Index: /tags/icedtea-web/beta/AUTHORS
===================================================================
--- /tags/icedtea-web/beta/AUTHORS	(revision 403)
+++ /tags/icedtea-web/beta/AUTHORS	(revision 403)
@@ -0,0 +1,23 @@
+The following people have made contibutions to this project.
+Please keep this list in alphabetical order.
+
+Lillian Angel <langel@redhat.com>
+Deepak Bhole <dbhole@redhat.com>
+Ricardo MartÃ­n Camarero <rickyepoderi@yahoo.es>
+Thomas Fitzsimmons <fitzsim@redhat.com>
+Mark Greenwood <mark@dcs.shef.ac.uk>
+Andrew John Hughes <gnu_andrew@member.fsf.org, ahughes@redhat.com>
+Matthias Klose <doko@ubuntu.com>
+Francis Kung <fkung@redhat.com>
+DJ Lucas <dj@lucasit.com>
+Omair Majid <omajid@redhat.com>
+Jon A. Maxwell <jmaxwell@users.sourceforge.net>
+Andrew Su <asu@redhat.com>
+Joshua Sumali <jsumali@redhat.com>
+Mark Wielaard <mark@klomp.org>
+Man Lung Wong <mwong@redhat.com>
+
+This project also includes code from the following projects:
+
+OpenJDK <http://openjdk.java.net/>
+Netx <http://jnlp.sourceforge.net/netx/>
Index: /tags/icedtea-web/beta/CHANGES.OS2
===================================================================
--- /tags/icedtea-web/beta/CHANGES.OS2	(revision 403)
+++ /tags/icedtea-web/beta/CHANGES.OS2	(revision 403)
@@ -0,0 +1,9 @@
+This document contains a brief list of the most important OS/2-specific changes
+in the IcedTea-Web product from release to release.
+
+
+CHANGES
+
+1.1.2 Beta (2012-07-21)
+
+  - First public release.
Index: /tags/icedtea-web/beta/COPYING
===================================================================
--- /tags/icedtea-web/beta/COPYING	(revision 403)
+++ /tags/icedtea-web/beta/COPYING	(revision 403)
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /tags/icedtea-web/beta/ChangeLog
===================================================================
--- /tags/icedtea-web/beta/ChangeLog	(revision 403)
+++ /tags/icedtea-web/beta/ChangeLog	(revision 403)
@@ -0,0 +1,3483 @@
+2011-08-31  Deepak Bhole <dbhole@redhat.com>
+
+	* NEWS: Prepare for 1.1.2
+	* configure.ac: Same
+
+2011-08-29  Deepak Bhole <dbhole@redhat.com>
+
+	RH734081: Javaws cannot use proxy settings from Firefox
+	Based on patch from Lukas Zachar <lzachar at redhat dot com>
+	* netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java
+	(find): Only process Profile sections. Do not throw an exception if a
+	Default= line is not found since it is not guaranteed to exist.
+
+2011-08-24  Deepak Bhole <dbhole@redhat.com>
+
+	RH718693: MindTerm SSH Applet doesn't work
+	* plugin/icedteanp/java/netscape/security/PrivilegeManager.java: New
+	file. Stub class, not needed with IcedTea-Web.
+
+2011-08-23  Deepak Bhole <dbhole@redhat.com>
+
+	PR769: IcedTea-Web plugin does not work with some ssl sites with OpenJDK7
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
+	(checkServerTrusted): Account for a null hostname that the
+	overloaded implementation may pass.
+
+2011-08-23  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am: Remove JRE. Replace uses with SYSTEM_JRE_DIR instead. Also
+	replace uses of SYSTEM_JDK_DIR/jre with SYSTEM_JRE_DIR.
+	* acinclude.m4
+	(IT_CHECK_FOR_JRE): New macro.
+	(IT_FIND_JAVA): Require IT_CHECK_FOR_JRE. Use java binary from within the
+	JRE.
+
+2011-08-03  Deepak Bhole <dbhole@redhat.com>
+
+	PR768: Signed applets/Web Start apps don't work with OpenJDK7 and up
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java (verifyJar): Put entry in
+	cert hashtable only if the entry is expected to be signed.
+
+2011-07-21  Deepak Bhole <dbhole@redhat.com>
+
+	PR749: sun.applet.PluginStreamHandler#handleMessage(String) really slow
+	Patch from: Ricardo MartÃ­n Camarero (Ricky) <rickyepoderi at yahoo dot es>
+	* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java
+	(readPair): New function.
+	(handleMessage): Use readPair to incrementally tokenize message, rather
+	than using String.split().
+
+2011-07-20  Deepak Bhole <dbhole@redhat.com>
+
+	* configure.ac: Prepare for 1.1.2
+	* NEWS: Same
+
+2011-07-15  Deepak Bhole <dbhole@redhat.com>
+
+	* configure.ac: Prepare to release 1.1.1
+	* NEWS: Same
+
+2011-07-14  Omair Majid  <omajid@redhat.com>
+
+	RH718170, CVE-2011-2514: Java Web Start security warning dialog
+	manipulation
+	* netx/net/sourceforge/jnlp/services/XExtendedService.java
+	(openFile): Create XContents based on a copy of the File object to prevent
+	overloaded File classes from mangling the name.
+	(XFileContents): Create a separate copy of File object for local use.
+
+2011-07-14  Omair Majid  <omajid@redhat.com>
+
+	RH718164, CVE-2011-2513: Home directory path disclosure to untrusted
+	applications
+	* netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java: New file.
+	* netx/net/sourceforge/jnlp/util/UrlUtils.java: New file.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	jarLocationSecurityMap now contains originating urls, not cache urls.
+	(initializeResources): Add remote url to map instead of local url.
+	(activateJars): Add remote url to the classloader's urls. Add mapping for
+	remote to local url. Put remote url in jarLocationSecurityMap.
+	(loadClass): Add remote url to the classloader's urls. Add mapping for
+	remote to local url.
+	(getCodeSourceSecurity): Update javadoc to note that the url must be
+	remote.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Set the callback for URLJarFile.
+
+2011-06-14  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java:
+	(ControlPanel): Removed line that prevents resizing.
+	(createMainSettingsPanel): Detect the minimum size of panels instead
+	of fixed size.
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	(addComponents): Changed to update size when tool is being resized.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	addComponents): Changed to a layout that will resize itself.
+
+2011-06-08  Deepak Bhole <dbhole@redhat.com>
+
+	* configure.ac: Prepare for 1.1.1
+	* NEWS: Same
+
+2011-06-08  Deepak Bhole <dbhole@redhat.com>
+
+	* configure.ac: Update for release.
+	* NEWS: Update for release.
+
+2011-06-08  Deepak Bhole <dbhole@redhat.com>
+
+	* NEWS: Remove security update notes from NEWS as they are not "New"
+
+2011-06-08  Deepak Bhole <dbhole@redhat.com>
+
+	PR721: IcedTeaPlugin.so cannot run g_main_context_iteration on a different
+	thread unless a different GMainContext *context is used
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
+	(postAndWaitForResponse): Added logic for tracking when the processor is
+	running from a plugin main thread, and logic to process main thread
+	specific messages queued thereafter until function exit.
+	* plugin/icedteanp/IcedTeaNPPlugin.cc:
+	(itnp_plugin_thread_id): New variable. Tracks plugin main thread ID.
+	(pluginAsyncCallMutex): New variable. Mutex to lock async call queue.
+	(NP_Initialize): Initialize the itnp_plugin_thread_id variable and make
+	ithe make pluginAsyncCallMutex recursive.
+	(NP_Shutdown): Destroy pluginAsyncCallMutex.
+	* plugin/icedteanp/IcedTeaNPPlugin.h:
+	(CHROMIUM_WORKAROUND): Remove macro.
+	(itnp_plugin_thread_id): New variable. Tracks plugin main thread ID.
+	(pluginAsyncCallMutex): New variable. Mutex to lock async call queue.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(eval): Remove chromium workaround.
+	(call): Same.
+	(sendString): Same.
+	(setMember): Same.
+	(sendMember): Same.
+	(loadURL): Same.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.h: Moved
+	async_call_thread_data to IcedTeaPluginUtils.h.
+	* plugin/icedteanp/IcedTeaPluginUtils.cc
+	(pendingPluginThreadRequests): New variable. Queue to track events waiting
+	for async execution on plug-in thread.
+	(callAndWaitForResult): New function. Calls a method on plug-in thread and
+	waits for the execution to complete.
+	(postPluginThreadAsyncCall): New function. Posts a method call to the
+	async execution queue and calls NPN_PluginThreadAsynCall.
+	(processAsyncCallQueue): New function. Called from the plug-in thread,
+	this function empties the event queue of functions waiting for plug-in
+	thread execution.
+	* plugin/icedteanp/IcedTeaPluginUtils.h
+	(plugin_thread_call): New struct to hold async call data.
+	(async_call_thread_data): Struct moved from IcedTeaPluginRequestProcessor.
+	(processAsyncCallQueue): New function.
+	(postPluginThreadAsyncCall): Same.
+	(callAndWaitForResult): Same.
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.cc
+	(get_scriptable_java_object): Use
+	IcedTeaPluginUtilities::callAndWaitForResult to post async callback for
+	_createAndRetainJavaObject.
+
+2011-05-30  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	(downloadResource): Check whether file to be downloaded is current.
+
+2011-05-30  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java:
+	(properties): Removed property.
+	(addComponents): Removed checkbox.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties:
+	Removed translation string for DPLifeCycleExceptions.
+
+2011-05-27  Deepak Bhole <dbhole@redhat.com>
+
+	PR723: AccessControlException while downloading resource
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java
+	(Downloader): Make class private.
+	(Downloader::run): Call processResource via doPrivileged since
+	resources may get added at run time from application code via
+	JNLPClassLoader::addNewJar().
+
+2011-05-27  Deepak Bhole <dbhole@redhat.com>
+
+	PR735: Firefox 4 sometimes freezes if the applet calls showDocument()
+	* plugin/icedteanp/IcedTeaNPPlugin.cc (consume_message): Defer handling to
+	url load request to the queue processor.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(PluginRequestProcessor::newMessageOnBus): Handle new LoadURL command.
+	(PluginRequestProcessor::loadURL): New method. Loads the specified url in
+	the given target.
+	(queue_processor): Process the LoadURL command.
+	(_loadURL): New async callback function to handle LoadURL commands.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.h: Add _loadURL and
+	loadURL method declerations.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (showDocument):
+	Send the url load command in the standard "instance X reference Y
+	<command> <args>" format.
+
+2011-05-27  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(appletClose): Call dispose from the swing thread. Also, don't try to stop
+	the threadgroup.
+
+2011-05-27  Deepak Bhole <dbhole@redhat.com>
+
+	* Backed out 0256de6a4bf6
+
+2011-05-27  Omair Majid  <omajid@redhat.com>
+
+	* NEWS: Update.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(getClassPathsFromManifest): Check for possible nulls and empty strings.
+
+2011-05-26  Andrew Su  <asu@redhat.com>
+
+	* NEWS: Update.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(cleanCache): Split conditional for delete.
+
+2011-05-20  Andrew Su  <asu@redhat.com>
+
+	* NEWS: Update.
+
+2011-05-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java:
+	(CacheLRUWrapper): New constructor to create file.
+	(lock): Removed creation of file here.
+
+2011-05-10  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CachePane.java:
+	(addComponents):Created a new comparator for sorting by file size and
+	date.
+
+2011-05-02  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(appletClose): Do not try to stop threads, now that the loader is shared
+	and the thread group for applets on a page is identical. Call dispose from
+	invokeAndWait.
+	(appletSystemExit): Exit the VM when called.
+
+2011-04-28  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (javaws, itweb_settings): New variables.
+	(edit_launcher_script, all-local, install-exe-local)
+	(uninstall-local, clean-launchers, javaws.desktop)
+	(itweb-settings.desktop): Replace all uses of javaws and
+	itweb-settings with the new variables.
+	(launcher.build/javaws): Replace with ...
+	(launcher.build/$(javaws)): New target.
+	(launcher.build/itweb-settings): Replace with...
+	(launcher.build/$(itweb-settings)): New target. 
+
+2011-04-21  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaNPPlugin.cc (consume_message): Use
+	NPN_GetURLNotify (non-blocking) instead of NPN_GetURL (blocking) so that
+	the plugin is free to process additional requests.
+	* ChangeLog: Fixed spacing issues in previous entry.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CachePane.java:
+	(createButtonPanel): Changed to update the recently_used file to
+	reflect the deletion. Added method updateRecentlyUsed to anonymous
+	ActionListener class which will do the actual updating.
+
+2011-04-20  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Add new private
+	variable classpathsInManifest.
+	(activateJars): When adding jar index, also add Class-Path entries from the
+	Manifest file in the jar.
+	(loadClass): Search for jars specified in classpaths before looking for 
+	entries in jar index.
+	(addNewJar): New method refactored from loadClass. 
+
+2011-04-20  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(getApplication(Class[],int)): Renamed to ...
+	(getApplication(Thread,Class[],int)): New method. Check the thread's
+	context ClassLoader as well as parents of the classloader.
+	(getJnlpClassLoader): New method.
+	(getApplication, checkExit): Update to work with new method signatures.
+
+2011-04-20  Omair Majid  <omajid@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
+	(PluginAppletSecurityContext): Set the launch handler to the stdout/stderr
+	based one.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CachePane.java:
+	(generateData): Skip through the identifier for cached item.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CachePane.java:
+	(createButtonPanel): Added check to delete button for whether plugin
+	or javaws is not running before proceeding with delete.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(cleanCache): Added check for removing files that are over set max
+	limit.
+	(removeUntrackedDirectories): Removed method. Replaced by
+	removeSetOfDirectories.
+	(removeSetOfDirectories): New method. Removes a given set of
+	directories.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java:
+	(addComponents): Uncommented lines of code to reintroduce components
+	to handle setting cache size limit.
+
+2011-04-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(getCacheFile): Store lru after modifying.
+
+2011-04-18  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheEntry.java:
+	(markForDelete): New method. Adds an entry to info file specifying
+	that this file should be delete.
+	(lock): New method. Locks the info file.
+	(unlock): New method. Unlocks the info file.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(cacheDir, lruHandler, propertiesLockPool): New private static fields.
+	(clearCache): Changed to use static field.
+	(getCacheFile): Changed to call getCacheFileIfExist and
+	makeNewCacheFile where appropriate.
+	(getCacheFileIfExist): New method. Get the file of requested item.
+	(makeNewCacheFile): New method. Create a new location to store cache
+	file.
+	(pathToURLPath): New method. Convert the file path to the url path.
+	(cleanCache): New method. Search for redundant entries and remove
+	them.
+	(removeUntrackedDirectories): New method. Remove all untracked
+	directories.
+	(lockFile): New method. Locks the given property file.
+	(unlockFile): New method. Unlocks the property file if we locked
+	before.
+	* netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java: New class.
+	Provides wrappers for handling cache's LRU.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	(downloadResource): Ensure that we only allow downloading the
+	specified file once.
+	(initializeResource): Added creation of new location to store an
+	updated or new file.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	(JNLPClassLoader): Reordered the calls since we should check
+	permission after we have the files ready.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	(markNetxRunning): Added call to CacheUtil.cleanCache() when adding
+	shutdown hooks.
+	* netx/net/sourceforge/jnlp/util/FileUtils.java:
+	(getFileLock): New method.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java:
+	(getContentsAsReader): Changed call from using urlToPath to
+	getCacheFile, since the directories are no longer in that location.
+
+2011-04-18  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java:
+	Remove unused import.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	Add annotation to suppress warning.
+	(loadClass): Make synchronized.
+
+2010-04-14  Andrew John Hughes  <ahughes@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java,
+	(PluginAppletPanelFactory.createPanel(PluginStreamHandler,
+	int,long,int,int,URL,Hashtable)): Remove duplication of wait
+	for panel.isAlive().
+	(PluginAppletViewer.panelLock): New lock used to track panel
+	creation.
+	(PluginAppletViewer.panelLive): Condition queue for panel creation.
+	(PluginAppletViewer.appletsLock): New lock used to track additions
+	to the applets map.
+	(PluginAppletViewer.appletAdded): Condition queue for applet addition.
+	(PluginAppletViewer.statusLock): New lock for status changes.
+	(PluginAppletViewer.initComplete): Condition queue for initialisation
+	completion.
+	(PluginAppletViewer.framePanel(int,long,NetxPanel)):
+	Replace synchronized block with use of appletsLock and notification
+	on appletAdded condition queue.
+	(AppletEventListener.appletStateChanged(AppletEvent)): Signal the
+	panelLive condition queue that the panel is live.
+	(PluginAppletViewer.handleMessage(int,int,String)): Wait on appletAdded
+	condition queue for applet to be added to the applets map.
+	(PluginAppletViewer.updateStatus(Int,PAV_INIT_STATUS)): Signal when a
+	status change occurs using the initComplete condition queue.
+	(PluginAppletViewer.waitForAppletInit(NetxPanel)): Wait on the panelLive
+	condition queue until the panel is created.
+	(PluginAppletViewer.handleMessage(int,String)): Wait on the initComplete
+	condition queue until initialisation is complete.  Wait on the panelLive
+	signal until panel is created.
+	(waitTillTimeout(ReentrantLock,Condition,long)): Convert to use
+	ReentrantLock and Condition.  Add assertion to check the lock is held.
+	Avoid conversion between milliseconds and nanoseconds.
+
+2011-04-18  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(PluginAppletPanelFactory::createPanel): Make the NetxPanel variable
+	final. Resize frame to work around problem whereby AppletViewerPanel
+	doesn't always set the right size initially.
+
+2011-04-18  Deepak Bhole <dbhole@redhat.com>
+
+	RH691259: Midori sends a SIGSEGV with the IcedTea NP Plugin
+	* plugin/icedteanp/IcedTeaNPPlugin.cc (NP_Initialize): Rather than
+	returning immediately if already initialized, return after function tables
+	are reset.
+
+2010-04-11  Andrew John Hughes  <ahughes@redhat.com>
+
+	* configure.ac:
+	Check Gentoo install location for JUnit 4.
+
+2011-04-13  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (createPanel):
+	use Object.wait() to wait, rather than pariodic sleep.
+	(APPLET_TIMEOUT): Updated to be in nanoseconds.
+	(framePanel): Synchronize put and notify threads waiting on the applets
+	map instance.
+	(appletStateChanged): Notify all threads waiting on the panel that just
+	changed state.
+	(handleMessage): Use the new waitTillTimeout function to wait, rather than
+	periodically waking up. Improved timeout error string sent back.
+	(updateStatus): Synchronize put and notify all threads waiting on status
+	map.
+	(waitForAppletInit): Use the new waitTillTimeout function to wait, rather
+	than periodically waking up.
+	(waitTillTimeout): New function. For a given non-null object, waits until
+	the specified timeout, or, if an interrupt was thrown during wait, returns
+	immediately.
+
+2011-04-14  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	Remove unused imports, added various SuppressWarnings annotations.
+	(createPanel): Return NetxPanel from doPriviledged. Remove dead code.
+	(PluginParseRequest): Remove - unused.
+	(defaultSaveFile, label, statusMsgStream, requests, handle): Remove unused.
+	(panel): Make NetxPanel.
+	(identifier, appletPanels): Privatize.
+	(appletPanels): Change type to NetxPanel.
+	(applets, status): Use ConcurrentHashMaps.
+	(framePanel, PluginAppletViewer): Remove unused PrintStream argument.
+	(forceredraw): Remove - unused.
+	(getApplets): Use generics.
+	(appletClose): Fix style to match our convention.
+	(destroyApplet): Use pav instead of calling get many times.
+	(splitSeparator): Remove. Replace uses by String.split().
+
+2011-04-13  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheDirectory.java:
+	Added final modifier to class declaration.
+	(CacheDirectory): New private constructor.
+
+2011-04-12  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(applets, status): Make concurrent.
+	(PluginAppletViewer): Synchronize appletPanels addElement.
+	(destroyApplet): Remove applets.containsKey because it and the
+	get that followed it were not atomic.
+	(appletPanels): Privatize.
+	(getApplet, getApplets): Synchronize iteration.
+
+2011-04-08  Omair Majid  <omajid@redhat.com>
+
+	* README: Update to add notes on rhino and junit.
+
+2011-04-07  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(constructor): Make window close event call destroy applet which can be
+	safely called multiple times, unlike appletClose.
+
+2011-04-06  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java:
+	(addComponents): Changed all port fields to use document which
+	prevents input of non-valid port numbers.
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	(addComponents): likewise.
+	(getPortNumberDocument): New method.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties:
+	Added CPInvalidPort and CPInvalidPortTitle.
+
+2011-04-05  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java:
+	Replaced every instance of PluginDebug.debug(a + b + c...)
+	with PluginDebug.debug(a, b, c...).
+
+2011-04-05  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	Remove unused imports, add import.
+	(downloadOptions): Make ConcurrentHashMap.
+
+2011-04-05  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(plugin_start_appletviewer): Replace hardcoded indices
+	with a variable; roll up free calls in a loop; fix whitespace;
+	set classpath to ICEDTEA_WEB_JRE/lib/rt.jar.
+	* launcher/javaws.in:
+	Set class path to JRE/lib/rt.jar.
+	* Makefile.am:
+	Replace @JRE@ with $(JRE) in edit_launcher_script.
+
+2011-04-01  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginDebug.java: 
+	(debug): Use StringBuilder to build the string.
+
+2011-03-31  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java: Add parserSettings and extra.
+	(setParserSettings): New method.
+	(setInformationToMerge): New method.
+	(launch(JNLPFile,Container)): Call mergeExtraInformation.
+	(launch(URL,boolean)): New method.
+	(mergeExtraInformation): New method.
+	(addProperties, addParameters, addArguments): Moved here from Boot.java
+	(fromUrl): New method.
+	* netx/net/sourceforge/jnlp/ParserSettings.java: New file.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Remove BArgNA,
+	BParamNA.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java
+	(run): Do not parse JNLP file. Pass ParserSettings and other command line
+	additions to launcher.
+	(getFile): Rename to...
+	(getFileLocation): New method.
+	(addProperties, addParameters, addArguments): Move to Launcher.java.	
+
+2011-03-31  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java:
+	Fix comments, remove unused imports.
+	(equals): Remove. It was breaking the reflexivity in the
+	equals contract.
+
+2011-03-31  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java:
+	Add citation of Effective Java, 2nd edition.
+
+2011-03-31  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
+	(store): Make private and remove fixme to make private.
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java
+	(PluginObjectStore): Make it a singleton using enum.
+	(objects, counts, identifiers, lock, wrapped, nextUniqueIdentifier,
+	 checkNeg): Made instance methods/members.
+	(getInstance): New static method.
+
+2011-03-31  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java
+	* plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java
+	* plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	* plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java
+	* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java
+	* plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java
+	* plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java
+	* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java
+	* plugin/icedteanp/java/sun/applet/RequestQueue.java
+	* plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java:
+	Change all instances of PluginDebug.debug(arg1 + arg2 + ...)
+	to PluginDebug.debug(arg1, arg2, ...).
+	* plugin/icedteanp/java/sun/applet/PluginDebug.java:
+	Change debug from "void debug(String)" to "void debug(Object...)". 
+
+2011-03-31  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java
+	(wrapped, lock): New static variables.
+	(getNextID, checkNeg): New functions.
+	(reference): Using getNextID and synchronized.
+	(dump): Improve iteration and synchronized.
+	(unreference, getObject, getIdentifier, contains(Object),
+	contains(int)): Synchronized.
+
+2011-03-31  Omair Majid  <omajid@redhat.com>
+
+	Add unit tests for the parser
+	* Makefile.am: Add TESTS_DIR,TESTS_SRCDIR, NETX_UNIT_TEST_DIR,
+	and NETX_UNIT_TEST_SRCDIR, JUNIT_RUNNER_DIR, JUNIT_RUNNER_SRCDIR, and
+	JUNIT_RUNNER_JAR. Conditionally define RHINO_TESTS and UNIT_TESTS.
+	(clean-local): Use RHINO_TESTS and UNIT_TESTS.
+	(clean-tests): Depend on clean-netx-tests. Delete directory.
+	(junit-runner-source-files.txt, $(JUNIT_RUNNER_JAR)),
+	(next-unit-tests-sources-files.txt stamps/netx-unit-tests-compile.stamp),
+	(run-netx-unit-tests, clean-netx-tests, clean-junit-runner)
+	(clean-netx-unit-tests): New targets.
+	* configure.ac: Add new optional dependency on junit.
+	* tests/junit-runner/CommandLine.java,
+	* tests/junit-runner/LessVerboseTextListener.java,
+	* tests/junit-runner/README,
+	* tests/netx/unit/net/sourceforge/jnlp/ParserBasicTests.java,
+	* tests/netx/unit/net/sourceforge/jnlp/ParserCornerCaseTests.java,
+	* tests/netx/unit/net/sourceforge/jnlp/ParserMalformedXmlTests.java,
+	* tests/netx/unit/net/sourceforge/jnlp/basic.jnlp: New files.
+
+2011-03-30  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am: Fix comment explaining reasons for setting
+	JDK_UPDATE_VERSION.
+
+2011-03-30  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Fix typo in
+	RCantRename.
+
+2011-03-30  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am: Document reason for using bootclasspath.
+
+2011-03-30  Omair Majid  <omajid@redhat.com>
+
+	* netx/javaws.1: Fix FILES section to point to
+	~/.icedtea/deployment.properties.
+
+2011-03-30  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/LaunchHandler.java
+	(launchInitialized, launchStarting): New methods.
+	* netx/net/sourceforge/jnlp/DefaultLaunchHandler.java
+	(launchInitialized, launchStarting): New methods. No-op
+	implementation.
+	(printMessage): Make it static.
+	* netx/net/sourceforge/jnlp/GuiLaunchHandler.java: New file.
+	(launchCompleted, launchError, launchStarting, launchInitialized),
+	(launchWarning, validationError): New methods.
+	* netx/net/sourceforge/jnlp/Launcher.java (launchApplication):
+	Invoke handler.launchInitialized and handler.launchStarting instead
+	of showing a splash screen directly.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	ButShowDetails, ButHideDetails and Error.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java (run): Do not exit on
+	error.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Set handler to GuiLaunchHandler if not running in
+	headless mode.
+	* netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java: New
+	file.
+	(exceptionToString, show): New methods.
+
+2011-03-29  Denis Lila <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java
+	(getInformation): Remove redundant if.
+
+2010-03-29  Andrew John Hughes  <ahughes@redhat.com>
+
+	* plugin/docs/npplugin_liveconnect_design.html:
+	Replace binary PDF documentation with editable HTML.
+	* plugin/docs/npplugin_liveconnect_design.pdf: Removed.
+
+2011-03-28  Omair Majid  <omajid@redhat.com>
+
+	* launcher/javaws.in: Split out -J arguments and pass it to the JVM.
+
+2011-03-28  Deepak Bhole <dbhole@redhat.com>
+
+	* netx/net/sourceforge/jnlp/PluginBridge.java
+	(PluginBridge): Construct unique key based on a combination of
+	codebase, cache_archive, java_archive, and archive. This automatically
+	ensures are loaders are shared only when appropriate.
+
+2011-03-25  Denis Lila <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/PluginBridge.java
+	(codeBaseLookup): new member and getter for it.
+	(PluginBridge): set codeBaseLookup.
+	* netx/net/sourceforge/jnlp/Launcher.java:
+	(createApplet, createAppletObject): call enableCodeBase() if and
+	only if the enableCodeBase argument is true.
+
+2011-03-24  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add $(top_srcdir)/tests.
+
+2011-03-24  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	RBrowserLocationPromptTitle, RBrowserLocationPromptMessage and
+	RBrowserLocationPromptMessageWithReason.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(isWindows): New method. Moved from XBasicService.
+	(isUnix): New method.
+	* netx/net/sourceforge/jnlp/services/XBasicService
+	(initialize): Call initializeBrowserCommand.
+	(initializeBrowserCommand): New method.
+	(posixCommandExists): New method.
+	(isWindows): Moved to JNLPRuntime.
+
+2011-03-23  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(findResource, findResources): New functions. Return nothing
+	if name.startsWith("META-INF"). Otherwise delegate to superclass.
+
+2011-03-21  Matthias Klose  <doko@ubuntu.com>
+
+	* launcher/itweb-settings.in: Use /bin/sh as interpreter.
+	* launcher/javaws.in: Likewise.
+
+2011-03-14  Andrew Su <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	(markNetxRunning): Handle case for when shared locks are not allowed
+	on the system.
+
+2011-03-14  Andrew Su <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java:
+	(fileLock): Removed private static field.
+	(launch): Mark NetX as running before launching apps.
+	(launchApplication): Removed call to markNetxRunning() and removed
+	shutdown hook for calling markNetxStopped().
+	(markNetxRunning): Removed method.
+	(markNetxStopped): Removed method.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(okToClearCache): Removed closing of channel.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	(fileLock): New private static field.
+	(markNetxRunning): New method to indicate NetX is running.
+	(markNetxStopped): New method to indicate NetX has stopped.
+
+2011-03-16  Jiri Vanek  <jvanek@redhat.com>
+
+	* extras/net/sourceforge/jnlp/about/Main.java: removed hyperlinkUpdate 
+	and HyperlinkListener, as it can not work without all-permissions. 
+	Also all createAndShowGUI was shorten for call from  
+	net.sourceforge.jnlp package. Html resources were redirected to javaws
+	* netx/net/sourceforge/jnlp/resources/about.jnlp: removed 
+	<all-permissions>
+
+2011-03-16  Jiri Vanek  <jvanek@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/Boot.java: getAboutFile changed to 
+	return path to local about.jnlp instead to  inner-from-jar
+	* extras/net/sourceforge/jnlp/: refactored to 
+	extras/net/sourceforge/javaws/, as /net/sourceforge/jnlp/ package 
+	must be run with all-permissions.
+	* netx/net/sourceforge/jnlp/resources/about.jnlp: codebase changed 
+	to "."
+
+
+2011-03-15  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(markNetxRunning): Throw exception if directories can't be created.
+	* netx/net/sourceforge/jnlp/cache/CacheDirectory.java
+	(cleanParent): Print error message if file can't be deleted.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java
+	(getCacheFile): Throw exception if directories can't be created.
+	* netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java
+	(save): Throw exception if directories can't be created.
+	* netx/net/sourceforge/jnlp/controlpanel/CachePane.java
+	(createButtonPanel): Print error message if file can't be deleted.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties
+	Added messages.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initializeStreams): Throw exception if directories can't be created.
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java
+	(create, get): Throw exception if directories can't be created.
+	(delete): Print error message if file can't be deleted.
+	* netx/net/sourceforge/jnlp/util/FileUtils.java
+	(createRestrictedFile): Throw exception if file permissions can't be
+	changed.
+	(createParentDir, deleteWithErrMesg): new functions.
+
+2011-03-15  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (LAUNCHER_BOOTCLASSPATH, PLUGIN_BOOTCLASSPATH)
+	(javaws.desktop, itweb-settings.desktop): Remove DESTDIR.
+
+2011-03-10  Mark Wielaard  <mark@klomp.org>
+
+	* tests/netx/pac/pac-funcs-test.js (testIsResolvable):
+	Change single host name icedtea to NotIcedTeaHost
+	to make sure it really isn't resolvable.
+
+2011-03-10  Omair Majid  <omajid@redhat.com>
+
+	Replace native launchers with shell scripts
+	* NEWS: Update.
+	* Makefile.am
+	(LAUNCHER_BOOTCLASSPATH): Remove leading -J.
+	(LAUNCHER_SRCDIR),
+	(LAUNCHER_OBJECTS),
+	(NETX_LAUNCHER_OBJECTS),
+	(CONTROLPANEL_LAUNCHER_OBJECTS),
+	(LAUNCHER_FLAGS),
+	(LAUNCHER_LINK): Remove.
+	(edit_launcher_script): New function.
+	(all-local): Depend on new launcher targets.
+	(clean-local): Depend on clean-launchers.
+	(.PHONY): Add clean-launchers.
+	(install-exec-local): Use new launcher paths.
+	(clean-launchers): New target.
+	($(NETX_DIR)/launcher/%.o),
+	($(NETX_DIR)/launcher/controlpanel/%.o),
+	($(NETX_DIR)/launcher/javaws),
+	($(NETX_DIR)/launcher/controlpanel/itweb-settings): Remove.
+	(launcher.build/javaws): New launcher.
+	(launcher.build/itweb-settings): Likewise.
+	* launcher/itweb-settings.in,
+	* launcher/javaws.in: New file.
+	* netx/net/sourceforge/jnlp/Launcher.java (launchExternal),
+	* netx/net/sourceforge/jnlp/controlpanel/CommandLine.java (CommandLine):
+	Use new system properties to find paths and program names.
+
+2011-03-10  Omair Majid  <omajid@redhat.com>
+
+	* acinclude.m4 (IT_FIND_RHINO_JAR): Remove.
+
+2011-03-10  Omair Majid  <omajid@redhat.com>
+
+	* tests/netx/pac/pac-funcs-test.js
+	(main): Make test summary output more jtreg-like.
+	(runTests): Change test output format to be more jtreg-like.
+
+2011-03-09  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Parser.java
+	(getJAR): Remove unused variable.
+	* netx/net/sourceforge/jnlp/cache/Resource.java
+	(connection): Remove unused member.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java
+	(lock): Initialize to Object() instead of Integer(0). Also,
+	make final.
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
+	(SettingsPanel): Make static class.
+	* netx/net/sourceforge/jnlp/event/ApplicationEvent.java
+	(application): Make member transient.
+	* netx/net/sourceforge/jnlp/event/DownloadEvent.java
+	(tracker, resource): Make members transient.
+	* netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java
+	(appletInstance): Remove unused member.
+	(parameters): Add parameters to its type (a map).
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	Remove unused import.
+	(getNativeDir): Improve random int computation.
+	(CodeBaseClassLoader): Make it a static class.
+	* netx/net/sourceforge/jnlp/JNLPFile.java
+	(JNLPFile): Improve random positive int computation.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(activeApplication): Remove unused member.
+	(checkExit): Remove dead code resulting from activeApplication
+	always being null.
+	* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java
+	Remove unused import.
+	(addComponents): Remove unused variable.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java
+	(SetValueHandler): Make it a static class.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(CertificateType): Make it a static class.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java
+	(checkAccess): Replace new Boolean with Boolean.valueOf.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java
+	(storeHash): Remove unused member.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java
+	(getContentsAsReader): Remove unused variable pathToJavaws.
+
+2011-03-09  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java:
+	(addComponents): Fix typo.
+
+2011-03-08  Omair Majid  <omajid@redhat.com>
+
+	* acinclude.m4 (IT_FIND_OPTIONAL_JAR): New macro.
+	* configure.ac: Do not call IT_FIND_RHINO. Use IT_FIND_OPTIONAL_JAR
+	instead.
+
+2011-03-08  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
+	(getProxies): Add result to cache, not cachedResult.
+
+2011-03-08  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java
+	(find): Close input stream.
+	* netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java
+	(parse): Close input stream.
+	* netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
+	(getPacContents, getHelperFunctionContents): Close input stream.
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java
+	(CheckBoxListener.actionPerformed): Close output stream.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(ImportButtonListener.actionPerformed): Close output stream.
+
+2011-03-08  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/util/PropertiesFile.java:
+	(load): Closed streams after opening them.
+	(store): Likewise.
+
+2011-03-08  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(getRequestIdentifier): Fix race condition by synchronizing
+	on mutex.
+	(requestIdentityCounter): Now a long.
+
+2011-03-07  Omair Majid  <omajid@redhat.com>
+
+	* acinclude.m4 (IT_FIND_RHINO_JAR): Set RHINO_AVAILABLE to true or false
+	appropriately.
+	* build.properties.in: New file.
+	* jrunscript.in: New file.
+	* configure.ac: Add build.properties and jrunscript to AC_CONFIG_FILES.
+	* Makefile.am
+	(.PHONY): Remove clean-jrunscript.
+	(build.properties): Remove target.
+	(stamps/netx.stamp): Remove dependency on build.properties.
+	(clean-netx): Do not delete build.properties.
+	(jrunscript): Remove target.
+	(check-pac-functions): Remove dependency on jrunscript.
+	(clean-tests): Remove dependency on clean-jrunscript.
+	(clean-jrunscript): Remove target.
+
+2011-03-07  Omair Majid  <omajid@redhat.com>
+
+	* NEWS: Update.
+	* acinclude.m4 (IT_OBTAIN_HG_REVISIONS): Use hg id instead of hg tip.
+
+2011-03-07  Omair Majid  <omajid@redhat.com>
+
+	* plugin/icedteanp/IcedTeaNPPlugin.cc: Add plugin_debug_suspend.
+	(plugin_start_appletviewer): If plugin_debug_suspend is true, start jvm in
+	suspend mode.
+
+2011-03-07  Omair Majid  <omajid@redhat.com>
+
+	* NEWS: Update.
+	* Makefile.am
+	(RHINO_RUNTIME): Define to point to rhino jars, or empty.
+	(RUNTIME, LAUNCHER_BOOTCLASSPATH, PLUGIN_BOOTCLASSPATH): Include
+	RHINO_RUNTIME.
+	(PHONY): Add check-pac-functions, clean-jrunscript and clean-tests.
+	(check-local): New target. Depends on check-pac-functions.
+	(check-pac-functions): New target.
+	(jrunscript): New target.
+	(clean-tests): New target.
+	(clean-jrunscript): New target.
+	(netx-source-files.txt): Remove rhino related files if not building with
+	rhino.
+	(build.properties): New target.
+	(stamps/netx.stamp): Depend on build.properties and copy new files to
+	build location.
+	(clean-netx): Remove build.properties.
+	(stamps/bootstrap-directory.stamp): Add java to bootstrap programs.
+	* acinclude.m4 (IT_FIND_RHINO_JAR): New macro.
+	* configure.ac: Invoke IT_FIND_RHINO_JAR.
+	* netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java: Add
+	browserProxyAutoConfig.
+	(initFromBrowserConfig): Initialize browserProxyAutoConfig if needed.
+	(getFromBrowserPAC): Use browserProxyAutoConfig to find proxies.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Replace
+	RPRoxyPacNotImplemented with RPRoxyPacNotSupported.
+	* netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: Add
+	pacEvaluator.
+	(parseConfiguration): Initialize pacEvaluator if needed.
+	(getFromPAC): Use pacEvaulator to find proxies.
+	(getProxiesFromPacResult): New method. Converts a proxy string to a list
+	or proxies.
+	* netx/net/sourceforge/jnlp/runtime/PacEvaluator.java: New file. Defines a
+	Java interface for a PAC evaluator.
+	* netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java: New file. Dummy
+	implementation of a PAC evaluator.
+	* netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java: New file.
+	A rhino-based PAC evaluator.
+	* netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java: New file. A
+	factory for creating the right PAC evaulator.
+	* netx/net/sourceforge/jnlp/runtime/pac-funcs.js: New file. Defines helper
+	functions needed while evaluating PAC files.
+	* tests/netx/pac/pac-funcs-test.js: New file. Tests the PAC helper
+	functions.
+
+2011-03-07  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java:
+	(prepopulateMethod) removed unused object o.
+	* plugin/icedteanp/java/sun/applet/PluginCallRequest.java:
+	Made all the members private.
+	* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java:
+	Removed unused imports.
+	(MAX_PARALLEL_INITS, MAX_WORKERS, PRIORITY_WORKERS, readQueue,
+	 workers, streamHandler, consumerThread,
+	 registerPriorityWait(String), unRegisterPriorityWait(String)):
+	 made private.
+	(initWorkers, as, processedIds, unRegisterPriorityWait(Long),
+	 addToInitWorkers): removed - unused.
+	(getPriorityStrIfPriority): made static; replaced while with for-each.
+	(notifyWorkerIsFree): removed synchronized section - useless.
+	(ConsumerThread.run): removed call to addToInitWorkers.
+	* plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java:
+	Removed explicit member initializations to the default values; fixed typo.
+	(PluginMessageHandlerWorker): Removed SecurityManager argument - unused.
+	* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java:
+	Removed unused imports.
+	(consumer, shuttingDown): made private.
+	(pav, writeQueue, getMessage, messageAvailable): removed - unused.
+	(PluginStreamHandler): removed pav initialization.
+	* plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java:
+	Removed FIXME comment.
+
+2011-03-07  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java:
+	(getResourcesDescs): added comment.
+	(getDownloadOptionsForJar): removed commented out code.
+	* netx/net/sourceforge/jnlp/PluginBridge.java
+	(getResourcesDescs): added comment.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java
+	(downloadResource): added comment.
+
+2011-03-04  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java:
+	(getDownloadOptionsForJar): Moved here from JNLPClassLoader.java.
+	* netx/net/sourceforge/jnlp/PluginBridge.java
+	(usePack, useVersion): added.
+	(PluginBridge): initializing usePack and useVersion.
+	(getDownloadOptionsForJar): return the download options.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(getDownloadOptionsForJar): logic moved to JNLPFile.java and its
+	subclasses. Now just calling file.getDownloadOptionsForJar.
+	* NEWS: Updated with fix of PR658.
+
+2011-03-04  Denis Lila  <dlila@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java
+	(downloadResource): changed the order in which pack200+gz compression
+	and gzip compression are checked.
+	* netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java
+	(getUrl): if usePack is true, append ".pack.gz" to the file name,
+	instead of replacing ".jar" with ".pack.gz".
+
+2011-03-04  Deepak Bhole <dbhole@redhat.com>
+
+	* NEWS: Updated.
+	* netx/net/sourceforge/jnlp/PluginBridge.java (PluginBridge): Use
+	documentbase as a uniquekey so that the classloader may be shared by
+	applets from the same page.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Added new
+	CodeBaseClassLoader class to load codebase (from path instead of a file)
+	classes.
+	(getInstance): Try to match file locations only for Web Start apps. For
+	plugin, merge the new loader into current one.
+	(enableCodeBase): Use the new addToCodeBaseLoader method.
+	(findLoadedClassAll): Search the codebase loader if the class was not
+	found in the file loaders.
+	(findClass): Likewise.
+	(getResource): Likewise.
+	(findResources): Likewise.
+	(merge): Merge codebase loaders.
+	(addToCodeBaseLoader): New method. Adds a given url to the codebase loader
+	if it is a path.
+	(CodeBaseClassLoader): New inner class. Extends URLClassLoader to expose
+	its protected methods like addURL.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(getApplication): Accomodate the fact that the classloader for a class may
+	be a CodeBaseClassLoader.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (run):
+	Likewise.
+
+2011-03-03  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(plugin_send_initialization_message): New method. Sends initialization
+	information to the Java side.
+	(ITNP_SetWindow): Call the new plugin_send_initialization_message
+	function.
+	(get_scriptable_object): Same.
+
+2011-03-03  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(eval): Proceed with _eval only if instance is valid.
+	(call): Proceed with _call only if instance is valid. Moved declaration
+	of result_variant_jniid, result_variant args_array and thread_data to 
+	the top.
+	(sendString): Proceed with _getString only if instance is valid. Remove
+	thread count incrementer.
+	(setMember): Proceed with _setMember only if instance is valid. Remove
+	thread count incrementer.
+	(sendMember): Proceed with _getMember only if instance is valid.
+
+2011-03-03  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(PluginRequestProcessor): Remove initialization of tc_mutex
+	(~PluginRequestProcessor): Remove destruction of tc_mutex
+	(sendString): Removed thread count incrementer code.
+	(setMember): Same.
+	(sendMember): Same.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.h: Removed tc_mutex and
+	thread_count variables. 
+
+2011-03-02  Omair Majid  <omajid@redhat.com>
+
+	Fix PR612.
+	* NEWS: Update with fix.
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Add PropertyPermissions for
+	browser and browser.* to sandboxPermissions.
+
+2011-03-02  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CommandLine.java
+	(handleSetCommand): Fix warning message.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	CLWarningUnknownProperty.
+
+2011-03-01  Omair Majid  <omajid@redhat.com>
+
+	 * netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java (isSystemJar): Check
+	 for nulls.
+
+2011-03-01  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
+	(createMainSettingsPanel): Commented out unimplemented feature.
+	* netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java
+	(addComponents): Commented out unimplemented feature.
+
+2011-02-28  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/CommandLine.java
+	(printResetHelp): Indicate that "all" is a valid argument.
+	(handleResetCommand): Deal with "all" instead of a property name by
+	reseting all properties.
+
+2011-02-28  Denis Lila  <dlila@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginMain.java
+	(redirectStreams, streamHandler, securityContext) make them local.
+	(theVersion): make it private.
+	(PluginMain): make it private. Empty the body.
+	(main): Do all the work that used to be in PluginMain.
+	(connect): make it static, and now it returns a PluginStreamHandler
+	instead of setting a static variable.
+	(messageAvailable, getMessage): Remove.
+
+2011-02-28  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add Password,
+	Username and SAuthenticationPrompt.
+	* netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java
+	(getPasswordAuthentication): Show password prompt using the secure thread.
+	* netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java
+	(PasswordAuthenticationPane): Initialize variables.
+	(initialize): For consistency, rename to..
+	(addComponents): New method. Set the appropriate return value when user
+	takes an action.
+	(askUser): Remove.
+	(main): Remove.
+	* netx/net/sourceforge/jnlp/security/SecurityDialog.java
+	(initDialog): Add extra case for AUTHENTICATION dialog type.
+	(installPanel): Likewise.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogs.java
+	(DialogType): Add AUTHENTICATION.
+	(showAuthenicationPrompt): New method. Shows a password authentication
+	prompt.
+
+2011-02-28  Omair Majid  <omajid@redhat.com>
+
+	Rename files
+	* netx/net/sourceforge/jnlp/security/PasswordAuthenticationDialog.java:
+	Rename to ...
+	* netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java: New
+	file.
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Rename
+	to...
+	* netx/net/sourceforge/jnlp/security/SecurityDialog.java: New file.
+	* netx/net/sourceforge/jnlp/security/SecurityWarning.java: Rename to...
+	* netx/net/sourceforge/jnlp/security/SecurityDialogs.java: New file.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java,
+	* netx/net/sourceforge/jnlp/security/AccessWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/AppletWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/CertsInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java,
+	* netx/net/sourceforge/jnlp/security/MoreInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java,
+	* netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java,
+	* netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java,
+	* netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java,
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java,
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java,
+	* netx/net/sourceforge/jnlp/services/XClipboardService.java,
+	* netx/net/sourceforge/jnlp/services/XExtendedService.java,
+	* netx/net/sourceforge/jnlp/services/XFileOpenService.java,
+	* netx/net/sourceforge/jnlp/services/XFileSaveService.java: Update class
+	names to the new classes.
+
+2011-02-25  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (stamps/netx-dist.stamp): Do not add extra files to
+	classes.jar.
+
+2011-02-25  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Manifest.mf: Remove unused file.
+
+2011-02-23  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am: Add missing slash to JRE.
+
+2011-02-23  Omair Majid  <omajid@redhat.com>
+
+	RH677772: NoSuchAlgorithmException using SSL/TLS in javaws
+	* NEWS: Update with bugfix.
+	* netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java: Add new field
+	jreExtDir.
+	(JNLPPolicy): Initialize jreExtDir.
+	(getPermissions): Grant AllPermissions if the CodeSourse is a system jar.
+	(isSystemJar): New method.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(checkPermission): Remove special casing of
+	SecurityPermission("putProviderProperty.SunJCE") and
+	SecurityPermission("accessClassInPackage.sun.security.internal.spec").
+	(inTrustedCallChain): Remove.
+
+2011-02-22  Omair Majid  <omajid@redhat.com>
+            Mark Greenwood <mark@dcs.shef.ac.uk>
+
+	Fix PR638
+	* NEWS: Update with fix.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java (loadClass): Throw
+	ClassNotFoundException instead of returning null.
+	* AUTHORS: Update.
+
+2011-02-22  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (uninstall-local): Fix typo in PACKAGE_NAME.
+
+2011-02-22  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	RNoAboutJnlp.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java: Remove NETX_ABOUT_FILE.
+	(getAboutFile): Look for about.jnlp using the classloader.
+	(getFile): Use localized error message string.
+
+2011-02-22  Omair Majid  <omajid@redhat.com>
+            DJ Lucas  <dj@lucasit.com>
+
+	* Makefile.am
+	(install-data-local): Use $(mandir) for man page dir.
+	(uninstall-local): Use $(mandir) for man page dir.
+	* AUTHORS: Update.
+
+2011-02-22  Omair Majid  <omajid@redhat.com>
+
+	Install icedtea-web into a FHS-compliant location
+	* Makefile.am: Add new vars JRE, LAUNCHER_BOOTCLASSPATH and
+	PLUGIN_BOOTCLASSPATH.
+	(install-exec-local): Install files to FHS-compliant location; do not
+	create links.
+	(install-data-local): Likewise.
+	(uninstall-local): Update file paths to delete.
+	($(PLUGIN_DIR)/%.o): Pass PLUGIN_BOOTCLASSPATH and ICEDTEA_WEB_JRE.
+	($(NETX_DIR)/launcher/%.o): Pass LAUNCHER_BOOTCLASSPATH and
+	ICEDTEA_WEB_JRE.
+	($(NETX_DIR)/launcher/controlpanel/%.o): Likewise.
+	* launcher/java_md.c
+	(GetIcedTeaWebJREPath): New method.
+	(CreateExecutionEnvironment): Call GetIcedTeaWebJREPath.
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(plugin_start_appletviewer): Add PLUGIN_BOOTCLASSPATH to the command.
+	(NP_Initialize): Use ICEDTEA_WEB_JRE to initialize filename.
+
+2011-02-18  Omair Majid  <omajid@redhat.com>
+
+	Remove pluginappletviewer binary
+	* Makefile.am
+	(ICEDTEAPLUGIN_TARGET): Remove dependency on pluginappletviewer.
+	(PLUGIN_LAUNCHER_OBJECTS): Remove.
+	(install-exec-local): Do not install pluginappletviewer.
+	(uninstall-local): Do not remove pluginappletviewer.
+	($(PLUGIN_DIR)/launcher/%.o): Remove.
+	($(PLUGIN_DIR)/launcher/pluginappletviewer): Remove.
+	(clean-IcedTeaPlugin): Dont clean plugin launcher files.
+
+2011-02-15  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/util/TimedHashMap.java: Do not extend HashMap
+	to provide a more type-safe and consistent interface. Use System.nanoTime
+	for a more monotonic clock.
+
+2011-02-15  Omair Majid  <omajid@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java
+	(TimedHashMap): Moved to...
+	* netx/net/sourceforge/jnlp/util/TimedHashMap.java: New file.
+
+2011-02-11  Omair Majid  <omajid@redhat.com>
+
+	RH677332, CVE-2011-0706: IcedTea multiple signers privilege escalation
+	* NEWS: Updated.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(initializeResources): Assign appropriate security descriptor based on
+	code signing.
+
+2011-02-11  Deepak Bhole <dbhole@redhat.com>
+
+	Fix S6983554, CVE-2010-4450: Launcher incorrect processing of empty
+	library path entries
+	* NEWS: Updated.
+	* launcher/java_md.c: Ignore empty LD_LIBRARY_PATH.
+
+2011-02-11  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/PluginBridge.java
+	(getResourcesDescs): New method implemented to override behaviour in
+	JNLPFile class.
+
+2011-02-11  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java
+	(getResourceDescs): Renamed to...
+	(getResourcesDescs): New method.
+	(getResourceDescs): Renamed to...
+	(getResourcesDescs): New method.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(getDownloadOptionsForJar): Call renamed method.
+
+2011-02-10  Omair Majid  <omajid@redhat.com>
+
+	Fix RH669942; Add support for packEnabled and versionEnabled.
+	* NEWS: Update with bugfix.
+	* netx/net/sourceforge/jnlp/DownloadOptions.java: New file.
+	* netx/net/sourceforge/jnlp/JNLPFile.java
+	(openURL): Use null for DownloadOptions.
+	(getResourceDescs): New method.
+	(getResourceDescs(Locale,String,String)): New method.
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(launchApplication): Add image to downloader with null DownloadOptions.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java
+	(getCachedResource):  Add resource with null DownloadOptions.
+	* netx/net/sourceforge/jnlp/cache/Resource.java: Add new field
+	downloadLocation.
+	(Resource): Initialize downloadLocation.
+	(getDownloadLocation): New method.
+	(setDownloadLocation): New method.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java: Add new field
+	downloadOptions.
+	(addResource(URL,Version,UpdatePolicy)): Renamed to...
+	(addResource(URL,Version,DownloadOptions,UpdatePolicy)): New method.
+	(downloadResource): Add support for explicit downloading of packed jars as
+	well as content-encoded packed jars.
+	(initializeResource): Invokde findBestUrl to find the best url. Set that
+	as the download location for the resource.
+	(getVersionedResourceURL): Remove.
+	(findBestUrl): New method. Use ResourceUrlCreator to get a list of all
+	possible urls that can be used to download this resource. Try them one by
+	one until one works and return that.
+	* netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java: New file.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(initializeResources): Add resource with appropriate download options.
+	(activateJars): Likewise.
+	(loadClass): Likewise.
+	(getDownloadOptionsForJar): New method.
+
+2011-02-10  Deepak Bhole <dbhole@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize):
+	Restrict access to net.sourceforge.jnlp.* classes by untrusted
+	classes.
+
+2011-02-09  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java
+	(addComponents): Fix the listener attached to the port field to update the
+	right config option.
+
+2011-02-08  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
+	(initFromBrowserConfig): Do not try to create a URL from null.
+	(getFromBrowser): Only print informational messages in debug mode.
+
+2011-02-01  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(activateJars): Add the nested jar to ResourceTracker. Use
+	JarSigner.verifyJars instead of JarSigner.verifyJar.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java
+	(verifyJar): Make private to indicate nothing should be using this
+	directly.
+
+2011-01-24 Deepak Bhole <dbhole@redhat.com>
+
+	RH672262, CVE-2011-0025: IcedTea jarfile signature verification bypass
+	* rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(initializeResources): Prompt user only if there is a single certificate
+	that signs all jars in the jnlp file, otherwise treat as unsigned.
+	* rt/net/sourceforge/jnlp/security/CertVerifier.java: Rename getCerts to
+	getCertPath and make it return a CertPath.
+	* rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Rename certs
+	variable to certPath and change its type to CertPath.
+	(buildTree): Use new certPath variable.
+	(populateTable): Same.
+	* rt/net/sourceforge/jnlp/security/HttpsCertVerifier.java: Rename getCerts
+	to getCertPath and make it return a CertPath.
+	* rt/net/sourceforge/jnlp/tools/JarSigner.java: Change type for certs
+	variable to be a hashmap that stores certs and the number of entries they
+	have signed.
+	(totalSignableEntries): New variable to track how many signable entries
+	have been encountered.
+	(getCerts): Updated method to return certs from new hashmap.
+	(isFullySignedByASingleCert): New method. Returns if there is a single
+	cert that signs all the entries in the jars specified in the jnlp file.
+	(verifyJars): Move verifiedJars and unverifiedJars out of the for loop so
+	that the data is not lost when the next jar is processed. After verifying
+	each jar, see if there is a single signer, and prompt the user if there is
+	such an untrusted signer.
+	(verifyJar): Increment totalSignableEntries for each signable entry
+	encountered and the count for each cert when it signs an entry. Move
+	checkTrustedCerts() out of the function into verifyJars(). 
+
+2011-01-28  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am: Move ICEDTEA_REV, ICEDTEA_PKG to acinclude.m4. Use
+	FULL_VERSION.
+	(stamps/netx-dist.stamp): Depend on netx.manifest. Use this file as the
+	jar file manifest.
+	* acinclude.m4 (IT_SET_VERSION): New macro. Defines FULL_VERSION.
+	* configure.ac: Add netx.manifest to AC_CONFIG_FILES. Invoke
+	IT_SET_VERSION.
+	* netx.manifest.in: New file.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java: Set name and version using
+	information from the manifest file.
+
+2011-01-27  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	RPRoxyPacNotImplemented, RProxyFirefoxNotFound, and
+	RProxyFirefoxOptionNotImplemented.
+	* netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: Make abstract.
+	(getFromBrowser): Remove implementation; make abstract.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Set BrowserAwareProxySelector as the proxy selector.
+	* netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java: New
+	file. This class extends JNLPProxySelector and searches the browser's
+	configuration to load additional proxy settings from.
+	* netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java: New
+	file. This class looks into the browser configration to find the
+	preferences file for the default firefox profile.
+	* netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java: New
+	file. Parses the browser's preferences and makes it available through a
+	simpler interface.
+
+2011-01-27  Omair Majid  <omajid@redhat.com>
+
+	* AUTHORS: Update to include Jon A Maxwell.
+	* extra/net/sourceforge/jnlp/about/resources/notes.html: Include everyone
+	from AUTHORS.
+
+2011-01-25  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/default.jnlp: Remove.
+
+2011-01-24  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java: Exit with error code
+	* netx/net/sourceforge/jnlp/NetxPanel.java: Likewise.
+
+2011-01-20  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/AppletLog.java: Restrict log files to
+	owner accessible only.
+
+2011-01-20  Andrew Su  <asu@redhat.com>
+
+	Removing dead/commented/unused code.
+	* plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java:
+	Removed unused imports.
+	* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java:
+	(getMatchingMethod): Removed unused variable.
+	(getMatchingConstructor): Removed unused variable.
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java:
+	Removed unused imports.
+	(Signature): Removed commented code.
+	(handleMessage): Removed commented code.
+	(getAccessControlContext): Remove commented code.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java:
+	(getCachedImage): Removed commented code.
+	(makeReader): Removed unused method.
+	(parse): Removed unused variables. Removed dead code.
+	* plugin/icedteanp/java/sun/applet/PluginCallRequest.java: Removed
+	unused imports.
+	* plugin/icedteanp/java/sun/applet/PluginDebug.java: Removed unused
+	imports.
+	* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java: Removed
+	unused imports.
+	(getReference): Removed unused method.
+	(isInInit): Removed unused method.
+	(dumpWorkerStatus): Removed unused method.
+	* plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java:
+	Removed unused variable.
+	(PluginMessageHandlerWorker): Removed unused variable.
+	(plugin/icedteanp/java/sun/applet/PluginObjectStore.java): Removed
+	unused imports.
+	(reference): Removed commented code.
+	(unreference): Removed commented code.
+	* plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java:
+	Removed unused import.
+	* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java: Removed
+	unused imports. Removed unused variable.
+	(PluginStreamHandler): Removed unnecessary comments. Removed commented
+	code.
+	(startProcessing): Removed unused variables. Removed commented code.
+	(write): Removed commented code.
+
+2011-01-20  Deepak Bhole <dbhole@redhat.com>
+
+	PR619: Improper finalization by the plugin can crash the browser
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java (finalize):
+	Proceed with finalization only if JSObject is valid.
+
+2011-01-17  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/NetxPanel.java:
+	(showAppletException): Override, adds logging to file then proceed
+	with showAppletException in sun.applet.AppletPanel.
+	* netx/net/sourceforge/jnlp/AppletLog.java: New class.
+	* netx/net/sourceforge/jnlp/Log.java: New class.
+
+2011-01-14  Andrew Su  <asu@redhat.com>
+
+	* Makefile.am: Added net.sourceforge.jnlp.config and
+	net.sourceforge.jnlp.runtime to NETX_PKGS.
+
+2011-01-12  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
+	(main): Set look and feel. Set config object to use with KeyStores.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Set config object to use with KeyStores.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java: Add new member
+	config.
+	(setConfiguration): New method. Sets the value of config after security
+	check.
+	(getKeyStoreLocation): Use config object instead of querying JNLPRuntime.
+
+2011-01-12  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile: Add missing generic type to info.
+	(getInformation): Remove redundant cast.
+
+2011-01-12  Omair Majid  <omajid@redhat.com>
+
+	* netx/javax/jnlp/UnavailableServiceException.java: Remove unused
+	imports.
+	* netx/net/sourceforge/jnlp/AppletDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/ApplicationDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/ComponentDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/DefaultLaunchHandler.java: Likewise.
+	* netx/net/sourceforge/jnlp/IconDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/InformationDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/InstallerDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/JARDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/JREDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/Launcher.java: Likewise.
+	* netx/net/sourceforge/jnlp/PackageDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/ParseException.java: Likewise.
+	* netx/net/sourceforge/jnlp/PluginBridge.java: Likewise.
+	* netx/net/sourceforge/jnlp/PropertyDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/ResourcesDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/Version.java: Likewise.
+	* netx/net/sourceforge/jnlp/cache/CacheEntry.java: Likewise.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java: Likewise.
+	* netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/cache/DownloadIndicator.java: Likewise.
+	* netx/net/sourceforge/jnlp/cache/UpdatePolicy.java: Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel
+	/AdvancedProxySettingsDialog.java: Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel
+	/AdvancedProxySettingsPane.java: Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel
+	/TemporaryInternetFilesPanel.java: Likewise.
+	* netx/net/sourceforge/jnlp/event/ApplicationEvent.java: Likewise.
+	* netx/net/sourceforge/jnlp/event/DownloadEvent.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/AppletInstance.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/runtime/Boot13.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/security/CertsInfoPane.java: Likewise.
+	* netx/net/sourceforge/jnlp/security/SecurityUtil.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XBasicService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XDownloadService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/services/XFileContents.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XFileOpenService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XFileSaveService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/util/PropertiesFile.java: Likewise.
+	* netx/net/sourceforge/jnlp/util/Reflect.java: Likewise.
+	
+2011-01-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/security/KeyStores.java
+	(getKeyStoreLocation): Fix typo. Return the user-level certificate
+	store correctly.
+
+2011-01-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java: Add
+	systemJnlpPolicy and userJnlpPolicy.
+	(JNLPPolicy): Initialize the new policies.
+	(getPermissions): Consult the extra policies as well to determine the
+	resulting permissions to be granted.
+	(getPolicyFromConfig): New method. Create a new Policy instance to
+	delegate to for system- and user-level policies.
+
+2011-01-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Add
+	customTrustedPolicy.
+	(SecurityDesc): Initialize customTrustedPolicy.
+	(getCustomTrustedPolicy): New method. Get custom policy file from
+	configuration and use it to initialize a custom configuration.
+	(getPermissions): If trusted application and customTrustedPolicy is
+	not null, delegate to otherwise return AllPermissions.
+	* netx/net/sourceforge/jnlp/config/Defaults.java
+	(getDefaults): Use constant for property.
+	* netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java:
+	Add new constant KEY_SECURITY_TRUSTED_POLICY.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
+	(installEnvironment): Pass cs as a parameter to
+	SecurityDesc.getPermissions.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(getPermissions): Likewise.
+
+2011-01-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java: Remove
+	JNLPRuntime import. Remove configBrowserCommand.
+	(createMainSettingsPanel): Remove call to loadConfiguration.
+	(loadConfiguration): Remove method. Setting the browser command
+	should be handled by the appropriate panel.
+	(main): Remove call to JNLPRuntime.initialize and just create a new
+	DeploymentConfiguration object. Clarify TODO comment.
+
+2011-01-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(installShutdownHooks): Only print when not null.
+
+2011-01-04  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java:
+	(addComponents): Hide unsupported options.
+
+2010-12-23  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java:
+	(showAdvancedProxySettingsDialog): Removed call to setSystemLookAndFeel().
+	(setSystemLookAndFeel): Method removed.
+
+2010-12-23  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java:
+	(showAdvancedProxySettingsDialog): Removed creation of swing thread.
+	* netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java:
+	(showCacheDialog): Removed throwing of exception.
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	(addComponents): Removed try catch block.
+	* /netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java:
+	(addComponents): Removed creation of swing thread and try catch block.
+
+2010-12-22  Deepak Bhole <dbhole@redhat.com>
+
+	RH665104: OpenJDK Firefox Java plugin loses a cookie
+	* plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java
+	(parseReturn): Skip one less space so that the first cookie is not
+	skipped.
+	* NEWS: Updated.
+
+2010-12-21  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java,
+	netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	(addComponents): Replaced key listeners and mouse listeners for text
+	fields with document adapter.
+	* netx/net/sourceforge/jnlp/controlpanel/DocumentAdapter.java: New class.
+	* netx/net/sourceforge/jnlp/controlpanel/MiddleClickListener.java:
+	Removed.
+
+2010-12-20  Andrew Su  <asu@redhat.com>
+
+	Added a cache viewer for the control panel.
+	* netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java:
+	(addComponents): Changed buttons to open cache viewer.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Added text
+	used by the cache viewer.
+	* netx/net/sourceforge/jnlp/cache/CacheDirectory.java,
+	netx/net/sourceforge/jnlp/cache/DirectoryNode.java,
+	netx/net/sourceforge/jnlp/controlpanel/CachePane.java,
+	netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java: New classes.
+
+2010-12-20  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am
+	($(NETX_DIR)/launcher/controlpanel/%.o): Set program name, and launch
+	net.sourceforge.jnlp.controlpanel.CommandLine.
+	* netx/net/sourceforge/jnlp/config/Defaults.java
+	(getDefaults): Set descriptions to Unknown rather than the name.
+	Set source to localized form of internal.
+	* netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java
+	(getProperty): Check for nulls.
+	(setProperty): Add unknown as description and source for new
+	properties.
+	(checkAndFixConfiguration): Fix translation constants.
+	(parsePropertiesFile): Use unknown as description.
+	* netx/net/sourceforge/jnlp/controlpanel/CommandLine.java: New file
+	(CommandLine): New method.
+	(handleHelpCommand): Likewise.
+	(printListHelp): Likewise.
+	(handleListCommand): Likewise.
+	(printGetHelp): Likewise.
+	(handleGetCommand): Likewise.
+	(printSetHelp): Likewise.
+	(handleSetCommand): Likewise.
+	(printResetHelp): Likewise.
+	(handleResetCommand): Likewise.
+	(printInfoHelp): Likewise.
+	(handleInfoCommand): Likewise.
+	(printCheckHelp): Likewise.
+	(handleCheckCommand): Likewise.
+	(handle): Likewise.
+	(main): Likewise.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	Usage, Unknown, RConfigurationFatal, DCIncorrectValue,
+	DCSourceInternal, DCUnknownSettingWithName, VVPossibleValues,
+	CLNoInfo, CLValue, CLValueSource, CLDescription, CLUnknownCommand
+	CLUnknownProperty, CLNoIssuesFound, CLIncorrectValue,
+	CLListDescription, CLGetDescription, CLSetDescription,
+	CLResetDescription, CLInfoDescription, CLCheckDescription and
+	CLHelpDescription. Remove DCErrorInSetting and
+	DCUnknownSettingWithVal.
+
+2010-12-17  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
+	(ControlPanel): Create and add the topPanel.
+	(createTopPanel): New method. Creates a JPanel to display the
+	description on top of the Control Panel.
+	(createNotImplementedPanel): Use the same way to load resource
+	as createTopPanel to avoid null pointer exceptions.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	CPMainDescriptionShort and CPMainDescriptionLong.
+
+2010-12-17  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/security/SecurityWarning.java
+	(shouldPromptUser): Use full privileges when checking configuration. This
+	value is not security-sensitive and the method is private.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java
+	(shouldPromptUser): Likewise.
+
+2010-12-16 Omair Majid <omajid@redhat.com>
+
+	RH663680, CVE-2010-4351:
+	* NEWS: List issue.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	Make sure SecurityException is thrown if necessary. 
+
+2010-12-15  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am
+	(install-exec-local): Install plugin.jar as data. If $(prefix)/jre/bin
+	exists, then install symlinks to real javaws and itweb-settings binaries
+	under it.
+	($(NETX_DIR)/launcher/%.o): Set system property java.icedtea-web.bin to
+	point to the installed location of the javaws binary.
+	* netx/net/sourceforge/jnlp/Launcher.java (launchExternal): Use the system
+	property java.icedtea-web.bin to locate javaws binary.
+
+2010-12-15  Andrew Su  <asu@redhat.com>
+
+	* /netx/net/sourceforge/jnlp/resources/Messages.properties: Changed
+	messages for about and JRE.
+
+2010-12-14  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	(LAUNCHER_OBJECTS): Add jli_util.o, parse_manifest.o,
+	version_comp.o, wildcard.o.
+	(LAUNCEHR_FLAGS): Add -DEXPAND_CLASSPATH_WILDCARDS
+	as used in build of libjli in OpenJDK.
+	(LAUNCHER_LINK): Don't link to libjli.
+	* launcher/jli_util.c,
+	* launcher/parse_manifest.c,
+	* launcher/version_comp.c,
+	* launcher/wildcard.c:
+	Add source files from OpenJDK6 to match header files
+	already used.
+
+2010-12-13  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/config/ValueValidator.java: New file.
+	* netx/net/sourceforge/jnlp/config/BasicValueValidators.java: New
+	file. Provides methods to get some common validators.
+	* netx/net/sourceforge/jnlp/config/ConfiguratonValidator.java: New
+	file. Provides methods to validate a configuration.
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Moved to config subpackage instead and split off into Setting.java,
+	DeploymentConfiguration.java and Defaults.java.
+	* netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java:
+	Renamed version of original DeploymentConfiguration.
+	(load): Delegate to load.
+	(load(boolean)): Load configuration and optionally fix any issues
+	found.
+	(checkAndFixConfiguration): New method. Validate all settings and
+	set them to default values if problems found.
+	* netx/net/sourceforge/jnlp/config/Setting.java: New file. Based on
+	ConfigValue which was originally a part of DeploymentConfiguration.
+	* netx/net/sourceforge/jnlp/config/Defaults.java: New file.
+	Contains the default configuration settings. Originally from
+	DeploymentConfiguration.java's loadDefaultProperties.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add new
+	messages.
+	* netx/net/sourceforge/jnlp/Launcher.java: Fix imports.
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Likewise.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java: Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel
+	/AdvancedProxySettingsDialog.java: Likewise
+	* netx/net/sourceforge/jnlp/controlpanel
+	/AdvancedProxySettingsPane.java: Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java: Likewise
+	* netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel/MiddleClickListener.java:
+	Likewise
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/controlpanel
+	/TemporaryInternetFilesPanel.java:Likewise.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Likewise.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java: Likewise.
+	* netx/net/sourceforge/jnlp/security/SecurityWarning.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/SingleInstanceLock.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/services/XBasicService.java: Likewise
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java: Likewise.
+	* plugin/icedteanp/java/sun/applet/JavaConsole.java: Likewise.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java: Likewise. 
+
+2010-12-13  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Parser.java
+	(getInformationDesc): Fix whitespace in title, vendor and description
+	elements.
+	(getRelatedContent): Fix whitespace in title and description elements.
+	(getSpanText(Node)): Delegate to ...
+	(getSpanText(Node,boolean)): New method.  Return the text in an element,
+	optionally fixing whitespace.
+
+2010-12-10  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java: Remove unused variables
+	collator, VERSION, IN_KEYSTORE, IN_SCOPE, privateKey, store, keystore,
+	nullStream, token, jarfile, alias, storepass, protectedPath, storetype,
+	providerName, providers, providerArgs, keypass, sigfile, sigalg,
+	digestalg, signedjar, tsaUrl, tsaAlias, verify, debug, signManifest and
+	externalSF.
+	(getPublisher): Remove unnecessary cast.
+	(getRoot): Likewise.
+
+2010-12-08  Deepak Bhole <dbhole@redhat.com>
+
+	PR597: Entities are parsed incorrectly in PARAM tag in applet plugin
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(encode_string): New function. Takes a string and replaces certain special
+	characters with html escapes.
+	(plugin_create_applet_tag): Use the new encode_string function to encode
+	argn and argv right away, rather than encoding the whole tag.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(handleMessage): Move decoding out so that it is done after parsing.
+	(decodeString): New function. Decodes the given string such that html
+	escapes are replaced by the original special characters.
+	(scanTag): Decode parameter name and value before adding it to attribute
+	array.
+	* NEWS: Updated.
+
+2010-12-08  Omair Majid  <omajid@redhat.com>
+
+	* configure.ac: Add check for sun.misc.HexDumpEncoder
+	* netx/net/sourceforge/jnlp/security/CertsInfoPane.java: Import
+	sun.misc.HexDumpEncoder. Remove import of net.sourceforge.jnlp.tools.*
+	* netx/net/sourceforge/jnlp/tools/CharacterEncoder.java: Remove file.
+	* netx/net/sourceforge/jnlp/tools/HexDumpEncoder.java: Remove file.
+
+2010-12-08  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java
+	(getSupportedVersions): Remove method.
+	* netx/net/sourceforge/jnlp/Parser.java: Remove supportedVersions.
+	(Parser(JNLPFile,URL,Node,boolean,boolean)): Remove check for supported
+	version.
+	(getSupportedVersions): Remove method.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties:
+	Remove PSpecUnsupported.
+
+2010-12-08  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/tools/JarRunner.java: Remove unused class.
+	* netx/net/sourceforge/jnlp/tools/JarSignerResources.java: Remove unused
+	class.
+
+2010-12-07  Andrew John Hughes  <ahughes@redhat.com>
+
+	* netx/net/sourceforge/jnlp/InformationDesc.java,
+	(InformationDesc(JNLPFile,Locale)): Correct @param tag.
+	* netx/net/sourceforge/jnlp/JARDesc.java:
+	(JARDesc(URL,Version,String,boolean,boolean,boolean,boolean)):
+	Correct typo and add missing @param tag for cacheable.
+	* netx/net/sourceforge/jnlp/JREDesc.java:
+	(JREDesc(Version,URL,String,String,String,List)): Correct typo
+	in @param tag.
+	* netx/net/sourceforge/jnlp/Launcher.java:
+	(Launcher(boolean)): Correct broken @param tag.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	(addDownloadListener(DownloadListener)): Remove broken @param tags.
+	Add correct one.
+	(removeDownloadListener(DownloadListener)): Add missing @param tag.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java:
+	(getKeyStoreLocation(Level,Type)): Add content to @param and @return tags.
+	(toTranslatableString(Level,Type)): Likewise.
+	* netx/net/sourceforge/jnlp/security/PasswordAuthenticationDialog.java:
+	(askUser(String,int,String,String)): Correct typo in @param tag.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java:
+	(createSetValueListener(SecurityWarningDialog,int)): Add content to @return tag.
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java:
+	(showCertInfoDialog(CertVerifier,SecurityWarningDialog)): Remove broken
+	@param tag and add correct ones.
+	(showSingleCertInfoDialog(X509Certificate,JDialog)): Add content to @param tags.
+	* netx/net/sourceforge/jnlp/tools/CharacterEncoder.java:
+	Remove broken @see tags from import from OpenJDK.
+	* netx/net/sourceforge/jnlp/util/FileUtils.java:
+	Fix bad whitespace.
+	(sanitizeFileName(String)): Fix @param tag.
+	* netx/net/sourceforge/nanoxml/XMLElement.java:
+	Fix example in class documentation.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java,
+	(waitForAppletInit(NetxPanel)): Fix @param tag.
+
+2010-12-08  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/tools/KeyTool.java: Remove unused class.
+
+2010-12-07  Andrew Su  <asu@redhat.com>
+
+	* MiddleClickListener.java: Added copyright header. Corrected typo in
+	javadoc.
+
+2010-12-07  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am
+	(PLUGIN_VERSION): Change to IcedTea-Web
+	($(PLUGIN_DIR)/%.o): Define PLUGIN_NAME and PACKAGE_URL.
+	* configure.ac
+	(AC_INTIT): Add url.
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(PLUGIN_NAME): Removed.
+	(PLUGIN_FULL_NAME): New definition.
+	(PLUGIN_DESC): Add link to IcedTea-Web wiki page.
+	(NP_GetValue): Return PLUGIN_FULL_NAME instead of PLUGIN_NAME.
+
+2010-12-06  Deepak Bhole <dbhole@redhat.com>
+
+	Fixed indentation and spacing for all .java files
+	* .settings/org.eclipse.jdt.core.prefs: New file. Contains code style
+	preference settings for Eclipse.
+	* .settings/org.eclipse.jdt.ui.prefs: Same.
+
+2010-12-03  Andrew John Hughes  <ahughes@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java,
+	(getCachedResource(URL,Version,UpdatePolicy)):
+	Revert change to use toURI() for now.
+	See http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2010-December/011270.html
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java,
+	(getCacheURL(URL)): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java,
+	(getFile()): Use toURI.toURL() to avoid broken escaping.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	(initializeResources()): Likewise.
+
+2010-12-01  Andrew John Hughes  <ahughes@redhat.com>
+
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(getCachedResource(URL,Version,UpdatePolicy)): Use
+	toURI().toURL() to avoid broken escaping.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	(getCacheURL(URL)): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java:
+	(destroy()): Suppress deprecated warning from use of thread.stop().
+	Only use when interrupt() has already been tried.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java:
+	(getFile()): Use toURI.toURL() to avoid broken escaping.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	(initializeResources()): Likewise.
+	* netx/net/sourceforge/jnlp/security/PasswordAuthenticationDialog.java:
+	(askUser(String,int,String,String)): Use getPassword() to retrieve
+	a character array directly.  Fix overrunning line.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java:
+	Remove unused IdentityScope variable, scope.
+	* netx/net/sourceforge/nanoxml/XMLElement.java:
+	(scanWhitespace(StringBuffer)): Don't fallthrough.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc:
+	Fix warnings where std::string is used in printf
+	rather than char* by invoking c_str on these strings.
+	* plugin/icedteanp/java/netscape/javascript/JSException.java:
+	(JSException()): Mark with @Deprecated annotation.
+	(JSException(String)): Likewise.
+	(JSException(String,String,int,String,int)): Likewise.
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java:
+	(JSObject(String)): Remove redundant cast.
+	(getWindow(Applet)): Likewise.
+	* plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java:
+	(contexts): Initialise properly with generic typing.
+	* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java:
+	(getMatchingMethod(Object[]): Add missing generic type to Class
+	instances.
+	(getMatchingConstructor(Object[])): Likewise.
+	(getCostAndCastedObject(Object,Class<?>)): Likewise.
+	(getMatchingMethods(Class<?>,String,int)): Likewise.
+	(getMatchingConstructors(Class<?>,int)): Likewise.
+	(getNum(String,Class<?>)): Likewise.
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java:
+	(parseCall(String,ClassLoader,Class<V>)): Use c.cast rather than (V).
+	(handleMessage(int,String,AccessControlContext,String)): Add
+	missing generic type to Class instances.  Remove redundant casts.
+	(prepopulateField(int,String)): Add missing generic type to Class instance.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java:
+	(createPanel(PluginStreamHandler,int,long,URL,Hashtable<String,String>)):
+	Add missing generic types on Hashtable and PrivilegedAction.
+	(initEventQueue(AppletPanel)): Add missing generic type to PrivilegedAction.
+	(splitSeparator(String,String)): Use an ArrayList rather than Vector
+	to avoid locking and use generic types.
+	(requests): Initialise properly with generic typing.
+	(applets): Likewise.
+	(appletStateChanged(AppletEvent)): Use setSize and getPreferredSize.
+	(handleMessage(int,String)): Remove redundant casts.
+	(audioClips): Add generic types.
+	(getAudioClip): Remove redundant cast.
+	(imageRefs): Add generic types.
+	(getCachedImageRef(URL)): Remove redundant cast.
+	(appletPanels): Add generic types.
+	(getApplets()): Likewise.
+	(getStream(String)): Mark with @Override.
+	(getStreamKeys()): Likewise.
+	(systemParam): Add generic types.
+	(printTag(PrintStream,Hashtable<String,String>)): Likewise.
+	Remove redundant casts.
+	(updateAtts()): Use getSize() and getInsets().  Use Integer.valueOf().
+	(appletReload()): Add generic types to PrivilegedAction.
+	(scanIdentifier(int[],Reader)): Use StringBuilder to avoid unnecessary
+	locking.
+	(skipComment(int[],Reader)): Likewise.
+	(scanTag(int[],Reader)): Likewise. Add generic types.
+	(parse(int,long,String,String,Reader,URL)): Use PrivilegedExceptionAction
+	to avoid catching and rethrowing the exception manually.  Add generic types.
+	(parse(int,long,String,String,Reader,URL,PrintStream,PluginAppletPanelFactory)):
+	Add generic types.  Remove unnecessary casts.  Fix overlong lines.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java:
+	(init()): Add generic types.  Remove unnecessary cast.
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java:
+	(objects): Initialise properly with generic typing.
+	(counts): Likewise.
+	(identifiers): Likewise.
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java:
+	(get(Object)): Suppress unchecked warning arising from cast to K.
+
+2010-12-02  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add itweb-settings.desktop.in.
+	(all-local): Add itweb-settings.desktop.
+	(clean-desktop-files): Remove itweb-settings.desktop.
+	(itweb-settings.desktop): New target.
+	* itweb-settings.desktop.in: New file.
+
+2010-12-01  Andrew John Hughes  <ahughes@redhat.com>
+
+	* acinclude.m4:
+	(IT_CHECK_FOR_APPLETVIEWERPANEL_HOLE):
+	New check to ensure sun.applet.AppletViewerPanel
+	is public (via the patch in IcedTea, applet_hole.patch).
+	* configure.ac: Invoke the above macro.  Don't call
+	IT_CHECK_FOR_CLASS for the same class (the above macro
+	handles this too).
+	* README: Mention this limitation.
+
+2010-12-01  Andrew Su  <asu@redhat.com>
+
+	* NEWS: Added controlpanel for modifying deployments.properties
+	* Makefile.am:
+	(CONTROLPANEL_LAUNCHER_OBJECTS): Objects used to compile binary
+	control panel.
+	(all-local): Add $(NETX_DIR)/launcher/controlpanel/itw-settings.
+	(install-exec-local): Install the control panel binary.
+	(uninstall-local): Removes the compiled control panel binary.
+	($(NETX_DIR)/launcher/controlpanel/%.o): Create the launcher objects.
+	($(NETX_DIR)/launcher/controlpanel/itw-settings): Link the objects to
+	make the launcher.
+	* netx/net/sourceforge/jnlp/controlpanel/AboutPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/ComboItem.java,
+	* netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/JREPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/NamedBorderPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/MiddleClickListener.java,
+	* netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java,
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java,
+	* netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java,
+	* netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java,:
+	New classes. All methods are new as well.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Added
+	messages used by control panel.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java:
+	Changed to not display a close button if null parent frame.
+
+2010-11-30  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	(liveconnect): Add NETX_DIR first on the bootclasspath
+	so the plugin can be built against 1.7 and 1.8
+	branch releases of IcedTea6.
+
+2010-11-26  Andrew John Hughes  <ahughes@redhat.com>
+
+	Make distcheck work.
+	* Makefile.am:
+	(EXTRA_DIST): Use relative paths for netx
+	and the plugin.
+	(clean-local): Remove empty stamps directory.
+	(install-exec-local): Use install to install
+	programs and data with the correct permissions.
+	(install-data-local): Likewise.
+	(uninstall-local): Remove documentation.
+	(netx): Use ${INSTALL_DATA} to add resources so
+	that read-only files aren't copied.
+	(extra-files): Likewise.
+	($(NETX_DIR)/launcher/javaws): Don't create empty launcher
+	directory.
+	(clean-docs): Remove empty docs directory.
+	(clean-bootstrap-directory): Remove empty bootstrap
+	directory.
+
+2010-11-29  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(createPanel): Call the new framePanel() method with the proper handle.
+	(framePanel): New method, renamed from reFrame. Changed to now do one-time
+	framing of panel into the plugin.
+	(handleMessage): Don't re-frame the panel. Panel is now framed only once.
+	(destroyApplet): Dispose the frame right away, and try to remove the panel
+	if possible. If not, handleMessage() will do it when the panel is
+	ready/removable.
+
+2010-11-25  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	(JDK_UPDATE_VERSION): Document.
+	(NETX_PKGS): NetX packages for documentation.
+	(PLUGIN_PKGS): Same for the plugin.
+	(JAVADOC_OPTS): Common options passed to javadoc.
+	(JAVADOC_MEM_OPTS): Memory options passed to JVM
+	if possible (taken from the previous OpenJDK build).
+	(all-local): Depend on docs.stamp.
+	(clean-local): Add clean-docs.
+	(.PHONY): Add clean-docs, clean-plugin-docs, clean-netx-docs.
+	(install-exec-local): Install the documentation if enabled.
+	(docs): Meta-dependency for netx-docs and plugin-docs.
+	(clean-docs): Likewise but for clean targets.
+	(netx-docs): Build documentation for the NetX API.
+	(clean-netx-docs): Remove the NetX docs.
+	(plugin-docs): Build documentation for the plugin API.
+	(clean-plugin-docs): Likewise.
+	(bootstrap-directory): Link to javadoc binary.
+	* acinclude.m4:
+	(IT_FIND_JAVADOC): Find a javadoc binary, first checking
+	user input, then the JDK and the path for 'javadoc' and
+	'gjdoc'.  Also sets JAVADOC_SUPPORTS_J_OPTIONS if it does.
+	* configure.ac:
+	Call IT_FIND_JAVADOC.
+
+2010-11-25  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (stamps/liveconnect.stamp): Set a bootclasspath to
+	avoid using an older netx.jar during compilation.
+
+2010-11-24  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/util/FileUtils.java
+	(createRestrictedDirectory): New method. Creates a directory with reduced
+	permissions.
+	(createRestrictedFile(File,boolean)): New method. Creates a file with reduced
+	permissions.
+	(createRestrictedFile(File,boolean,boolean): New method. Creates a file or
+	a directory with reduced permissions.
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(markNetxRunning): Do not grant unnecessary file permissions.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java: Remove umask from
+	help message.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(activateNative): Create file with proper permissions.
+	(getNativeDir): Create directory with proper permissions.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initializeStreams): Create files with proper permissions.
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java
+	(CheckBoxListener.actionPerformed): Likewise.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java
+	(createKeyStoreFromFile): Likewise.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(ImportButtonListener.actionPerformed): Likewise.
+	(RemoveButtonListener.actionPerformed): Likewise.
+	* netx/net/sourceforge/jnlp/services/SingleInstanceLock.java
+	(createWithPort): Likewise.
+	(getLockFile): Likewise.
+	* netx/net/sourceforge/jnlp/services/XExtendedService.java
+	(openFile): Likewise.
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java
+	(create): Likewise.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java
+	(installDesktopLauncher): Likewise.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	CantCreateFile, RCantCreateDir and RCantRename. Remove BNoBase and
+	BOUmask.
+
+2010-11-24  Deepak Bhole <dbhole@redhat.com>
+
+	Fix PR593: Increment of invalidated iterator in IcedTeaPluginUtils (patch
+	from barbara.xxx1975@libero.it)
+	* plugin/icedteanp/IcedTeaPluginUtils.cc
+	(invalidateInstance): Act on the pointer directly, rather than via
+	members.
+	* NEWS: Updated.
+
+2010-11-24  Deepak Bhole <dbhole@redhat.com>
+
+	Fix PR552: Support for FreeBSD's pthread implementation (patch from
+	jkim@freebsd.org)
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(NP_Shutdown): Do pthread_join after cancel to	avoid destroying mutexes
+	or condition variables in use.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(PluginRequestProcessor): Initialize mutexes dynamically.
+	(queue_cleanup): New method. Destroy dynamically created mytexes.
+	(queue_processor): Initialize wait_mutex and push cleanup on exit. Clean
+	up after processing stops.
+
+2010-11-24  Andrew John Hughes  <ahughes@redhat.com>
+
+	* NEWS: Bring in changes from IcedTea6 1.10
+	NEWS (now redundant there) and apply same structure
+	as in IcedTea6.
+
+2010-11-24  Omair Majid  <omajid@redhat.com>
+
+	CVE-2010-3860 IcedTea System property information leak via public static
+	* netx/net/sourceforge/jnlp/runtime/Boot.java: Remove basedir
+	 option. Add NETX_ABOUT_FILE.
+	 (run): Remove call to JNLPRuntime.setBaseDir.
+	 (getAboutFile): Use the constant in this file, not JNLPRuntime.
+	 (getBaseDir): Remove obsolete method.
+	 * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove
+	 baseDir, USER, HOME_DIR, NETXRC_FILE, NETX_DIR, SECURITY_DIR,
+	 CERTFICIATES_FILE, JAVA_HOME_DIR, NETX_ABOUT_FILE.
+	 (initialize): Do not set baseDir.
+	 (getBaseDir): Remove method.
+	 (setBaseDir): Likewise.
+	 (getDefaultBaseDir): Likewise.
+	 (getProperties): Likewise.
+	 * netx/net/sourceforge/jnlp/security/SecurityUtil.java
+	 (getTrustedCertsFilename): Delegate to
+	 KeyStores.getKeyStoreLocation.
+	 * plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
+	 (PluginAppletSecurityContext): Remove call to obsolete method.
+
+2010-11-24  Omair Majid  <omajid@redhat.com>
+
+	Fix PR592.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java
+	(getContentsAsReader): Sanitize information before adding to desktop file.
+	(sanitize): New method. Ensure that there are no newlines in input.
+
+2010-11-24  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	CVCertificateType.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Use
+	CVCertificateType instead of hardcoded string.
+
+2010-11-24  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Add grantAwtPermissions.
+	(SecurityDesc): Set grantAwtPermissions.
+	(getSandboxPermissions): Use grantAwtPermissions to determine whether to
+	grant permissions.
+
+2010-11-24  Matthias Klose  <doko@ubuntu.com>
+
+	* Makefile.am (javaws.desktop): Search javaws.desktop.in in $(srcdir).
+
+2010-11-24  Matthias Klose  <doko@ubuntu.com>
+
+	* Makefile.am (LAUNCHER_LINK): Don't explicitely link with -lc,
+	link with -pthread instead of -lpthread.
+	(LAUNCHER_FLAGS): Add -pthread.
+
+2010-11-24  Chris Coulson  <chris.coulson@canonical.com>
+
+	* Makefile.am (pluginappletviewer, javaws):
+	Fix linking with --as-needed.
+
+2010-11-23  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_PROXY_TYPE, KEY_PROXY_SAME, KEY_PROXY_AUTO_CONFIG_URL,
+	KEY_PROXY_BYPASS_LIST, KEY_PROXY_BYPASS_LOCAL, KEY_PROXY_HTTP_HOST,
+	KEY_PROXY_HTTP_PORT, KEY_PROXY_HTTPS_HOST, KEY_PROXY_HTTPS_PORT,
+	KEY_PROXY_FTP_HOST, KEY_PROXY_FTP_PORT, KEY_PROXY_SOCKS4_HOST,
+	KEY_PROXY_SOCKS4_PORT, and KEY_PROXY_OVERRIDE_HOSTS.
+	(loadDefaultProperties): Use the new constants.
+	* netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java: New
+	class.
+	(JNLPProxySelector): New method.
+	(parseConfiguration): New method. Initializes this object by
+	querying the configuration.
+	(getHost): New method.
+	(getPort): New method.
+	(connectFailed): New method.
+	(select): New method. Returns a list of appropriate proxies to use
+	for a given uri.
+	(inBypassList): New method. Return true if the host in the URI
+	should be bypassed for proxy purposes.
+	(isLocalHost): New method.
+	(getFromConfiguration): New method. Finds a proxy based on
+	configuration.
+	(getFromPAC): New method.
+	(getFromBrowser): New method.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Install proxy selector and authenticator.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java
+	(init): Do not install authenticator.
+	(CustomAuthenticator): Moved to...
+	* netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java: Here.
+	* plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java
+	Moved to...
+	* netx/net/sourceforge/jnlp/security
+	/PasswordAuthenticationDialog.java: Here.
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java: Extend
+	JNLPProxySelector.
+	(select): Renamed to...
+	(getFromBrowser): New method.
+
+2010-11-19  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Replace javaws.desktop with
+	javaws.desktop.in. (all-local): Add javaws.desktop. (clean-local):
+	Add dependency on clean-desktop-files. (.PHONY): Add clean-desktop-
+	files. (clean-desktop-files): New target. (javaws.desktop): New
+	target. Use the absolute path to javaws binary in the Exec= line to
+	create the javaws.desktop file.
+	* javaws.desktop: Renamed to...
+	* javaws.desktop.in: New file. Does not contain Encoding key. Value
+	for Icon does not contain extension.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java
+	(JAVA_ICON_NAME): Set to icon name without the extension.
+
+2010-11-18  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/SecurityDesc.java: Remove window banner
+	permissions from sandboxPermissions and j2eePermissions.
+	(getSandBoxPermissions): Dynamically add window banner permissions
+	if allowed by configuration.
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_SECURITY_PROMPT_USER,
+	KEY_SECURITY_ALLOW_HIDE_WINDOW_WARNING,
+	KEY_SECURITY_PROMPT_USER_FOR_JNLP, and
+	KEY_SECURITY_INSTALL_AUTHENTICATOR.
+	(loadDefaultProperties): Use the new constants.
+	* netx/net/sourceforge/jnlp/security/SecurityWarning.java
+	(showAccessWarningDialog): Check if the user should be prompted
+	before prompting the user.
+	(showNotAllSignedWarningDialog): Likewise.
+	(showCertWarningDialog): Likewise.
+	(showAppletWarning): Likewise.
+	(shouldPromptUser): New method. Check if configuration allows
+	showing user prompts.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java
+	(checkAccess(AccessType,Object...)): Clarify javadocs.
+	(checkAccess(ApplicationInstance,AccessType,Object...)): Clarify
+	javadocs. Only prompt the user if showing JNLP prompts is ok.
+	(shouldPromptUser): New method. Returns true if configuration allows
+	for showing JNLP api prompts.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java
+	(init): Only install custom authenticator if allowed by
+	configuration.
+
+2010-11-18  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_ENABLE_LOGGING.
+	(loadDefaultProperties): Use KEY_ENABLE_LOGGING.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Add
+	redirectStreams, STDERR_FILE and STDOUT_FILE.
+	(initialize): Call initializeStreams.
+	(initializeStreams): New method. Redirects or duplicates stdout and
+	stderr to the logging files as required.
+	(setRedirectStreams): New method. Sets whether stdout/stderr streams
+	should be redirected.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java:
+	(PluginMain): Move code for creating logging files into JNLPRuntime.
+	Call JNLPRuntime.setRedirectStreams to redirect streams.
+	(TeeOutputStream): Move to its own class.
+	* netx/net/sourceforge/jnlp/util/TeeOutputStream.java: Moved from
+	PluginMain into this new class.
+
+2010-11-18  Omair Majid  <omajid@redhat.com>
+
+	* NEWS: Update with new interfaces
+	* netx/javax/jnlp/DownloadService2.java: New interface.
+	(ResourceSpec): New class.
+	(ResourceSpec.ResourceSpec): New method.
+	(ResourceSpec.getExpirationDate): New method.
+	(ResourceSpec.getLastModified): New method.
+	(ResourceSpec.getSize): New method.
+	(ResourceSpec.getType): New method.
+	(ResourceSpec.getUrl): New method.
+	(ResourceSpec.getVersion): New method.
+	(getCachedResources): New method.
+	(getUpdateAvaiableReosurces): New method.
+	* netx/javax/jnlp/IntegrationService.java: New interface.
+	(hasAssociation): New method.
+	(hasDesktopShortcut): New method.
+	(hasMenuShortcut): New method.
+	(removeAssociation): New method.
+	(removeShortcuts): New method.
+	(requestAssociation): New method.
+	(requestShortcut): New method.
+
+2010-11-16  Andrew Su  <asu@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Corrected typo in one of the default values.
+
+2010-11-11  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/Boot.java (main): Move trust
+	manager initialization code into JNLPRuntime.initialize.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java
+	(init): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize):
+	Set the default SSL TrustManager here.
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java
+	(CheckBoxListener.actionPerformed): Add this certificate into
+	user's trusted certificate store.
+	* netx/net/sourceforge/jnlp/tools/KeyTool.java
+	(addToKeyStore(File,KeyStore)): Move to CertificateUtils.
+	(addToKeyStore(X509Certificate,KeyStore)): Likewise.
+	(dumpCert): Likewise.
+	* netx/net/sourceforge/jnlp/security/CertificateUtils.java: New
+	class.
+	(addToKeyStore(File,KeyStore)): Moved from KeyTool.
+	(addToKeyStore(X509Certificate,KeyStore)): Likewise.
+	(dumpCert): Likewise.
+	(inKeyStores): New method.
+	* netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java
+	(getRootInCacerts): Check all available CA store to check if
+	root is in CA certificates.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java
+	(getKeyStore(Level,Type,boolean)): Add security check.
+	(getClientKeyStores): New method.
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
+	(VariableX509TrustManager): Initialize multiple CA, certificate and
+	client trust managers.
+	(checkClientTrusted): Check all the client TrustManagers if
+	certificate is trusted.
+	(checkAllManagers): Check multiple CA certificates and trusted
+	certificates to determine if the certificate chain can be trusted.
+	(isExplicitlyTrusted): Check with multiple TrustManagers.
+	(getAcceptedIssuers): Gather results from multiple TrustManagers.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(ImportButtonListener): Use CertificateUtils instead of KeyTool.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java
+	(checkTrustedCerts): Use multiple key stores to check if certificate
+	is directly trusted and if the root is trusted.
+
+2010-11-09  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	ButAllow, ButClose, ButCopy, ButMoreInformation, ButProceed,
+	ButRun, AlwaysAllowAction, Continue, Field, From, Name, Publisher,
+	Value, Version, SNoAssociatedCertificate, SAlwaysTrustPublisher,
+	SHttpsUnverified, SNotAllSignedSummary, SNotAllSignedDetail,
+	SNotAllSignedQuestion, SCertificateDetails, SIssuer, SSerial,
+	SMD5Fingerprint, SSHA1Fingerprint, SSignature, SSignatureAlgorithm,
+	SSubject, SValidity, CVCertificateViewer, CVDetails, CVIssuedTo,
+	CVExport, CVImport, CVIssuedBy, IssuedTo, CVRemove,
+	CVRemoveConfirmMessage,CVRemoveConfirmTitle, CVUser, CVSystem,
+	KS, KSCerts, KSJsseCerts, KSCaCerts, KSJsseCaCerts, and
+	KSClientCerts.
+	* netx/net/sourceforge/jnlp/security/AccessWarningPane.java
+	(addComponents): Use localized strings.
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java
+	(addComponents): Likewise.
+	* netx/net/sourceforge/jnlp/security/CertsInfoPane.java
+	(parseCert): Likewise.
+	(addComponents): Likewise.
+	* netx/net/sourceforge/jnlp/security/MoreInfoPane.java
+	(addComponents): Likewise.
+	* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java
+	(addComponents): Likewise.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java:
+	Likewise.
+	(addComponents): Likewise.
+	(CertificateType.toString): Likewise.
+	(RemoveButtonListener.actionPerformed): Likewise. 
+
+2010-11-05  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_BROWSER_PATH.
+	(loadDefaultProperties): Use KEY_BROWSER_PATH.
+	* netx/net/sourceforge/jnlp/services/XBasicService.java
+	(initialize): Use the browser command from the configuration.
+	Save updates to configuration as well. 
+
+2010-11-05  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/ShortcutDesc.java: Change prefixes from
+	SHORTCUT_ to CREATE_.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
+	(addMenuAndDesktopEntries): Call shouldCreateShortcut to find out
+	if shortcut should be created. Remove call to checkAccess which
+	does nothing as the entire stack contains trusted classes.
+	(shouldCreateShortcut): New method. Use the configuration to find
+	out if a shorcut should be created, and possibly prompt the user.
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_CREATE_DESKTOP_SHORTCUT.
+	(loadDefaultProperties): Use KEY_CREATE_DESKTOP_SHORTCUT.
+
+2010-11-08  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (JDK_UPDATE_VERSION): Define variable.
+
+2010-11-04  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Add KEY_USER_TRUSTED_CA_CERTS, KEY_USER_TRUSTED_JSSE_CA_CERTS,
+	KEY_USER_TRUSTED_CERTS, KEY_USER_TRUSTED_JSSE_CERTS,
+	KEY_USER_TRUSTED_CLIENT_CERTS, KEY_SYSTEM_TRUSTED_CA_CERTS,
+	KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS, KEY_SYSTEM_TRUSTED_CERTS,
+	KEY_SYSTEM_TRUSTED_JSSE_CERTS, KEY_SYSTEM_TRUSTED_CLIENT_CERTS
+	(loadDefaultProperties): Use the defined constants.
+	* netx/net/sourceforge/jnlp/security/KeyStores.java: New class.
+	(getPassword): New method. Return the default password used for
+	KeyStores.
+	(getKeyStore(Level,Type)): New method. Returns the appropriate
+	KeyStore.
+	(getKeyStore(Level,Type,String)): Likewise.
+	(getCertKeyStores): New method. Return all the trusted certificate
+	KeyStores.
+	(getCAKeyStores): New method. Return all the trusted CA certificate
+	KeyStores.
+	(getKeyStoreLocation): New method. Return the location of the
+	appropriate KeyStore.
+	(toTranslatableString): New method. Return a string that can be
+	used to create a human-readable name for the KeyStore.
+	(toDisplayableString): New method. Return a human-readable name
+	for the KeyStore.
+	(createKeyStoreFromFile): New method. Creates a new KeyStore object,
+	initializing it from the given file if possible.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(CertificatePane): Create two JTables. Populate the tables when
+	done creating the user interface.
+	(initializeKeyStore): Use the correct keystore.
+	(addComponents): Do not read KeyStore. Create more interface
+	elements to show the new possible KeyStores. Mark some buttons to
+	be disabled when needed.
+	(repopulateTable): Renamed to...
+	(repopulateTables): New method. Read KeyStore and use the contents
+	to create the user and system tables.
+	(CertificateType): New class.
+	(CertificateTypeListener): New class. Listens to JComboBox change
+	events.
+	(TabChangeListener): New class. Listens to new tab selections.
+	(ImportButtonListener): Import certificates to the appropriate
+	KeyStore.
+	(ExportButtonListener): Find the certificate from the right table.
+	(RemoveButtonListener): Find the certificate from the right table
+	and right the KeyStore.
+	(DetailsButtonListener): Find the certificate from the right table.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
+	(showCertficaiteViewer): Initialize the JNLPRuntime so the
+	configuration gets loaded.
+	* netx/net/sourceforge/jnlp/tools/KeyTool.java
+	(addToKeyStore(File,KeyStore)): New method. Adds certificate from
+	the file to the KeyStore.
+	(addToKeyStore(X509Certificate,KeyStore)): New method. Adds a
+	certificate to a KeyStore.
+
+2010-11-04  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (update):
+	Override method and implement double-buffering.
+
+2010-10-28  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	(NETX_BOOTSTRAP_CLASSES): Removed.
+	(PLUGIN_BOOTSTRAP_CLASSES): Likewise.
+	(NETX_SUN_CLASSES): Likewise.
+	(PLUGIN_SUN_CLASSES): Likewise.
+	* acinclude.m4:
+	(IT_CHECK_FOR_CLASS): Require detection
+	of javac and java.  Put test class in
+	sun.applet to get access to some internal
+	classes.  Change test to use forName for
+	the same reason.  I expect to be able to
+	revert this when usage of sun.applet is fixed.
+	(IT_FIND_JAVA): Ported from IcedTea6.  Change
+	to prioritise 'java' over 'gij'.
+	* configure.ac:
+	Add IT_CHECK_FOR_CLASS checks for classes which
+	are required but not found in JDKs other than
+	Oracle-based ones.  Also check for java.* classes
+	missing from current versions of gcj but which
+	may appear there in future.
+
+2010-11-03  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(markNetxRunning): Get file name from configuration.
+	(markNetxStopped): Likewise.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java
+	(clearCache): Get cache directory from configuration.
+	(okToClearCache): Get netx_running file from configuration.
+	(getCacheFile): Get cache directory from configuration.
+	(urlToPath): Change semantics to take in the full path of the
+	directory instead of a directory under runtime.
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	Change DEPLOYMENT_DIR to ".icedtea". Add constants
+	KEY_USER_CACHE_DIR, KEY_USER_PERSISTENCE_CACHE_DIR,
+	KEY_SYSTEM_CACHE_DIR, KEY_USER_LOG_DIR, KEY_USER_TMP_DIR,
+	KEY_USER_LOCKS_DIR, and KEY_USER_NETX_RUNNING_FILE.
+	(load): Use DEPLOYMENT_DIR instead of hardcoded string.
+	(loadDefaultProperties): Add LOCKS_DIR. Replace strings with
+	constants. Add new default values for persistence cache directory,
+	single instance locks directory and the netx_running file.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove
+	unneeded TMP_DIR, LOCKS_DIR and NETX_RUNNING_FILE
+	* netx/net/sourceforge/jnlp/services/SingleInstanceLock.java
+	(getLockFile): Get locks directory from configuration.
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java
+	(toCacheFile): Get persistence cache directory from configuration.
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java
+	(getContentsAsReader): Get cache directory from configuration.
+	(installDesktopLauncher): Get temporary directory from
+	configuration. Make parent directories if required.
+	* plugin/icedteanp/java/sun/applet/JavaConsole.java
+	(initialize): Get log directory from configuration and create the
+	error and output files under it.
+	* plugin/icedteanp/java/sun/applet/PluginMain.java:
+	PLUGIN_STDERR_FILE and PLUGIN_STDOUT_FILE are now just filesnames.
+	(PluginMain): Use configuration for finding the log directory.
+	Initialize JNLPRuntime before creating the stderr and stdout logs.
+
+2010-11-01  Omair Majid  <omajid@redhat.com>
+
+	* Makefile.am (clean-IcedTeaPlugin): Only delete launcher directory if it
+	exists.
+
+2010-11-01  Deepak Bhole <dbhole@redhat.com>
+
+	PR542: Plugin fails with NPE on
+	http://www.openprocessing.org/visuals/iframe.php?visualID=2615
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(initializeResources): If cacheFile is null (JAR couldn't be downloaded),
+	try to continue, rather than allowing the exception to cause an abort.
+	* NEWS: Updated.
+
+2010-11-01  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/docs: Added new docs folder that contains plugin documentation.
+	* plugin/docs/MessageBusArchitecture.png: Diagram of the JS <-> Java 
+	message handling architectrure.
+	* plugin/docs/OverallArchitecture.png: Diagram of the overall plugin
+	architecture.
+	* plugin/docs/java-js-wf.png: Sequence diagram showing an example
+	LiveConnect call from an applet to JavaScript/Browser.
+	* plugin/docs/js-java-wf.png: Sequence diagram showing an example
+	LiveConnect call from JavaScript/Browser to an applet.
+	* plugin/docs/npplugin_liveconnect_design.pdf: Slides with notes on the
+	above diagrams.
+
+2010-10-29  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/JNLPFile.java: Add component.
+	(getLaunchInfo): Modify javadoc to indicate that it does not return
+	the ComponentDesc.
+	(getComponent): Return component instead of launchType.
+	(isComponent): Check if component is not null.
+	(parse): Find and set component descriptor.
+	* netx/net/sourceforge/jnlp/Parser.java
+	(getLauncher): Remove all checks for component-desc. Allow having
+	none of application-desc, applet-desc and installer-desc.
+	(getComponent): Check for more than one component-desc element.
+	Read and parse the component-desc.
+
+2010-10-28  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java
+	(showMoreInfoDialog): Make dialog modal.
+	(showCertInfoDialog): Likewise.
+	(showSingleCertInfoDialog): Likewise.
+	(initDialog): Use setModality instead of setModal.
+
+2010-10-27  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaNPPlugin.cc (plugin_create_applet_tag): Escape
+	the entire applet tag, not just the params.
+
+2010-10-27  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java
+	(load): Do a security check at start. A security exception later on may
+	accidentally reveal a filename or a system property.
+	(save): Likewise.
+
+2010-10-26  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(doPerApplicationAppContextHacks): New method. Create a new ParserDelegate
+	to intialize the per AppContext dtd used by Swing HTML controls.
+	(TgThread.run): Call doPerApplicationAppContextHacks.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Call doMainAppContextHacks.
+	(doMainAppContextHacks): New method. Create a new ParserDelegate to
+	initialize the per AppContext dtd used by Swing HTML controls.
+
+2010-10-26  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Launcher.java
+	(launchApplication): Mark main method as accessible before
+	invoking it.
+
+2010-10-26  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/Parser.java: Add 1.1, 1.2, 1.3 and
+	1.4 to supportedVersions.
+
+2010-10-26  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/Translator.java
+	(R(String)): New method.
+
+2010-10-26  Deepak Bhole <dbhole@redhat.com>
+
+	* netx/net/sourceforge/jnlp/PluginBridge.java: Trim whitespace from jar
+	names in the constructor.
+
+2010-10-26  Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java:
+	Replace all status.put calls with calls to updateStatus().
+	(createPanel): Create a frame with a 0 handle. Use the new
+	waitForAppletInit function to wait until applet is ready.
+	(reFrame): Re-order code so that the panel is never parentless.
+	(handleMessage): Re-wrote message processing to handle destroy calls
+	correctly, checking for them more often to prevent a frame from popping up
+	if the tab/page is closed before loading finishes. Decode special
+	characters in the message.
+	(updateStatus): New function. Updates the status for the given instance if
+	applicable.
+	(destroyApplet): New function. Destroys a given applet and frees related
+	resources.
+	(waitForAppletInit): New function. Blocks until applet is initialized.
+	(parse): Remove part that decoded the params. Decoding is now done earlier
+	in handleMessage().
+	* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java:
+	(getPriorityStrIfPriority): Mark destroy messages as priority.
+	(bringPriorityMessagesToFront): Scans the queue for priority messages and
+	brings them to the front.
+	(run): If the queue is not empty and there are no workers left, run
+	bringPriorityMessagesToFront() and retry.
+
+2010-10-26  Andrew Su  <asu@redhat.com>
+
+	* Makefile.am: Split rm -rf into rm -f and rmdir for launcher
+	directory.
+
+2010-10-25  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/ShortcutDesc.java:
+	Add SHORTCUT_NEVER, SHORTCUT_ALWAYS, SHORTCUT_ASK_USER,
+	SHORTCUT_ASK_USER_IF_HINTED, SHORTCUT_ALWAYS_IF_HINTED,
+	SHORTCUT_DEFAULT.
+	* netx/net/sourceforge/jnlp/resources/Messages.properties:
+	Add RConfigurationError.
+	* netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java:
+	New file.
+	(ConfigValue): New class. Holds a configuration value.
+	(DeploymentConfiguration): New method.
+	(load): New method.
+	(getProperty): Likewise.
+	(getAllPropertyNames): Likewise.
+	(setProperty): Likewise.
+	(loadDefaultProperties): Likewise.
+	(findSystemConfigFile): Likewise.
+	(loadSystemConfiguration): Likewise.
+	(loadProperties): Likewise.
+	(save): Likewise.
+	(parsePropertiesFile): Likewise.
+	(mergeMaps): Likewise.
+	(dumpConfiguration): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	(initialize): Load configuration.
+	(getConfiguration): Return the configuration.
+
+2010-10-25  Omair Majid  <omajid@redhat.com>
+
+	* net/sourceforge/jnlp/ExtensionDesc.java: Import Translator.R and use
+	that.
+	* net/sourceforge/jnlp/JNLPFile.java: Import Translator.R.
+	(R): Remove.
+	* net/sourceforge/jnlp/JREDesc.java: Import Translator.R.
+	(checkHeapSize): Use R instead of JNLPRuntime.getMessage.
+	* net/sourceforge/jnlp/Launcher.java: Import Translator.R.
+	(R): Remove.
+	* net/sourceforge/jnlp/Parser.java: Import Translator.R
+	(R(String)): Remove.
+	(R(String,Object)): Remove.
+	(R(String,Object,Object)): Remove.
+	(R(String,Object,Object,Object)): Remove.
+	* net/sourceforge/jnlp/cache/CacheEntry.java: Import Translator.R
+	(CacheEntry): Use R instead of JNLPRuntime.getMessage.
+	* net/sourceforge/jnlp/cache/CacheUtil.java: Import Translator.R
+	(R(String)): Remove.
+	(R(String,Object)): Remove.
+	* net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java: Import
+	Translator.R and use that instead of JNLPRuntime.getMessage.
+	* net/sourceforge/jnlp/runtime/Boot.java: Import Translator.R.
+	(R(String)): Remove.
+	(R(String, Object)): Remove.
+	(run): Use R instead of JNLPRuntime.getMessage.
+	* net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Import Translator.R.
+	(R): Remove.
+	* net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: Import
+	Translator.R.  Use it instead of JNLPRuntime.getMeesage.
+	(R): Remove.
+	* net/sourceforge/jnlp/security/AccessWarningPane.java: Import
+	Translator.R.
+	* net/sourceforge/jnlp/security/CertWarningPane.java: Likewise.
+	* net/sourceforge/jnlp/security/HttpsCertVerifier.java: Import
+	Translator.R.
+	(R(String)): Remove.
+	(R(String,String,String)): Remove.
+	* net/sourceforge/jnlp/security/MoreInfoPane.java: Import Translator.R.
+	* net/sourceforge/jnlp/security/SecurityDialogPanel.java
+	(R(String)): Remove.
+	(R(String,Object)): Remove.
+	* net/sourceforge/jnlp/services/ServiceUtil.java
+	(R): Remove.
+	* net/sourceforge/jnlp/services/SingleInstanceLock.java: Import
+	Translator.R
+	(R(String)): Remove.
+	(R(String,Object)): Remove.
+	* net/sourceforge/jnlp/tools/JarSigner.java: Import Translator.R.
+	(R): Remove.
+	* net/sourceforge/jnlp/runtime/Translator.java: New file
+	(R(String,Object...)): New method.
+
+2010-10-25  Andrew Su <asu@redhat.com>
+
+	* Makefile.am:
+	(clean-IcedTeaPlugin): Remove launcher folder first.
+	(clean-plugin): Removed called to remove launcher folder
+
+2010-10-22  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/NetxPanel.java
+	(runLoader): Do not initialize JNLPRuntime here.
+	(createAppletThreads): Initialize JNLPRuntim here.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java:
+	Switch from SecurityWarningDialog.AccessType to
+	SecurityWarning.AccessType.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(getInstance(JNLPFile,UpdatePolicy)): Switch to SecurityWarning.
+	(initializeResources): Likewise.
+	(checkTrustWithUser): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	Add securityDialogMesasgeHandler.
+	(initialize): Set System look and feel. Start security thread.
+	(startSecurityThread): New method. Starts a thread to show security
+	dialogs.
+	(getSecurityDialogHandler): Returns the securityDialogMessageHandler.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	Switch from SecurityWarningDialog.AccessType to
+	SecurityWarning.AccessType.
+	(checkAwtEventQueueAccess): New method. Skeleton code for allowing
+	EventQueue acccess to applets.
+	* netx/net/sourceforge/jnlp/security/AccessWarningPane.java:
+	Switch from SecurityWarningDialog.AccessType to
+	SecurityWarning.AccessType.
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java:
+	Likewise.
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java:
+	Move DialogType and AccessType to SecurityWarning.
+	(SecurityWarningDialog(DialogType,AccessType,JNLPFile,CertVerifier,
+	X509Certificate,Object[])): New method. The catch-all construction.
+	(SecurityWarningDialog(DialogType,AccessType,JNLPFile): Delegate to
+	the new constructor.
+	(SecurityWarningDialog(DialogType,AccessType,JNLPFile,CertVerifier)):
+	Likewise.
+	(SecurityWarningDialog(DialogType,AccessType,CertVerifier)): Likewise.
+	(SecurityWarningDialog(DialogType,AccessType,JNLPFile,Object[])):
+	Likewise.
+	(SecurityWarningDialog(DialogType,X509Certificate)): Likewise.
+	(showAccessWarningDialog(AccessType,JNLPFile)): Move to SecurityWarning
+	class.
+	(showAccessWarningDialog(AccessType,JNLPFile,Object[])): Likewise.
+	(showNotAllSignedWarningDialog(JNLPFile)): Likewise.
+	(showCertWarningDialog(AccessType,JNLPFile,CertVerifier)): Likewise.
+	(showAppletWarning): Likewise.
+	(initDialog): Make dialog non modal and remove window closing listener.
+	(getValue): Make public.
+	(dispose): New method. Notify listeners.
+	(notifySelectionMade): New method. Notify listeners that user has made
+	a decision.
+	(addActionListener): New method. Add a listener to be notified when
+	user makes a decision about this security warning.
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java:
+	Switch from SecurityWarningDialog.AccessType to
+	SecurityWarning.AccessType.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XClipboardService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XExtendedService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XFileOpenService.java: Likewise.
+	* netx/net/sourceforge/jnlp/services/XFileSaveService.java: Likewise.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java:
+	New class.
+	* netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java:
+	New class.
+	(run): New method. Runs the security message loop.
+	(handleMessage): New method. Handles a SecurityDialogMessage to show a
+	security warning.
+	(postMessage): New method. Posts a message to sthe security message
+	queue.
+	* netx/net/sourceforge/jnlp/security/SecurityWarning.java: New class.
+	Move AccessType and DialogType from SecurityWarningDialog to here.
+	(showAccessWarningDialog): Moved from SecurityWarningDialog to here.
+	(showAccessWarningDialog): Moved from SecurityWarningDialog to here.
+	Modified to post messages to the security queue instead of showing a
+	SecurityWarningDialog directly.
+	(showNotAllSignedWarningDialog): Likewise.
+	(showCertWarningDialog): Likewise.
+	(showAppletWarning): Likewise.
+	(getUserReponse): New method. Posts a message to the security thread and
+	blocks until it gets a response from the user.
+
+2010-10-20  Andrew John Hughes  <ahughes@redhat.com>
+
+	* netx/javax/jnlp/ServiceManager.java:
+	(lookupTable): Add generic types.
+	* netx/net/sourceforge/jnlp/AppletDesc.java:
+	(parameters): Likewise.
+	(AppletDesc(String,String,URL,int,int,Map)): Likewise.
+	(getParameters()): Likewise.
+	* netx/net/sourceforge/jnlp/ApplicationDesc.java:
+	(getArguments()): Remove redundant cast.
+	(addArgument(String)): Add generic typing.
+	* netx/net/sourceforge/jnlp/ExtensionDesc.java:
+	(extToPart): Add generic types.
+	(eagerExtParts): Likewise.
+	* netx/net/sourceforge/jnlp/InformationDesc.java:
+	(info): Likewise.
+	(getIcons(Object)): Add generic typing.
+	(getAssociations()): Likewise.
+	(getRelatedContents()): Likewise.
+	(getItem(Object)): Likewise.
+	(getItems(Object)): Likewise.
+	(addItem(String,Object)): Likewise.
+	* netx/net/sourceforge/jnlp/JNLPFile.java:
+	(resources): Likewise.
+	(InformationDesc.getItems(Object)): Likewise.
+	(getResources(Class)): Likewise.
+	* netx/net/sourceforge/jnlp/LaunchException.java:
+	(getCauses()): Likewise.
+	* netx/net/sourceforge/jnlp/Launcher.java:
+	(launchApplication(JNLPFile)): Likewise.
+	* netx/net/sourceforge/jnlp/NetxPanel.java:
+	(NetxPanel(URL,Hashtable)): Likewise.
+	(NetxPanel(URL,Hashtable,boolean)): Likewise.
+	* netx/net/sourceforge/jnlp/Node.java:
+	(getChildNodes()): Likewise.
+	* netx/net/sourceforge/jnlp/Parser.java:
+	(getResources(Node,boolean)): Likewise.
+	(getInfo(Node)): Likewise.
+	(getInformationDesc(Node)): Likewise.
+	(getApplet(Node)): Likewise.
+	(getApplication(Node)): Likewise.
+	(splitString(String)): Likewise.
+	(getLocales(Node)): Likewise.
+	(getChildNodes(Node,String)): Likewise.
+	* netx/net/sourceforge/jnlp/PluginBridge.java:
+	Fix variable naming and add generic types.
+	(cacheJars): Changed from cache_jars.
+	(cacheExJars): Changed from cache_ex-jars.
+	(atts): Add generic typing.
+	(PluginBridge(URL,URL,String,String,int,int,Hashtable)): Likewise.
+	(getInformation(Locale)): Likewise.
+	(getResources(Locale,String,String)): Likewise.
+	(getJARs()): Avoid excessive copying; filtering already performed
+	by getResources in JNLPFile.
+	* netx/net/sourceforge/jnlp/ResourcesDesc.java:
+	(resources): Add generic typing.
+	(getJREs()): Likewise.
+	(getJARs()): Likewise.
+	(getJARs(String)): Likewise.
+	(getExtensions()): Likewise.
+	(getPackages()): Likewise.
+	(getPackages(String)): Likewise.
+	(getProperties()): Likewise.
+	(getPropertiesMap()): Likewise.
+	(getResources(Class)): Make generic.
+	* netx/net/sourceforge/jnlp/Version.java:
+	(matches(Version)): Add generic types.
+	(matchesAny(Version)): Likewise.
+	(matchesSingle(String)): Likewise.
+	(matches(String,String)): Likewise.
+	(equal(List,List)): Likewise.
+	(greater(List,List)): Likewise.
+	(compare(String,String)): Use Integer.valueOf.
+	(normalize(List,int)): Add generic types, using
+	a List of lists rather than an array of lists.
+	(getVersionStrings()): Add generic types.
+	(getParts()): Likewise.
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java:
+	(waitForResources(ApplicationInstance,ResourceTracker,
+	URL,String)): Likewise.
+	* netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java:
+	(getListener(ApplicatonInstance,String,URL)): Use setVisible instead
+	of show().
+	(disposeListener(DownloadServiceListener)): Use setVisible instead
+	of hide().
+	(DownloadPanel.urls): Add generic typing.
+	(DownloadPanel.panels): Likewise.
+	(DownloadPanel.update(URL,String,long,long,int)): Fix formatting.
+	Add generic types.
+	* netx/net/sourceforge/jnlp/cache/Resource.java:
+	(resources): Add generic typing.
+	(trackers): Likewise.
+	(getResource(URL,Version,UpdatePolicy)): Use generic types.
+	(getTracker()): Likewise.
+	(addTracker(ResourceTracker)): Likewise.
+	(fireDownloadEvent()): Likewise.
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java:
+	(prefetchTrackers): Add generic typing.
+	(queue): Likewise.
+	(active): Likewise.
+	(resources): Likewise.
+	(listeners): Likewise.
+	(fireDownloadEvent(Resource)): Remove unneeded cast.
+	(getPrefetch()): Use generic typing.
+	(selectByFlag(List,int,int)): Likewise.
+	(getResource(URL)): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java:
+	(weakClips): Add generic types.
+	(destroy()): Use generic typing.
+	(getApplets()): Likewise.
+	(getStreamKeys()): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java:
+	(weakWindows): Add generic types.
+	(installEnvironment()): Likewise.
+	(destroy()): Remove redundant cast.
+	* netx/net/sourceforge/jnlp/runtime/Boot.java:
+	Extend PrivilegedAction<Void>.
+	(run()): Add generic typing.
+	(getOptions(String)): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/Boot13.java:
+	(main(String[]): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java:
+	Fix formatting.
+	(urlToLoader): Add generic types.
+	(resourcePermissions): Likewise.
+	(available): Likewise.
+	(jarEntries): Likewise.
+	(getInstance(JNLPFile,UpdatePolicy)): Remove redundant cast.
+	(getInstance(URL,String,Version,UpdatePolicy)): Likewise.
+	(initializeExtensions()): Add generic types.
+	(initializePermissions()): Likewise.
+	(initializeResources()): Likewise.
+	(getPermissions(CodeSource)): Likewise.
+	(fillInPartJars(List)): Likewise.
+	(activateJars(List)): Likewise.
+	(loadClass(String)): Likewise.  Suppress warnings due to
+	sun.misc.JarIndex usage.
+	(findResources(String)): Mark as overriding.  Add generic
+	types.
+	(getExtensionName()): Add @Deprecated annotation.
+	(getExtensionHREF()): Likewise.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	(weakWindows): Add generic typing.
+	(weakApplications): Likewise.
+	(getApplication(Window)): Remove redundant casts.  Add w,
+	which is window cast to Window.
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java:
+	(invoke(Object,Method,Object[])): Use generic types.
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java:
+	(getNames(URL)): Likewise.
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java:
+	(verifyJars(List,ResourceTracker)): Remove redundant cast.
+	* netx/net/sourceforge/jnlp/util/WeakList.java:
+	Redesign as a generic type.
+	(refs): Add generic types.
+	(deref(WeakReference)): Likewise.
+	(get(int)): Likewise.
+	(set(int,Object)): Likewise.
+	(add(int,E)): Likewise.
+	(remove()): Likewise.
+	(hardList()): Likewise.
+	* netx/net/sourceforge/nanoxml/XMLElement.java:
+	(attributes): Add generic typing.
+	(children): Likewise.
+	(entities): Likewise.
+	(XMLElement()): Use generic types.
+	(XMLElement(Hashtable): Likewise.
+	(resolveEntity(StringBuffer)): Remove redundant cast.
+
+2010-10-20  Omair Majid  <omajid@redhat.com>
+
+	* AUTHORS: Add Francis Kung, Andrew Su, Joshua Sumali, Mark Wielaard and
+	Man Lung Wong. Add link to forked Netx project.
+
+2010-10-20  Matthias Klose  <doko@ubuntu.com>
+
+	* AUTHORS: Add myself.
+
+2010-10-20  Andrew Su  <asu@redhat.com>
+
+	* PluginBridge.java:
+	(PluginBridge): Added parsing for jnlp_href, and reading the jnlp file
+	for applet parameters.
+
+2010-10-20  Matthias Klose  <doko@ubuntu.com>
+
+	* Makefile.am (stamps/extra-class-files.stamp): Fix -sourcepath.
+
+2010-10-20  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(initializeResources): Do not perform url encoding on the file url. Stay
+	consistent with the unencoded urls used in getPermissions.
+
+2010-10-20  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(JNLPClassLoader): Call installShutdownHooks.
+	(installShutdownHooks): New method. Installs a shutdown hook to
+	recursively delete the contents of nativeDir.
+	(activateNative): Only create a nativeDir if there are native
+	libraries.
+
+2010-10-19  Deepak Bhole  <dbhole@redhat.com>
+
+	* Makefile.am:
+	($(NETX_DIR)/launcher/javaws): Use $(NETX_DIR).
+
+2010-10-19  Deepak Bhole  <dbhole@redhat.com>
+
+	* Makefile.am:
+	(NETX_DIR): New variable representing the NetX build dir.
+	(NETX_LAUNCHER_OBJECTS): Prefix with $(NETX_DIR).
+	(LAUNCHER_LINK): Fixed escaping of ORIGIN to the rpath argument.
+	(all-local): Fix javaws launcher path.
+	(install-exec-local): Likewise, and use $(NETX_DIR) for NetX classes.jar.
+	(clean-plugin): Remove launcher.
+	(liveconnect): Use NETX_DIR in classpath.
+	(netx): Use NETX_DIR throughout.
+	(netx-dist): Likewise.
+	(clean-netx): Likewise.
+	($(NETX_DIR)/launcher/%.o)): Likewise.
+	* launcher/jni_md.h: Imported from OpenJDK.
+
+2010-10-20  Matthias Klose  <doko@ubuntu.com>
+
+	* Makefile.am: Fix build with builddir != srcdir.
+
+2010-10-19  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am:
+	(PLUGIN_LAUNCHER_OBJECTS): Do prefixing once.
+	(NETX_LAUNCHER_OBJECTS): Likewise for NetX.
+	(pluginappletviewer): Use PLUGIN_LAUNCHER_OBJECTS.
+	(javaws): Use NETX_LAUNCHER_OBJECTS.
+	* configure.ac: Re-enable foreign (I want to use
+	GNU make!)
+	* README: Use gmake not make.
+
+2010-10-19  Andrew John Hughes  <ahughes@redhat.com>
+
+	* .hgignore,
+	* Makefile.am,
+	* acinclude.m4,
+	* autogen.sh,
+	* configure.ac,
+	* extra/net/sourceforge/jnlp/about/HTMLPanel.java,
+	* extra/net/sourceforge/jnlp/about/Main.java,
+	* extra/net/sourceforge/jnlp/about/resources/about.html,
+	* extra/net/sourceforge/jnlp/about/resources/applications.html,
+	* extra/net/sourceforge/jnlp/about/resources/notes.html,
+	* javac.in,
+	* javaws.desktop: Imported from IcedTea6.
+	* launcher/java.c,
+	* launcher/java.h,
+	* launcher/java_md.c,
+	* launcher/java_md.h,
+	* launcher/jli_util.h,
+	* launcher/jni.h,
+	* launcher/jvm.h,
+	* launcher/jvm_md.h,
+	* launcher/manifest_info.h,
+	* launcher/splashscreen.h,
+	* launcher/splashscreen_stubs.c,
+	* launcher/version_comp.h,
+	* launcher/wildcard.h: Imported from OpenJDK.
+	* netx/javaws.1,
+	* netx/javax/jnlp/BasicService.java,
+	* netx/javax/jnlp/ClipboardService.java,
+	* netx/javax/jnlp/DownloadService.java,
+	* netx/javax/jnlp/DownloadServiceListener.java,
+	* netx/javax/jnlp/ExtendedService.java,
+	* netx/javax/jnlp/ExtensionInstallerService.java,
+	* netx/javax/jnlp/FileContents.java,
+	* netx/javax/jnlp/FileOpenService.java,
+	* netx/javax/jnlp/FileSaveService.java,
+	* netx/javax/jnlp/JNLPRandomAccessFile.java,
+	* netx/javax/jnlp/PersistenceService.java,
+	* netx/javax/jnlp/PrintService.java,
+	* netx/javax/jnlp/ServiceManager.java,
+	* netx/javax/jnlp/ServiceManagerStub.java,
+	* netx/javax/jnlp/SingleInstanceListener.java,
+	* netx/javax/jnlp/SingleInstanceService.java,
+	* netx/javax/jnlp/UnavailableServiceException.java,
+	* netx/net/sourceforge/jnlp/AppletDesc.java,
+	* netx/net/sourceforge/jnlp/ApplicationDesc.java,
+	* netx/net/sourceforge/jnlp/AssociationDesc.java,
+	* netx/net/sourceforge/jnlp/ComponentDesc.java,
+	* netx/net/sourceforge/jnlp/DefaultLaunchHandler.java,
+	* netx/net/sourceforge/jnlp/ExtensionDesc.java,
+	* netx/net/sourceforge/jnlp/IconDesc.java,
+	* netx/net/sourceforge/jnlp/InformationDesc.java,
+	* netx/net/sourceforge/jnlp/InstallerDesc.java,
+	* netx/net/sourceforge/jnlp/JARDesc.java,
+	* netx/net/sourceforge/jnlp/JNLPFile.java,
+	* netx/net/sourceforge/jnlp/JNLPSplashScreen.java,
+	* netx/net/sourceforge/jnlp/JREDesc.java,
+	* netx/net/sourceforge/jnlp/LaunchException.java,
+	* netx/net/sourceforge/jnlp/LaunchHandler.java,
+	* netx/net/sourceforge/jnlp/Launcher.java,
+	* netx/net/sourceforge/jnlp/MenuDesc.java,
+	* netx/net/sourceforge/jnlp/NetxPanel.java,
+	* netx/net/sourceforge/jnlp/Node.java,
+	* netx/net/sourceforge/jnlp/PackageDesc.java,
+	* netx/net/sourceforge/jnlp/ParseException.java,
+	* netx/net/sourceforge/jnlp/Parser.java,
+	* netx/net/sourceforge/jnlp/PluginBridge.java,
+	* netx/net/sourceforge/jnlp/PropertyDesc.java,
+	* netx/net/sourceforge/jnlp/RelatedContentDesc.java,
+	* netx/net/sourceforge/jnlp/ResourcesDesc.java,
+	* netx/net/sourceforge/jnlp/SecurityDesc.java,
+	* netx/net/sourceforge/jnlp/ShortcutDesc.java,
+	* netx/net/sourceforge/jnlp/StreamEater.java,
+	* netx/net/sourceforge/jnlp/UpdateDesc.java,
+	* netx/net/sourceforge/jnlp/Version.java,
+	* netx/net/sourceforge/jnlp/cache/CacheEntry.java,
+	* netx/net/sourceforge/jnlp/cache/CacheUtil.java,
+	* netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java,
+	* netx/net/sourceforge/jnlp/cache/DownloadIndicator.java,
+	* netx/net/sourceforge/jnlp/cache/Resource.java,
+	* netx/net/sourceforge/jnlp/cache/ResourceTracker.java,
+	* netx/net/sourceforge/jnlp/cache/UpdatePolicy.java,
+	* netx/net/sourceforge/jnlp/cache/package.html,
+	* netx/net/sourceforge/jnlp/event/ApplicationEvent.java,
+	* netx/net/sourceforge/jnlp/event/ApplicationListener.java,
+	* netx/net/sourceforge/jnlp/event/DownloadEvent.java,
+	* netx/net/sourceforge/jnlp/event/DownloadListener.java,
+	* netx/net/sourceforge/jnlp/event/package.html,
+	* netx/net/sourceforge/jnlp/package.html,
+	* netx/net/sourceforge/jnlp/resources/Manifest.mf,
+	* netx/net/sourceforge/jnlp/resources/Messages.properties,
+	* netx/net/sourceforge/jnlp/resources/about.jnlp,
+	* netx/net/sourceforge/jnlp/resources/default.jnlp,
+	* netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java,
+	* netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java,
+	* netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java,
+	* netx/net/sourceforge/jnlp/runtime/AppletInstance.java,
+	* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java,
+	* netx/net/sourceforge/jnlp/runtime/Boot.java,
+	* netx/net/sourceforge/jnlp/runtime/Boot13.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java,
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java,
+	* netx/net/sourceforge/jnlp/runtime/package.html,
+	* netx/net/sourceforge/jnlp/security/AccessWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/AppletWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/CertVerifier.java,
+	* netx/net/sourceforge/jnlp/security/CertWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/CertsInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java,
+	* netx/net/sourceforge/jnlp/security/MoreInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java,
+	* netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java,
+	* netx/net/sourceforge/jnlp/security/SecurityUtil.java,
+	* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java,
+	* netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java,
+	* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java,
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java,
+	* netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java,
+	* netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java,
+	* netx/net/sourceforge/jnlp/services/InstanceExistsException.java,
+	* netx/net/sourceforge/jnlp/services/ServiceUtil.java,
+	* netx/net/sourceforge/jnlp/services/SingleInstanceLock.java,
+	* netx/net/sourceforge/jnlp/services/XBasicService.java,
+	* netx/net/sourceforge/jnlp/services/XClipboardService.java,
+	* netx/net/sourceforge/jnlp/services/XDownloadService.java,
+	* netx/net/sourceforge/jnlp/services/XExtendedService.java,
+	* netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java,
+	* netx/net/sourceforge/jnlp/services/XFileContents.java,
+	* netx/net/sourceforge/jnlp/services/XFileOpenService.java,
+	* netx/net/sourceforge/jnlp/services/XFileSaveService.java,
+	* netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java,
+	* netx/net/sourceforge/jnlp/services/XPersistenceService.java,
+	* netx/net/sourceforge/jnlp/services/XPrintService.java,
+	* netx/net/sourceforge/jnlp/services/XServiceManagerStub.java,
+	* netx/net/sourceforge/jnlp/services/XSingleInstanceService.java,
+	* netx/net/sourceforge/jnlp/services/package.html,
+	* netx/net/sourceforge/jnlp/tools/CharacterEncoder.java,
+	* netx/net/sourceforge/jnlp/tools/HexDumpEncoder.java,
+	* netx/net/sourceforge/jnlp/tools/JarRunner.java,
+	* netx/net/sourceforge/jnlp/tools/JarSigner.java,
+	* netx/net/sourceforge/jnlp/tools/JarSignerResources.java,
+	* netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java,
+	* netx/net/sourceforge/jnlp/tools/KeyTool.java,
+	* netx/net/sourceforge/jnlp/util/FileUtils.java,
+	* netx/net/sourceforge/jnlp/util/PropertiesFile.java,
+	* netx/net/sourceforge/jnlp/util/Reflect.java,
+	* netx/net/sourceforge/jnlp/util/WeakList.java,
+	* netx/net/sourceforge/jnlp/util/XDesktopEntry.java,
+	* netx/net/sourceforge/nanoxml/XMLElement.java,
+	* netx/net/sourceforge/nanoxml/XMLParseException.java,
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc,
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.h,
+	* plugin/icedteanp/IcedTeaNPPlugin.cc,
+	* plugin/icedteanp/IcedTeaNPPlugin.h,
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc,
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.h,
+	* plugin/icedteanp/IcedTeaPluginUtils.cc,
+	* plugin/icedteanp/IcedTeaPluginUtils.h,
+	* plugin/icedteanp/IcedTeaRunnable.cc,
+	* plugin/icedteanp/IcedTeaRunnable.h,
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.cc,
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.h,
+	* plugin/icedteanp/java/netscape/javascript/JSException.java,
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java,
+	* plugin/icedteanp/java/netscape/javascript/JSObjectCreatePermission.java,
+	* plugin/icedteanp/java/netscape/javascript/JSProxy.java,
+	* plugin/icedteanp/java/netscape/javascript/JSRunnable.java,
+	* plugin/icedteanp/java/netscape/javascript/JSUtil.java,
+	* plugin/icedteanp/java/netscape/security/ForbiddenTargetException.java,
+	* plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java,
+	* plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java,
+	* plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java,
+	* plugin/icedteanp/java/sun/applet/JavaConsole.java,
+	* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java,
+	* plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java,
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java,
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java,
+	* plugin/icedteanp/java/sun/applet/PluginCallRequest.java,
+	* plugin/icedteanp/java/sun/applet/PluginCallRequestFactory.java,
+	* plugin/icedteanp/java/sun/applet/PluginClassLoader.java,
+	* plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java,
+	* plugin/icedteanp/java/sun/applet/PluginCookieManager.java,
+	* plugin/icedteanp/java/sun/applet/PluginDebug.java,
+	* plugin/icedteanp/java/sun/applet/PluginException.java,
+	* plugin/icedteanp/java/sun/applet/PluginMain.java,
+	* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java,
+	* plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java,
+	* plugin/icedteanp/java/sun/applet/PluginObjectStore.java,
+	* plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java,
+	* plugin/icedteanp/java/sun/applet/PluginProxySelector.java,
+	* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java,
+	* plugin/icedteanp/java/sun/applet/RequestQueue.java,
+	* plugin/icedteanp/java/sun/applet/TestEnv.java,
+	* plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java,
+	* plugin/tests/LiveConnect/DummyObject.java,
+	* plugin/tests/LiveConnect/OverloadTestHelper1.java,
+	* plugin/tests/LiveConnect/OverloadTestHelper2.java,
+	* plugin/tests/LiveConnect/OverloadTestHelper3.java,
+	* plugin/tests/LiveConnect/PluginTest.java,
+	* plugin/tests/LiveConnect/build,
+	* plugin/tests/LiveConnect/common.js,
+	* plugin/tests/LiveConnect/index.html,
+	* plugin/tests/LiveConnect/jjs_eval_test.js,
+	* plugin/tests/LiveConnect/jjs_func_parameters_tests.js,
+	* plugin/tests/LiveConnect/jjs_func_rettype_tests.js,
+	* plugin/tests/LiveConnect/jjs_get_tests.js,
+	* plugin/tests/LiveConnect/jjs_set_tests.js,
+	* plugin/tests/LiveConnect/jsj_func_overload_tests.js,
+	* plugin/tests/LiveConnect/jsj_func_parameters_tests.js,
+	* plugin/tests/LiveConnect/jsj_func_rettype_tests.js,
+	* plugin/tests/LiveConnect/jsj_get_tests.js,
+	* plugin/tests/LiveConnect/jsj_set_tests.js,
+	* plugin/tests/LiveConnect/jsj_type_casting_tests.js,
+	* plugin/tests/LiveConnect/jsj_type_conversion_tests.js:
+	Initial import from IcedTea6.
+	* AUTHORS,
+	* COPYING
+	* INSTALL,
+	* NEWS,
+	* README: New documentation.
Index: /tags/icedtea-web/beta/Config.kmk
===================================================================
--- /tags/icedtea-web/beta/Config.kmk	(revision 403)
+++ /tags/icedtea-web/beta/Config.kmk	(revision 403)
@@ -0,0 +1,101 @@
+## @file
+# Global Project Configuration File
+#
+
+#------------------------------------------------------------------------------
+# Global definitions
+#------------------------------------------------------------------------------
+
+PACKAGE_NAME       := icedtea-web
+PACKAGE_VER_MAJOR  := 1
+PACKAGE_VER_MINOR  := 1
+PACKAGE_VER_PATCH  := 2
+PACKAGE_VERSION    := $(PACKAGE_VER_MAJOR).$(PACKAGE_VER_MINOR).$(PACKAGE_VER_PATCH)
+PACKAGE_STRING     := $(PACKAGE_NAME) $(PACKAGE_VERSION)
+PACKAGE_URL        := http://icedtea.classpath.org/wiki/IcedTea-Web
+
+FULL_VERSION       := $(PACKAGE_VERSION)
+
+IT_LANGUAGE_SOURCE_VERSION := 6
+IT_CLASS_TARGET_VERSION    := 6
+IT_JAVAC_SETTINGS          ?= -g -encoding utf-8 $(JAVACFLAGS) $(MEMORY_LIMIT) $(PREFER_SOURCE)
+IT_JAVACFLAGS              ?= $(IT_JAVAC_SETTINGS) -source $(IT_LANGUAGE_SOURCE_VERSION) -target $(IT_CLASS_TARGET_VERSION)
+
+BOOTSTRAP_JDK_RUNTIME  ?= $(PATH_BOOTSTRAP_JDK)/jre/lib/rt.jar;$(PATH_BOOTSTRAP_JDK)/jre/lib/jsse.jar
+
+INSTALL_DATA       := install -m 644
+
+# @todo later
+#ICEDTEA_WEB_JRE_DIR     := /@unixroot/usr/lib/jre
+#ICEDTEA_WEB_DATA_DIR    := /@unixroot/usr/share/$(PACKAGE_NAME)
+
+ICEDTEA_WEB_JRE     = icedtea_web_jre_dir()
+
+#
+# We need the jars in bootclasspath for a couple of reasons
+#  - we use classes (in the sun.applet package) loaded by the bootclassloader
+#    using another classloader to load classes from the same package causes an
+#    IllegalAccessException
+#  - we want full privileges
+#
+LAUNCHER_BOOTCLASSPATH  = \"-Xbootclasspath/a:%s/netx.jar$(RHINO_RUNTIME)\", \
+                          icedtea_web_data_dir()
+PLUGIN_BOOTCLASSPATH    = \"-Xbootclasspath/a:%s/netx.jar;%s/plugin.jar$(RHINO_RUNTIME)\", \
+                          icedtea_web_data_dir(), icedtea_web_data_dir()
+
+# Fake update version to work with the Deployment Toolkit script used by Oracle
+# http://download.oracle.com/javase/tutorial/deployment/deploymentInDepth/depltoolkit_index.html
+JDK_UPDATE_VERSION  := 50
+
+#------------------------------------------------------------------------------
+# Tools
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# Common libraries referenced by components
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# General Stuff
+#------------------------------------------------------------------------------
+
+KBUILD_SDK_PATHS       += $(PATH_ROOT)
+
+TEMPLATE_Cxx            = C++ sources
+TEMPLATE_Cxx_USES       =
+TEMPLATE_Cxx_TOOL       = GXX3OMF
+TEMPLATE_Cxx_INCS       = 
+TEMPLATE_Cxx_DEFS       = OS2EMX_PLAIN_CHAR
+
+ifn1of ($(EMXOMFLD_TYPE),WLINK wlink)
+TEMPLATE_Cxx_LDFLAGS    = -Zlinker '"DISABLE 1121"'
+endif
+
+# generate .sym files but don't put them in a separate dir
+TEMPLATE_Cxx_LD_DEBUG       = split
+TEMPLATE_Cxx_DEBUG_STAGE    = nul
+
+#------------------------------------------------------------------------------
+# Other Stuff
+#------------------------------------------------------------------------------
+
+#
+# Include a site-specific config for local overrides
+#
+ifndef LOCALCFG
+ LOCALCFG := $(wildcard $(PATH_ROOT)/LocalConfig.kmk)
+ ifneq ($(LOCALCFG),)
+  include $(LOCALCFG)
+ endif
+endif
+
+#------------------------------------------------------------------------------
+# Defaults
+#------------------------------------------------------------------------------
+
+PATH_MOZILLA_INCS          ?= $(PATH_ROOT)/../libs/mozilla/include
+MOZILLA_VERSION_COLLAPSED  ?= 11000000 # 11.0.0.0
+
+PATH_GLIB_INCS             ?= $(patsubst -I%,%,$(shell pkg-config --cflags-only-I glib-2.0 gthread-2.0))
+PATH_GLIB_LIBS             ?= $(patsubst -l%,%,$(shell pkg-config --libs-only-l glib-2.0 gthread-2.0))
+PATH_GLIB_LIBPATH          ?= $(patsubst -L%,%,$(shell pkg-config --libs-only-L glib-2.0 gthread-2.0))
Index: /tags/icedtea-web/beta/INSTALL
===================================================================
--- /tags/icedtea-web/beta/INSTALL	(revision 403)
+++ /tags/icedtea-web/beta/INSTALL	(revision 403)
@@ -0,0 +1,365 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+   Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.  Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+   The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the `make install' phase executed with root
+     privileges.
+
+  5. Optionally, type `make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior `make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type `make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide `make
+     distcheck', which can by used by developers to test that all other
+     targets like `make install' and `make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.  This
+is known as a "VPATH" build.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'.  Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated.  The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the `DESTDIR' variable.  For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names.  The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of `make' will be.  For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
Index: /tags/icedtea-web/beta/LocalConfig.kmk.tpl
===================================================================
--- /tags/icedtea-web/beta/LocalConfig.kmk.tpl	(revision 403)
+++ /tags/icedtea-web/beta/LocalConfig.kmk.tpl	(revision 403)
@@ -0,0 +1,26 @@
+## @file
+# Local Project Configuration File (Template)
+#
+# The local project configuration file is used to specify local paths to
+# external tools and libraries and also to optioanlly override the global
+# project configuration options.
+#
+# NOTES:
+#
+#   This file is a template! Copy it to a file named LocalConfig.kmk in 
+#   the same directory and modify the copy to fit your local environment.
+#
+#   All paths in this file are specified using forward slashes unless specified
+#   otherwise.
+#
+
+#
+# Base directory where all build output will go. The directory will be created
+# if does not exist. The default is "out" in the root of the source tree.
+#
+PATH_OUT_BASE := $(PATH_ROOT)/../$(PACKAGE_NAME)-build
+
+#
+# Path to bootstrap version of OpenJDK. Must be set.
+#
+PATH_BOOTSTRAP_JDK := $(PATH_ROOT)/../openjdk/build-product-release/j2sdk-image
Index: /tags/icedtea-web/beta/Makefile.am
===================================================================
--- /tags/icedtea-web/beta/Makefile.am	(revision 403)
+++ /tags/icedtea-web/beta/Makefile.am	(revision 403)
@@ -0,0 +1,576 @@
+# Source directories
+
+NETX_DIR = $(abs_top_builddir)/netx.build
+NETX_SRCDIR = $(abs_top_srcdir)/netx
+NETX_RESOURCE_DIR=$(NETX_SRCDIR)/net/sourceforge/jnlp/resources
+NETX_EXTRA_DIR=$(abs_top_srcdir)/extra/net/sourceforge/javaws/about/resources
+NETX_EXTRA_DIST_DIR=$(abs_top_builddir)/extra-lib/net/sourceforge/javaws/about/resources
+
+TESTS_SRCDIR=$(abs_top_srcdir)/tests
+TESTS_DIR=$(abs_top_builddir)/tests.build
+
+NETX_UNIT_TEST_SRCDIR=$(TESTS_SRCDIR)/netx/unit
+NETX_UNIT_TEST_DIR=$(TESTS_DIR)/netx/unit
+
+JUNIT_RUNNER_DIR=$(TESTS_DIR)/junit-runner
+JUNIT_RUNNER_SRCDIR=$(TESTS_SRCDIR)/junit-runner
+
+JUNIT_RUNNER_JAR=$(abs_top_builddir)/junit-runner.jar
+
+# Build directories
+
+BOOT_DIR = $(abs_top_builddir)/bootstrap/jdk1.6.0
+
+if WITH_RHINO
+  RHINO_RUNTIME=:$(RHINO_JAR)
+else
+  RHINO_RUNTIME=
+endif
+
+RUNTIME = $(BOOT_DIR)/jre/lib/rt.jar:$(BOOT_DIR)/jre/lib/jsse.jar$(RHINO_RUNTIME)
+
+# Flags
+IT_CFLAGS=$(CFLAGS) $(ARCHFLAG)
+IT_JAVAC_SETTINGS=-g -encoding utf-8 $(JAVACFLAGS) $(MEMORY_LIMIT) $(PREFER_SOURCE)
+IT_LANGUAGE_SOURCE_VERSION=6
+IT_CLASS_TARGET_VERSION=6
+IT_JAVACFLAGS=$(IT_JAVAC_SETTINGS) -source $(IT_LANGUAGE_SOURCE_VERSION) -target $(IT_CLASS_TARGET_VERSION)
+
+#
+# We need the jars in bootclasspath for a couple of reasons
+#  - we use classes (in the sun.applet package) loaded by the bootclassloader
+#    using another classloader to load classes from the same package causes an
+#    IllegalAccessException
+#  - we want full privileges
+#
+LAUNCHER_BOOTCLASSPATH="-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar$(RHINO_RUNTIME)"
+PLUGIN_BOOTCLASSPATH='"-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar:$(datadir)/$(PACKAGE_NAME)/plugin.jar$(RHINO_RUNTIME)"'
+
+# Fake update version to work with the Deployment Toolkit script used by Oracle
+# http://download.oracle.com/javase/tutorial/deployment/deploymentInDepth/depltoolkit_index.html
+JDK_UPDATE_VERSION=50
+
+# Sources list
+
+PLUGIN_TEST_SRCS = $(abs_top_srcdir)/plugin/tests/LiveConnect/*.java
+
+NETX_PKGS = javax.jnlp net.sourceforge.nanoxml net.sourceforge.jnlp \
+	net.sourceforge.jnlp.cache net.sourceforge.jnlp.config \
+	net.sourceforge.jnlp.controlpanel net.sourceforge.jnlp.event \
+	net.sourceforge.jnlp.runtime net.sourceforge.jnlp.security \
+	net.sourceforge.jnlp.security.viewer net.sourceforge.jnlp.services \
+	net.sourceforge.jnlp.tools net.sourceforge.jnlp.util
+
+# Conditional defintions
+if ENABLE_PLUGIN
+ICEDTEAPLUGIN_CLEAN = clean-IcedTeaPlugin
+LIVECONNECT_DIR = netscape sun/applet
+PLUGIN_DIR=$(abs_top_builddir)/plugin/icedteanp
+PLUGIN_SRCDIR=$(abs_top_srcdir)/plugin/icedteanp
+LIVECONNECT_SRCS = $(PLUGIN_SRCDIR)/java
+ICEDTEAPLUGIN_TARGET = $(PLUGIN_DIR)/IcedTeaPlugin.so stamps/liveconnect-dist.stamp
+PLUGIN_PKGS = sun.applet netscape.security netscape.javascript
+endif
+
+if CP_SUPPORTS_REFLINK
+  REFLINK = --reflink=auto
+endif
+
+if SRC_DIR_HARDLINKABLE
+  SRC_DIR_LINK = -l
+else
+  SRC_DIR_LINK = $(REFLINK)
+endif
+
+if ENABLE_DOCS
+JAVADOC_OPTS=-use -keywords -encoding UTF-8 -splitIndex \
+ -bottom '<font size="-1"> <a href="http://icedtea.classpath.org/bugzilla">Submit a bug or feature</a></font>'
+if JAVADOC_SUPPORTS_J_OPTIONS
+JAVADOC_MEM_OPTS=-J-Xmx1024m -J-Xms128m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m
+endif
+endif
+
+if WITH_RHINO
+  RHINO_TESTS=check-pac-functions
+else
+  RHINO_TESTS=
+endif
+
+if WITH_JUNIT
+  JUNIT_TESTS=run-netx-unit-tests
+else
+  JUNIT_TESTS=
+endif
+
+
+PLUGIN_VERSION = IcedTea-Web $(FULL_VERSION)
+
+EXTRA_DIST = $(top_srcdir)/netx $(top_srcdir)/plugin javaws.png javaws.desktop.in extra launcher \
+ itweb-settings.desktop.in $(top_srcdir)/tests
+
+# binary names
+javaws:= $(shell echo javaws | sed '@program_transform_name@')
+itweb_settings:= $(shell echo itweb-settings | sed '@program_transform_name@')
+
+# the launcher needs to know $(bindir) and $(datadir) which can be different at
+# make-time from configure-time
+edit_launcher_script = sed \
+  -e 's|[@]LAUNCHER_BOOTCLASSPATH[@]|$(LAUNCHER_BOOTCLASSPATH)|g' \
+  -e 's|[@]JAVAWS_BIN_LOCATION[@]|$(bindir)/$(javaws)|g' \
+  -e 's|[@]ITWEB_SETTINGS_BIN_LOCATION[@]|$(bindir)/$(itweb_settings)|g' \
+  -e 's|[@]JAVA[@]|$(JAVA)|g' \
+  -e 's|[@]JRE[@]|$(SYSTEM_JRE_DIR)|g'
+
+# Top-Level Targets
+# =================
+
+all-local: stamps/netx-dist.stamp extra-lib/about.jar stamps/plugin.stamp launcher.build/$(javaws) \
+ javaws.desktop stamps/docs.stamp launcher.build/$(itweb_settings) itweb-settings.desktop
+
+check-local: $(RHINO_TESTS) $(JUNIT_TESTS)
+
+clean-local: clean-netx clean-plugin clean-liveconnect clean-extra clean-bootstrap-directory \
+ clean-native-ecj clean-launchers clean-desktop-files clean-docs clean-tests
+	if [ -e stamps ] ; then \
+	  rmdir stamps ; \
+	fi
+
+.PHONY: clean-IcedTeaPlugin clean-add-netx clean-add-netx-debug clean-add-plugin clean-add-plugin-debug \
+ clean-bootstrap-directory clean-native-ecj clean-desktop-files clean-netx-docs clean-docs clean-plugin-docs \
+ clean-tests check-local clean-launchers check-pac-functions run-netx-unit-tests clean-netx-tests \
+ clean-junit-runner clean-netx-unit-tests
+
+install-exec-local:
+	${mkinstalldirs} $(DESTDIR)$(bindir) $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/ $(DESTDIR)$(libdir)
+if ENABLE_PLUGIN
+	${INSTALL_PROGRAM} $(PLUGIN_DIR)/IcedTeaPlugin.so $(DESTDIR)$(libdir)
+	${INSTALL_DATA} $(abs_top_builddir)/liveconnect/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar
+endif
+	${INSTALL_DATA} $(NETX_DIR)/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar
+	${INSTALL_PROGRAM} launcher.build/$(javaws) $(DESTDIR)$(bindir)
+	${INSTALL_DATA} extra-lib/about.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jar
+	${INSTALL_PROGRAM} launcher.build/$(itweb_settings) $(DESTDIR)$(bindir)
+
+install-data-local:
+	${mkinstalldirs} -d $(DESTDIR)$(mandir)/man1
+	${INSTALL_DATA} $(NETX_SRCDIR)/javaws.1 $(DESTDIR)$(mandir)/man1
+	${INSTALL_DATA} $(NETX_RESOURCE_DIR)/about.jnlp $(DESTDIR)$(datarootdir)/$(PACKAGE_NAME)
+if ENABLE_DOCS
+	${mkinstalldirs} $(DESTDIR)$(htmldir)
+	(cd ${abs_top_builddir}/docs/netx; \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} $(DESTDIR)$(htmldir)/netx/$${files}; \
+	 done)
+if ENABLE_PLUGIN
+	(cd ${abs_top_builddir}/docs/plugin; \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} $(DESTDIR)$(htmldir)/plugin/$${files}; \
+	 done)
+endif
+endif
+
+uninstall-local:
+	rm -f $(DESTDIR)$(libdir)/IcedTeaPlugin.so
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jnlp
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jar
+	rm -f $(DESTDIR)$(mandir)/man1/javaws.1
+	rm -f $(DESTDIR)$(bindir)/$(javaws)
+	rm -f $(DESTDIR)$(bindir)/$(itweb_settings)
+	rm -rf $(DESTDIR)$(htmldir)
+
+# Plugin
+
+if ENABLE_PLUGIN
+# IcedTeaPlugin.so.
+# Separate compile and link invocations to ensure intermediate object
+# is listed before -l options.  See:
+# http://developer.mozilla.org/en/docs/XPCOM_Glue
+
+PLUGIN_SRC=IcedTeaNPPlugin.cc IcedTeaScriptablePluginObject.cc \
+        IcedTeaJavaRequestProcessor.cc IcedTeaPluginRequestProcessor.cc \
+		IcedTeaPluginUtils.cc
+
+PLUGIN_OBJECTS=IcedTeaNPPlugin.o IcedTeaScriptablePluginObject.o \
+        IcedTeaJavaRequestProcessor.o IcedTeaPluginRequestProcessor.o \
+		IcedTeaPluginUtils.o
+
+$(PLUGIN_DIR)/%.o: $(PLUGIN_SRCDIR)/%.cc
+	mkdir -p $(PLUGIN_DIR) && \
+	cd $(PLUGIN_DIR) && \
+	$(CXX) $(CXXFLAGS) \
+	  -DJDK_UPDATE_VERSION="\"$(JDK_UPDATE_VERSION)\"" \
+	  -DPLUGIN_NAME="\"IcedTea-Web Plugin\"" \
+	  -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \
+	  -DPACKAGE_URL="\"$(PACKAGE_URL)\"" \
+	  -DMOZILLA_VERSION_COLLAPSED="$(MOZILLA_VERSION_COLLAPSED)" \
+	  -DICEDTEA_WEB_JRE="\"$(SYSTEM_JRE_DIR)\"" \
+	  -DPLUGIN_BOOTCLASSPATH=$(PLUGIN_BOOTCLASSPATH) \
+	  $(GLIB_CFLAGS) \
+	  $(GTK_CFLAGS) \
+	  $(MOZILLA_CFLAGS) \
+	  -fPIC -o $@ -c $<
+
+$(PLUGIN_DIR)/IcedTeaPlugin.so: $(addprefix $(PLUGIN_DIR)/,$(PLUGIN_OBJECTS))
+	cd $(PLUGIN_DIR) && \
+	$(CXX) $(CXXFLAGS) \
+	  $(PLUGIN_OBJECTS) \
+	  $(GLIB_LIBS) \
+	  $(GTK_LIBS) \
+	  $(MOZILLA_LIBS)\
+	  -shared -o $@
+
+clean-IcedTeaPlugin:
+	rm -f $(PLUGIN_DIR)/*.o
+	rm -f $(PLUGIN_DIR)/IcedTeaPlugin.so
+	if [ $(abs_top_srcdir) != $(abs_top_builddir) ]; then \
+	  if [ -e $(abs_top_builddir)/plugin/icedteanp ] ; then \
+	    rmdir $(abs_top_builddir)/plugin/icedteanp ; \
+	    rmdir $(abs_top_builddir)/plugin ; \
+	  fi ; \
+	fi
+endif
+
+stamps/plugin.stamp: $(ICEDTEAPLUGIN_TARGET)
+	mkdir -p stamps
+	touch stamps/plugin.stamp
+
+clean-plugin: $(ICEDTEAPLUGIN_CLEAN)
+	rm -f stamps/plugin.stamp
+
+liveconnect-source-files.txt:
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  find $(LIVECONNECT_SRCS) -name '*.java' | sort > $@ ; \
+	  sed -i '/_OS2/ d' $@
+	fi
+	touch $@
+
+stamps/liveconnect.stamp: liveconnect-source-files.txt stamps/netx.stamp
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  mkdir -p $(abs_top_builddir)/liveconnect && \
+	  $(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	      -d $(abs_top_builddir)/liveconnect \
+	      -bootclasspath $(NETX_DIR):$(RUNTIME) \
+	      -sourcepath $(LIVECONNECT_SRCS) \
+	      @liveconnect-source-files.txt ; \
+	fi
+	mkdir -p stamps
+	touch $@
+
+stamps/liveconnect-dist.stamp: stamps/liveconnect.stamp
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  (cd $(abs_top_builddir)/liveconnect ; \
+	   mkdir -p lib ; \
+	   $(BOOT_DIR)/bin/jar cf lib/classes.jar $(LIVECONNECT_DIR) ; \
+	   cp -pPR $(SRC_DIR_LINK) $(LIVECONNECT_SRCS) src; \
+	   find src -type f -exec chmod 640 '{}' ';' -o -type d -exec chmod 750 '{}' ';'; \
+	   cd src ; \
+	   $(ZIP) -qr $(abs_top_builddir)/liveconnect/lib/src.zip $(LIVECONNECT_DIR) ) ; \
+	fi
+	mkdir -p stamps
+	touch $@
+
+clean-liveconnect:
+	rm -rf $(abs_top_builddir)/liveconnect
+	rm -f stamps/liveconnect-dist.stamp
+	rm -f liveconnect-source-files.txt
+	rm -f stamps/liveconnect.stamp
+
+# NetX
+# requires availability of OpenJDK source code including
+# a patch applied to sun.plugin.AppletViewerPanel and generated sources
+
+netx-source-files.txt:
+	find $(NETX_SRCDIR) -name '*.java' | sort > $@
+if !WITH_RHINO
+	sed -i '/RhinoBasedPacEvaluator/ d' $@
+endif
+
+stamps/netx.stamp: netx-source-files.txt stamps/bootstrap-directory.stamp
+	mkdir -p $(NETX_DIR)
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	    -d $(NETX_DIR) \
+	    -sourcepath $(NETX_SRCDIR) \
+	    -bootclasspath $(RUNTIME) \
+	    @netx-source-files.txt
+	(cd $(NETX_RESOURCE_DIR); \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} \
+	   $(NETX_DIR)/net/sourceforge/jnlp/resources/$${files}; \
+	 done)
+	cp -a $(NETX_SRCDIR)/net/sourceforge/jnlp/runtime/pac-funcs.js \
+	  $(NETX_DIR)/net/sourceforge/jnlp/runtime
+	cp -a build.properties $(NETX_DIR)/net/sourceforge/jnlp/
+	mkdir -p stamps
+	touch $@
+
+stamps/netx-dist.stamp: stamps/netx.stamp $(abs_top_builddir)/netx.manifest
+	(cd $(NETX_DIR) ; \
+	 mkdir -p lib ; \
+	 $(BOOT_DIR)/bin/jar cfm lib/classes.jar \
+	  $(abs_top_builddir)/netx.manifest javax/jnlp net ; \
+	 cp -pPR $(SRC_DIR_LINK) $(NETX_SRCDIR) src; \
+	 find src -type f -exec chmod 640 '{}' ';' -o -type d -exec chmod 750 '{}' ';'; \
+	 cd src ; \
+	 $(ZIP) -qr $(NETX_DIR)/lib/src.zip javax net )
+	mkdir -p stamps
+	touch $@
+
+clean-netx:
+	rm -rf $(NETX_DIR)
+	rm -f stamps/netx-dist.stamp
+	rm -f netx-source-files.txt
+	rm -f stamps/netx.stamp
+
+clean-desktop-files:
+	rm -f javaws.desktop
+	rm -f itweb-settings.desktop
+
+# extras -- used to create about.jar for javaws.
+extra-source-files.txt:
+	find $(abs_top_srcdir)/extra -name '*.java' | sort > $@
+
+stamps/extra-class-files.stamp: extra-source-files.txt stamps/netx.stamp
+	mkdir -p extra-lib
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) -d extra-lib \
+          -sourcepath $(abs_top_srcdir)/extra -cp netx.build \
+          -bootclasspath $(RUNTIME) @extra-source-files.txt
+	(cd $(NETX_EXTRA_DIR); \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} \
+	   $(NETX_EXTRA_DIST_DIR)/$${files}; \
+	 done)
+	mkdir -p stamps
+	touch $@
+
+clean-extra:
+	rm -rf extra-lib
+	rm -f stamps/extra-class-files.stamp
+	rm -f extra-source-files.txt
+
+extra-lib/about.jar: stamps/extra-class-files.stamp
+	$(BOOT_DIR)/bin/jar cf $@ -C extra-lib net ;
+
+launcher.build/$(javaws): launcher/javaws.in
+	mkdir -p launcher.build
+	$(edit_launcher_script) < $< > $@
+
+launcher.build/$(itweb_settings): launcher/itweb-settings.in
+	mkdir -p launcher.build
+	$(edit_launcher_script) < $< > $@
+
+clean-launchers:
+	rm -f launcher.build/$(javaws)
+	rm -f launcher.build/$(itweb_settings)
+	if [ -e launcher.build ] ; then \
+	  rmdir launcher.build ; \
+	fi
+
+javaws.desktop: javaws.desktop.in
+	sed "s#PATH_TO_JAVAWS#$(bindir)/$(javaws)#" < $(srcdir)/javaws.desktop.in > javaws.desktop
+
+itweb-settings.desktop: $(srcdir)/itweb-settings.desktop.in
+	sed "s#PATH_TO_ITWEB_SETTINGS#$(bindir)/$(itweb_settings)#" \
+	  < $(srcdir)/itweb-settings.desktop.in > itweb-settings.desktop
+
+# documentation
+
+stamps/docs.stamp: stamps/netx-docs.stamp stamps/plugin-docs.stamp
+	touch stamps/docs.stamp
+
+clean-docs: clean-netx-docs clean-plugin-docs
+	if [ -e ${abs_top_builddir}/docs ] ; then \
+	  rmdir ${abs_top_builddir}/docs ; \
+	fi
+	rm -f stamps/docs.stamp
+
+stamps/netx-docs.stamp: stamps/bootstrap-directory.stamp
+if ENABLE_DOCS
+	$(BOOT_DIR)/bin/javadoc $(JAVADOC_MEM_OPTS) $(JAVADOC_OPTS) \
+	 -d ${abs_top_builddir}/docs/netx -sourcepath $(NETX_SRCDIR) \
+	 -doctitle 'IcedTea-Web: NetX API Specification' \
+	 -windowtitle 'IcedTea-Web: NetX ' \
+	 -header '<strong>IcedTea-Web<br/>NetX</strong>' \
+	 $(NETX_PKGS)
+endif
+	mkdir -p stamps
+	touch stamps/netx-docs.stamp
+
+clean-netx-docs:
+	rm -rf ${abs_top_builddir}/docs/netx
+	rm -f stamps/netx-docs.stamp
+
+stamps/plugin-docs.stamp: stamps/bootstrap-directory.stamp
+if ENABLE_DOCS
+if ENABLE_PLUGIN
+	$(BOOT_DIR)/bin/javadoc $(JAVADOC_MEM_OPTS) $(JAVADOC_OPTS) \
+	 -d ${abs_top_builddir}/docs/plugin -sourcepath $(NETX_SRCDIR):$(LIVECONNECT_SRCS) \
+	 -doctitle 'IcedTea-Web: Plugin API Specification' \
+	 -windowtitle 'IcedTea-Web: Plugin ' \
+	 -header '<strong>IcedTea-Web<br/>Plugin</strong>' \
+	 $(PLUGIN_PKGS)
+endif
+endif
+	mkdir -p stamps
+	touch stamps/plugin-docs.stamp
+
+clean-plugin-docs:
+	rm -rf ${abs_top_builddir}/docs/plugin
+	rm -f stamps/plugin-docs.stamp
+
+
+# check
+# ==========================
+
+clean-tests: clean-netx-tests
+	if [ -e $(TESTS_DIR) ]; then \
+		rmdir $(TESTS_DIR) ; \
+	fi
+
+check-pac-functions: stamps/bootstrap-directory.stamp
+	./jrunscript $(abs_top_srcdir)/tests/netx/pac/pac-funcs-test.js \
+	  $$(readlink -f $(abs_top_srcdir)/netx/net/sourceforge/jnlp/runtime/pac-funcs.js)
+
+junit-runner-source-files.txt:
+	find $(JUNIT_RUNNER_SRCDIR) -name '*.java' | sort > $@
+
+$(JUNIT_RUNNER_JAR): junit-runner-source-files.txt
+	mkdir -p $(JUNIT_RUNNER_DIR) && \
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	  -d $(JUNIT_RUNNER_DIR) \
+	  -classpath $(JUNIT_JAR) \
+	  @junit-runner-source-files.txt && \
+	$(BOOT_DIR)/bin/jar cf $@  -C $(JUNIT_RUNNER_DIR) .
+
+netx-unit-tests-source-files.txt:
+	find $(NETX_UNIT_TEST_SRCDIR) -name '*.java' | sort > $@
+
+stamps/netx-unit-tests-compile.stamp: stamps/netx.stamp \
+ netx-unit-tests-source-files.txt
+	mkdir -p $(NETX_UNIT_TEST_DIR) && \
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	 -d $(NETX_UNIT_TEST_DIR) \
+	 -classpath $(JUNIT_JAR):$(NETX_DIR)/lib/classes.jar \
+	 @netx-unit-tests-source-files.txt && \
+	mkdir -p stamps && \
+	touch $@
+
+run-netx-unit-tests: stamps/netx-unit-tests-compile.stamp \
+ $(JUNIT_RUNNER_JAR)
+	cp {$(NETX_UNIT_TEST_SRCDIR),$(NETX_UNIT_TEST_DIR)}/net/sourceforge/jnlp/basic.jnlp
+	cd $(NETX_UNIT_TEST_DIR) ; \
+	class_names= ; \
+	for test in `find -type f` ; do \
+	  class_name=`echo $$test | sed -e 's|\.class$$||' -e 's|^\./||'` ; \
+	  class_name=`echo $$class_name | sed -e 's|/|.|g' ` ; \
+	  class_names="$$class_names $$class_name" ; \
+	done ; \
+	echo $$class_names ; \
+	CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):. \
+	  $(BOOT_DIR)/bin/java -Xbootclasspath:$(RUNTIME) CommandLine $$class_names
+
+clean-netx-tests: clean-netx-unit-tests clean-junit-runner
+	if [ -e $(TESTS_DIR)/netx ]; then \
+	  rmdir $(TESTS_DIR)/netx ; \
+	fi
+
+clean-junit-runner:
+	rm -f junit-runner-source-files.txt
+	rm -rf $(JUNIT_RUNNER_DIR)
+	rm -f $(JUNIT_RUNNER_JAR)
+
+clean-netx-unit-tests:
+	rm -f netx-unit-tests-source-files.txt
+	rm -rf $(NETX_UNIT_TEST_DIR)
+	rm -f stamps/netx-unit-tests-compile.stamp
+
+# plugin tests
+
+if ENABLE_PLUGIN
+stamps/plugin-tests.stamp: $(PLUGIN_TEST_SRCS) stamps/plugin.stamp
+	mkdir -p plugin/tests/LiveConnect
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	 -d plugin/tests/LiveConnect \
+	 -classpath liveconnect/lib/classes.jar \
+	 $(PLUGIN_TEST_SRCS) ;
+	$(BOOT_DIR)/bin/jar cf plugin/tests/LiveConnect/PluginTest.jar \
+	  plugin/tests/LiveConnect/*.class ;
+	cp -pPR $(SRC_DIR_LINK) $(abs_top_srcdir)/plugin/tests/LiveConnect/*.{js,html} \
+	  plugin/tests/LiveConnect ;
+	echo "Done. Now launch \"firefox file://`pwd`/index.html\"" ;
+	mkdir -p stamps
+	touch stamps/plugin-tests.stamp
+endif
+
+# Bootstrap Directory Targets
+# ===========================
+
+stamps/native-ecj.stamp: 
+	mkdir -p stamps ; \
+	if test "x$(GCJ)" != "xno"; then \
+	  $(GCJ) $(IT_CFLAGS) -Wl,-Bsymbolic -findirect-dispatch -o native-ecj \
+	    --main=org.eclipse.jdt.internal.compiler.batch.Main ${ECJ_JAR} ; \
+	fi ; \
+	touch stamps/native-ecj.stamp
+
+clean-native-ecj:
+	rm -f native-ecj
+	rm -rf stamps/native-ecj.stamp
+
+# bootstrap
+stamps/bootstrap-directory.stamp: stamps/native-ecj.stamp
+	mkdir -p $(BOOT_DIR)/bin stamps/
+	ln -sf $(JAVA) $(BOOT_DIR)/bin/java
+	ln -sf $(JAR) $(BOOT_DIR)/bin/jar
+	ln -sf $(abs_top_builddir)/javac $(BOOT_DIR)/bin/javac
+	ln -sf $(JAVADOC) $(BOOT_DIR)/bin/javadoc
+	mkdir -p $(BOOT_DIR)/jre/lib && \
+	ln -s $(SYSTEM_JRE_DIR)/lib/rt.jar $(BOOT_DIR)/jre/lib && \
+	if [ -e $(SYSTEM_JRE_DIR)/lib/jsse.jar ] ; then \
+	  ln -s $(SYSTEM_JRE_DIR)/lib/jsse.jar $(BOOT_DIR)/jre/lib ; \
+	else \
+	  ln -s rt.jar $(BOOT_DIR)/jre/lib/jsse.jar ; \
+	fi
+	ln -sf $(SYSTEM_JRE_DIR)/lib/$(JRE_ARCH_DIR) \
+	  $(BOOT_DIR)/jre/lib/ && \
+	if ! test -d $(BOOT_DIR)/jre/lib/$(INSTALL_ARCH_DIR); \
+	  then \
+	  ln -sf ./$(JRE_ARCH_DIR) \
+	    $(BOOT_DIR)/jre/lib/$(INSTALL_ARCH_DIR); \
+	fi;
+	mkdir -p $(BOOT_DIR)/include && \
+	for i in $(SYSTEM_JDK_DIR)/include/*; do \
+	  test -r $$i | continue; \
+	  i=`basename $$i`; \
+	  rm -f $(BOOT_DIR)/include/$$i; \
+	  ln -s $(SYSTEM_JDK_DIR)/include/$$i $(BOOT_DIR)/include/$$i; \
+	done
+	mkdir -p stamps
+	touch stamps/bootstrap-directory.stamp
+
+clean-bootstrap-directory:
+	rm -rf $(BOOT_DIR)
+	if [ -e ${abs_top_builddir}/bootstrap ] ; then \
+	  rmdir ${abs_top_builddir}/bootstrap ; \
+	fi
+	rm -f stamps/bootstrap-directory.stamp
+
+# Target Aliases
+# ===============
+
+add-netx: stamps/add-netx.stamp
+
+add-netx-debug: stamps/add-netx-debug.stamp
+
+netx: stamps/netx.stamp
+
+netx-dist: stamps/netx-dist.stamp
+
+plugin: stamps/plugin.stamp
+
+plugin-tests: stamps/plugin-tests.stamp
Index: /tags/icedtea-web/beta/Makefile.in
===================================================================
--- /tags/icedtea-web/beta/Makefile.in	(revision 403)
+++ /tags/icedtea-web/beta/Makefile.in	(revision 403)
@@ -0,0 +1,1043 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Source directories
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/build.properties.in \
+	$(srcdir)/javac.in $(srcdir)/jrunscript.in \
+	$(srcdir)/netx.manifest.in $(top_srcdir)/configure AUTHORS \
+	COPYING ChangeLog INSTALL NEWS config.guess config.sub \
+	install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES = netx.manifest javac jrunscript build.properties
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d "$(distdir)" \
+    || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr "$(distdir)"; }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+ARCHFLAG = @ARCHFLAG@
+ARCH_PREFIX = @ARCH_PREFIX@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_ARCH_DIR = @BUILD_ARCH_DIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+ECJ = @ECJ@
+ECJ_JAR = @ECJ_JAR@
+EXEEXT = @EXEEXT@
+FULL_VERSION = @FULL_VERSION@
+GCJ = @GCJ@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+HG = @HG@
+ICEDTEA_REVISION = @ICEDTEA_REVISION@
+INSTALL = @INSTALL@
+INSTALL_ARCH_DIR = @INSTALL_ARCH_DIR@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAR_ACCEPTS_STDIN_LIST = @JAR_ACCEPTS_STDIN_LIST@
+JAR_KNOWS_ATFILE = @JAR_KNOWS_ATFILE@
+JAR_KNOWS_J_OPTIONS = @JAR_KNOWS_J_OPTIONS@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+JAVADOC = @JAVADOC@
+JAVADOC_KNOWS_J_OPTIONS = @JAVADOC_KNOWS_J_OPTIONS@
+JRE_ARCH_DIR = @JRE_ARCH_DIR@
+JUNIT_AVAILABLE = @JUNIT_AVAILABLE@
+JUNIT_JAR = @JUNIT_JAR@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MOZILLA_CFLAGS = @MOZILLA_CFLAGS@
+MOZILLA_LIBS = @MOZILLA_LIBS@
+MOZILLA_VERSION_COLLAPSED = @MOZILLA_VERSION_COLLAPSED@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGVERSION = @PKGVERSION@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RHINO_AVAILABLE = @RHINO_AVAILABLE@
+RHINO_JAR = @RHINO_JAR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_JDK_DIR = @SYSTEM_JDK_DIR@
+SYSTEM_JRE_DIR = @SYSTEM_JRE_DIR@
+USING_ECJ = @USING_ECJ@
+VERSION = @VERSION@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZIP = @ZIP@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NETX_DIR = $(abs_top_builddir)/netx.build
+NETX_SRCDIR = $(abs_top_srcdir)/netx
+NETX_RESOURCE_DIR = $(NETX_SRCDIR)/net/sourceforge/jnlp/resources
+NETX_EXTRA_DIR = $(abs_top_srcdir)/extra/net/sourceforge/javaws/about/resources
+NETX_EXTRA_DIST_DIR = $(abs_top_builddir)/extra-lib/net/sourceforge/javaws/about/resources
+TESTS_SRCDIR = $(abs_top_srcdir)/tests
+TESTS_DIR = $(abs_top_builddir)/tests.build
+NETX_UNIT_TEST_SRCDIR = $(TESTS_SRCDIR)/netx/unit
+NETX_UNIT_TEST_DIR = $(TESTS_DIR)/netx/unit
+JUNIT_RUNNER_DIR = $(TESTS_DIR)/junit-runner
+JUNIT_RUNNER_SRCDIR = $(TESTS_SRCDIR)/junit-runner
+JUNIT_RUNNER_JAR = $(abs_top_builddir)/junit-runner.jar
+
+# Build directories
+BOOT_DIR = $(abs_top_builddir)/bootstrap/jdk1.6.0
+@WITH_RHINO_FALSE@RHINO_RUNTIME = 
+@WITH_RHINO_TRUE@RHINO_RUNTIME = :$(RHINO_JAR)
+RUNTIME = $(BOOT_DIR)/jre/lib/rt.jar:$(BOOT_DIR)/jre/lib/jsse.jar$(RHINO_RUNTIME)
+
+# Flags
+IT_CFLAGS = $(CFLAGS) $(ARCHFLAG)
+IT_JAVAC_SETTINGS = -g -encoding utf-8 $(JAVACFLAGS) $(MEMORY_LIMIT) $(PREFER_SOURCE)
+IT_LANGUAGE_SOURCE_VERSION = 6
+IT_CLASS_TARGET_VERSION = 6
+IT_JAVACFLAGS = $(IT_JAVAC_SETTINGS) -source $(IT_LANGUAGE_SOURCE_VERSION) -target $(IT_CLASS_TARGET_VERSION)
+
+#
+# We need the jars in bootclasspath for a couple of reasons
+#  - we use classes (in the sun.applet package) loaded by the bootclassloader
+#    using another classloader to load classes from the same package causes an
+#    IllegalAccessException
+#  - we want full privileges
+#
+LAUNCHER_BOOTCLASSPATH = "-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar$(RHINO_RUNTIME)"
+PLUGIN_BOOTCLASSPATH = '"-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar:$(datadir)/$(PACKAGE_NAME)/plugin.jar$(RHINO_RUNTIME)"'
+
+# Fake update version to work with the Deployment Toolkit script used by Oracle
+# http://download.oracle.com/javase/tutorial/deployment/deploymentInDepth/depltoolkit_index.html
+JDK_UPDATE_VERSION = 50
+
+# Sources list
+PLUGIN_TEST_SRCS = $(abs_top_srcdir)/plugin/tests/LiveConnect/*.java
+NETX_PKGS = javax.jnlp net.sourceforge.nanoxml net.sourceforge.jnlp \
+	net.sourceforge.jnlp.cache net.sourceforge.jnlp.config \
+	net.sourceforge.jnlp.controlpanel net.sourceforge.jnlp.event \
+	net.sourceforge.jnlp.runtime net.sourceforge.jnlp.security \
+	net.sourceforge.jnlp.security.viewer net.sourceforge.jnlp.services \
+	net.sourceforge.jnlp.tools net.sourceforge.jnlp.util
+
+
+# Conditional defintions
+@ENABLE_PLUGIN_TRUE@ICEDTEAPLUGIN_CLEAN = clean-IcedTeaPlugin
+@ENABLE_PLUGIN_TRUE@LIVECONNECT_DIR = netscape sun/applet
+@ENABLE_PLUGIN_TRUE@PLUGIN_DIR = $(abs_top_builddir)/plugin/icedteanp
+@ENABLE_PLUGIN_TRUE@PLUGIN_SRCDIR = $(abs_top_srcdir)/plugin/icedteanp
+@ENABLE_PLUGIN_TRUE@LIVECONNECT_SRCS = $(PLUGIN_SRCDIR)/java
+@ENABLE_PLUGIN_TRUE@ICEDTEAPLUGIN_TARGET = $(PLUGIN_DIR)/IcedTeaPlugin.so stamps/liveconnect-dist.stamp
+@ENABLE_PLUGIN_TRUE@PLUGIN_PKGS = sun.applet netscape.security netscape.javascript
+@CP_SUPPORTS_REFLINK_TRUE@REFLINK = --reflink=auto
+@SRC_DIR_HARDLINKABLE_FALSE@SRC_DIR_LINK = $(REFLINK)
+@SRC_DIR_HARDLINKABLE_TRUE@SRC_DIR_LINK = -l
+@ENABLE_DOCS_TRUE@JAVADOC_OPTS = -use -keywords -encoding UTF-8 -splitIndex \
+@ENABLE_DOCS_TRUE@ -bottom '<font size="-1"> <a href="http://icedtea.classpath.org/bugzilla">Submit a bug or feature</a></font>'
+
+@ENABLE_DOCS_TRUE@@JAVADOC_SUPPORTS_J_OPTIONS_TRUE@JAVADOC_MEM_OPTS = -J-Xmx1024m -J-Xms128m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m
+@WITH_RHINO_FALSE@RHINO_TESTS = 
+@WITH_RHINO_TRUE@RHINO_TESTS = check-pac-functions
+@WITH_JUNIT_FALSE@JUNIT_TESTS = 
+@WITH_JUNIT_TRUE@JUNIT_TESTS = run-netx-unit-tests
+PLUGIN_VERSION = IcedTea-Web $(FULL_VERSION)
+EXTRA_DIST = $(top_srcdir)/netx $(top_srcdir)/plugin javaws.png javaws.desktop.in extra launcher \
+ itweb-settings.desktop.in $(top_srcdir)/tests
+
+
+# binary names
+javaws := $(shell echo javaws | sed '@program_transform_name@')
+itweb_settings := $(shell echo itweb-settings | sed '@program_transform_name@')
+
+# the launcher needs to know $(bindir) and $(datadir) which can be different at
+# make-time from configure-time
+edit_launcher_script = sed \
+  -e 's|[@]LAUNCHER_BOOTCLASSPATH[@]|$(LAUNCHER_BOOTCLASSPATH)|g' \
+  -e 's|[@]JAVAWS_BIN_LOCATION[@]|$(bindir)/$(javaws)|g' \
+  -e 's|[@]ITWEB_SETTINGS_BIN_LOCATION[@]|$(bindir)/$(itweb_settings)|g' \
+  -e 's|[@]JAVA[@]|$(JAVA)|g' \
+  -e 's|[@]JRE[@]|$(SYSTEM_JRE_DIR)|g'
+
+
+# Plugin
+
+# IcedTeaPlugin.so.
+# Separate compile and link invocations to ensure intermediate object
+# is listed before -l options.  See:
+# http://developer.mozilla.org/en/docs/XPCOM_Glue
+@ENABLE_PLUGIN_TRUE@PLUGIN_SRC = IcedTeaNPPlugin.cc IcedTeaScriptablePluginObject.cc \
+@ENABLE_PLUGIN_TRUE@        IcedTeaJavaRequestProcessor.cc IcedTeaPluginRequestProcessor.cc \
+@ENABLE_PLUGIN_TRUE@		IcedTeaPluginUtils.cc
+
+@ENABLE_PLUGIN_TRUE@PLUGIN_OBJECTS = IcedTeaNPPlugin.o IcedTeaScriptablePluginObject.o \
+@ENABLE_PLUGIN_TRUE@        IcedTeaJavaRequestProcessor.o IcedTeaPluginRequestProcessor.o \
+@ENABLE_PLUGIN_TRUE@		IcedTeaPluginUtils.o
+
+all: all-am
+
+.SUFFIXES:
+am--refresh:
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+netx.manifest: $(top_builddir)/config.status $(srcdir)/netx.manifest.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+javac: $(top_builddir)/config.status $(srcdir)/javac.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+jrunscript: $(top_builddir)/config.status $(srcdir)/jrunscript.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+build.properties: $(top_builddir)/config.status $(srcdir)/build.properties.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d "$(distdir)" || mkdir "$(distdir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	-test -n "$(am__skip_mode_fix)" \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+	$(am__remove_distdir)
+
+dist-lzma: distdir
+	tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+	$(am__remove_distdir)
+
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+	$(am__remove_distdir)
+
+dist-tarZ: distdir
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__remove_distdir)
+
+dist-shar: distdir
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lzma*) \
+	  lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	test -d $(distdir)/_build || exit 0; \
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && am__cwd=`pwd` \
+	  && $(am__cd) $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+	  && cd "$$am__cwd" \
+	  || exit 1
+	$(am__remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@$(am__cd) '$(distuninstallcheck_dir)' \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am all-local am--refresh check check-am check-local \
+	clean clean-generic clean-local dist dist-all dist-bzip2 \
+	dist-gzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \
+	distcheck distclean distclean-generic distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am \
+	install-data-local install-dvi install-dvi-am install-exec \
+	install-exec-am install-exec-local install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
+	uninstall-local
+
+
+# Top-Level Targets
+# =================
+
+all-local: stamps/netx-dist.stamp extra-lib/about.jar stamps/plugin.stamp launcher.build/$(javaws) \
+ javaws.desktop stamps/docs.stamp launcher.build/$(itweb_settings) itweb-settings.desktop
+
+check-local: $(RHINO_TESTS) $(JUNIT_TESTS)
+
+clean-local: clean-netx clean-plugin clean-liveconnect clean-extra clean-bootstrap-directory \
+ clean-native-ecj clean-launchers clean-desktop-files clean-docs clean-tests
+	if [ -e stamps ] ; then \
+	  rmdir stamps ; \
+	fi
+
+.PHONY: clean-IcedTeaPlugin clean-add-netx clean-add-netx-debug clean-add-plugin clean-add-plugin-debug \
+ clean-bootstrap-directory clean-native-ecj clean-desktop-files clean-netx-docs clean-docs clean-plugin-docs \
+ clean-tests check-local clean-launchers check-pac-functions run-netx-unit-tests clean-netx-tests \
+ clean-junit-runner clean-netx-unit-tests
+
+install-exec-local:
+	${mkinstalldirs} $(DESTDIR)$(bindir) $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/ $(DESTDIR)$(libdir)
+@ENABLE_PLUGIN_TRUE@	${INSTALL_PROGRAM} $(PLUGIN_DIR)/IcedTeaPlugin.so $(DESTDIR)$(libdir)
+@ENABLE_PLUGIN_TRUE@	${INSTALL_DATA} $(abs_top_builddir)/liveconnect/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar
+	${INSTALL_DATA} $(NETX_DIR)/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar
+	${INSTALL_PROGRAM} launcher.build/$(javaws) $(DESTDIR)$(bindir)
+	${INSTALL_DATA} extra-lib/about.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jar
+	${INSTALL_PROGRAM} launcher.build/$(itweb_settings) $(DESTDIR)$(bindir)
+
+install-data-local:
+	${mkinstalldirs} -d $(DESTDIR)$(mandir)/man1
+	${INSTALL_DATA} $(NETX_SRCDIR)/javaws.1 $(DESTDIR)$(mandir)/man1
+	${INSTALL_DATA} $(NETX_RESOURCE_DIR)/about.jnlp $(DESTDIR)$(datarootdir)/$(PACKAGE_NAME)
+@ENABLE_DOCS_TRUE@	${mkinstalldirs} $(DESTDIR)$(htmldir)
+@ENABLE_DOCS_TRUE@	(cd ${abs_top_builddir}/docs/netx; \
+@ENABLE_DOCS_TRUE@	 for files in $$(find . -type f); \
+@ENABLE_DOCS_TRUE@	 do \
+@ENABLE_DOCS_TRUE@	   ${INSTALL_DATA} -D $${files} $(DESTDIR)$(htmldir)/netx/$${files}; \
+@ENABLE_DOCS_TRUE@	 done)
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	(cd ${abs_top_builddir}/docs/plugin; \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 for files in $$(find . -type f); \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 do \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	   ${INSTALL_DATA} -D $${files} $(DESTDIR)$(htmldir)/plugin/$${files}; \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 done)
+
+uninstall-local:
+	rm -f $(DESTDIR)$(libdir)/IcedTeaPlugin.so
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jnlp
+	rm -f $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jar
+	rm -f $(DESTDIR)$(mandir)/man1/javaws.1
+	rm -f $(DESTDIR)$(bindir)/$(javaws)
+	rm -f $(DESTDIR)$(bindir)/$(itweb_settings)
+	rm -rf $(DESTDIR)$(htmldir)
+
+@ENABLE_PLUGIN_TRUE@$(PLUGIN_DIR)/%.o: $(PLUGIN_SRCDIR)/%.cc
+@ENABLE_PLUGIN_TRUE@	mkdir -p $(PLUGIN_DIR) && \
+@ENABLE_PLUGIN_TRUE@	cd $(PLUGIN_DIR) && \
+@ENABLE_PLUGIN_TRUE@	$(CXX) $(CXXFLAGS) \
+@ENABLE_PLUGIN_TRUE@	  -DJDK_UPDATE_VERSION="\"$(JDK_UPDATE_VERSION)\"" \
+@ENABLE_PLUGIN_TRUE@	  -DPLUGIN_NAME="\"IcedTea-Web Plugin\"" \
+@ENABLE_PLUGIN_TRUE@	  -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \
+@ENABLE_PLUGIN_TRUE@	  -DPACKAGE_URL="\"$(PACKAGE_URL)\"" \
+@ENABLE_PLUGIN_TRUE@	  -DMOZILLA_VERSION_COLLAPSED="$(MOZILLA_VERSION_COLLAPSED)" \
+@ENABLE_PLUGIN_TRUE@	  -DICEDTEA_WEB_JRE="\"$(SYSTEM_JRE_DIR)\"" \
+@ENABLE_PLUGIN_TRUE@	  -DPLUGIN_BOOTCLASSPATH=$(PLUGIN_BOOTCLASSPATH) \
+@ENABLE_PLUGIN_TRUE@	  $(GLIB_CFLAGS) \
+@ENABLE_PLUGIN_TRUE@	  $(GTK_CFLAGS) \
+@ENABLE_PLUGIN_TRUE@	  $(MOZILLA_CFLAGS) \
+@ENABLE_PLUGIN_TRUE@	  -fPIC -o $@ -c $<
+
+@ENABLE_PLUGIN_TRUE@$(PLUGIN_DIR)/IcedTeaPlugin.so: $(addprefix $(PLUGIN_DIR)/,$(PLUGIN_OBJECTS))
+@ENABLE_PLUGIN_TRUE@	cd $(PLUGIN_DIR) && \
+@ENABLE_PLUGIN_TRUE@	$(CXX) $(CXXFLAGS) \
+@ENABLE_PLUGIN_TRUE@	  $(PLUGIN_OBJECTS) \
+@ENABLE_PLUGIN_TRUE@	  $(GLIB_LIBS) \
+@ENABLE_PLUGIN_TRUE@	  $(GTK_LIBS) \
+@ENABLE_PLUGIN_TRUE@	  $(MOZILLA_LIBS)\
+@ENABLE_PLUGIN_TRUE@	  -shared -o $@
+
+@ENABLE_PLUGIN_TRUE@clean-IcedTeaPlugin:
+@ENABLE_PLUGIN_TRUE@	rm -f $(PLUGIN_DIR)/*.o
+@ENABLE_PLUGIN_TRUE@	rm -f $(PLUGIN_DIR)/IcedTeaPlugin.so
+@ENABLE_PLUGIN_TRUE@	if [ $(abs_top_srcdir) != $(abs_top_builddir) ]; then \
+@ENABLE_PLUGIN_TRUE@	  if [ -e $(abs_top_builddir)/plugin/icedteanp ] ; then \
+@ENABLE_PLUGIN_TRUE@	    rmdir $(abs_top_builddir)/plugin/icedteanp ; \
+@ENABLE_PLUGIN_TRUE@	    rmdir $(abs_top_builddir)/plugin ; \
+@ENABLE_PLUGIN_TRUE@	  fi ; \
+@ENABLE_PLUGIN_TRUE@	fi
+
+stamps/plugin.stamp: $(ICEDTEAPLUGIN_TARGET)
+	mkdir -p stamps
+	touch stamps/plugin.stamp
+
+clean-plugin: $(ICEDTEAPLUGIN_CLEAN)
+	rm -f stamps/plugin.stamp
+
+liveconnect-source-files.txt:
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  find $(LIVECONNECT_SRCS) -name '*.java' | sort > $@ ; \
+	  sed -i '/_OS2/ d' $@
+	fi
+	touch $@
+
+stamps/liveconnect.stamp: liveconnect-source-files.txt stamps/netx.stamp
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  mkdir -p $(abs_top_builddir)/liveconnect && \
+	  $(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	      -d $(abs_top_builddir)/liveconnect \
+	      -bootclasspath $(NETX_DIR):$(RUNTIME) \
+	      -sourcepath $(LIVECONNECT_SRCS) \
+	      @liveconnect-source-files.txt ; \
+	fi
+	mkdir -p stamps
+	touch $@
+
+stamps/liveconnect-dist.stamp: stamps/liveconnect.stamp
+	if test "x${LIVECONNECT_DIR}" != x; then \
+	  (cd $(abs_top_builddir)/liveconnect ; \
+	   mkdir -p lib ; \
+	   $(BOOT_DIR)/bin/jar cf lib/classes.jar $(LIVECONNECT_DIR) ; \
+	   cp -pPR $(SRC_DIR_LINK) $(LIVECONNECT_SRCS) src; \
+	   find src -type f -exec chmod 640 '{}' ';' -o -type d -exec chmod 750 '{}' ';'; \
+	   cd src ; \
+	   $(ZIP) -qr $(abs_top_builddir)/liveconnect/lib/src.zip $(LIVECONNECT_DIR) ) ; \
+	fi
+	mkdir -p stamps
+	touch $@
+
+clean-liveconnect:
+	rm -rf $(abs_top_builddir)/liveconnect
+	rm -f stamps/liveconnect-dist.stamp
+	rm -f liveconnect-source-files.txt
+	rm -f stamps/liveconnect.stamp
+
+# NetX
+# requires availability of OpenJDK source code including
+# a patch applied to sun.plugin.AppletViewerPanel and generated sources
+
+netx-source-files.txt:
+	find $(NETX_SRCDIR) -name '*.java' | sort > $@
+@WITH_RHINO_FALSE@	sed -i '/RhinoBasedPacEvaluator/ d' $@
+
+stamps/netx.stamp: netx-source-files.txt stamps/bootstrap-directory.stamp
+	mkdir -p $(NETX_DIR)
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	    -d $(NETX_DIR) \
+	    -sourcepath $(NETX_SRCDIR) \
+	    -bootclasspath $(RUNTIME) \
+	    @netx-source-files.txt
+	(cd $(NETX_RESOURCE_DIR); \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} \
+	   $(NETX_DIR)/net/sourceforge/jnlp/resources/$${files}; \
+	 done)
+	cp -a $(NETX_SRCDIR)/net/sourceforge/jnlp/runtime/pac-funcs.js \
+	  $(NETX_DIR)/net/sourceforge/jnlp/runtime
+	cp -a build.properties $(NETX_DIR)/net/sourceforge/jnlp/
+	mkdir -p stamps
+	touch $@
+
+stamps/netx-dist.stamp: stamps/netx.stamp $(abs_top_builddir)/netx.manifest
+	(cd $(NETX_DIR) ; \
+	 mkdir -p lib ; \
+	 $(BOOT_DIR)/bin/jar cfm lib/classes.jar \
+	  $(abs_top_builddir)/netx.manifest javax/jnlp net ; \
+	 cp -pPR $(SRC_DIR_LINK) $(NETX_SRCDIR) src; \
+	 find src -type f -exec chmod 640 '{}' ';' -o -type d -exec chmod 750 '{}' ';'; \
+	 cd src ; \
+	 $(ZIP) -qr $(NETX_DIR)/lib/src.zip javax net )
+	mkdir -p stamps
+	touch $@
+
+clean-netx:
+	rm -rf $(NETX_DIR)
+	rm -f stamps/netx-dist.stamp
+	rm -f netx-source-files.txt
+	rm -f stamps/netx.stamp
+
+clean-desktop-files:
+	rm -f javaws.desktop
+	rm -f itweb-settings.desktop
+
+# extras -- used to create about.jar for javaws.
+extra-source-files.txt:
+	find $(abs_top_srcdir)/extra -name '*.java' | sort > $@
+
+stamps/extra-class-files.stamp: extra-source-files.txt stamps/netx.stamp
+	mkdir -p extra-lib
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) -d extra-lib \
+          -sourcepath $(abs_top_srcdir)/extra -cp netx.build \
+          -bootclasspath $(RUNTIME) @extra-source-files.txt
+	(cd $(NETX_EXTRA_DIR); \
+	 for files in $$(find . -type f); \
+	 do \
+	   ${INSTALL_DATA} -D $${files} \
+	   $(NETX_EXTRA_DIST_DIR)/$${files}; \
+	 done)
+	mkdir -p stamps
+	touch $@
+
+clean-extra:
+	rm -rf extra-lib
+	rm -f stamps/extra-class-files.stamp
+	rm -f extra-source-files.txt
+
+extra-lib/about.jar: stamps/extra-class-files.stamp
+	$(BOOT_DIR)/bin/jar cf $@ -C extra-lib net ;
+
+launcher.build/$(javaws): launcher/javaws.in
+	mkdir -p launcher.build
+	$(edit_launcher_script) < $< > $@
+
+launcher.build/$(itweb_settings): launcher/itweb-settings.in
+	mkdir -p launcher.build
+	$(edit_launcher_script) < $< > $@
+
+clean-launchers:
+	rm -f launcher.build/$(javaws)
+	rm -f launcher.build/$(itweb_settings)
+	if [ -e launcher.build ] ; then \
+	  rmdir launcher.build ; \
+	fi
+
+javaws.desktop: javaws.desktop.in
+	sed "s#PATH_TO_JAVAWS#$(bindir)/$(javaws)#" < $(srcdir)/javaws.desktop.in > javaws.desktop
+
+itweb-settings.desktop: $(srcdir)/itweb-settings.desktop.in
+	sed "s#PATH_TO_ITWEB_SETTINGS#$(bindir)/$(itweb_settings)#" \
+	  < $(srcdir)/itweb-settings.desktop.in > itweb-settings.desktop
+
+# documentation
+
+stamps/docs.stamp: stamps/netx-docs.stamp stamps/plugin-docs.stamp
+	touch stamps/docs.stamp
+
+clean-docs: clean-netx-docs clean-plugin-docs
+	if [ -e ${abs_top_builddir}/docs ] ; then \
+	  rmdir ${abs_top_builddir}/docs ; \
+	fi
+	rm -f stamps/docs.stamp
+
+stamps/netx-docs.stamp: stamps/bootstrap-directory.stamp
+@ENABLE_DOCS_TRUE@	$(BOOT_DIR)/bin/javadoc $(JAVADOC_MEM_OPTS) $(JAVADOC_OPTS) \
+@ENABLE_DOCS_TRUE@	 -d ${abs_top_builddir}/docs/netx -sourcepath $(NETX_SRCDIR) \
+@ENABLE_DOCS_TRUE@	 -doctitle 'IcedTea-Web: NetX API Specification' \
+@ENABLE_DOCS_TRUE@	 -windowtitle 'IcedTea-Web: NetX ' \
+@ENABLE_DOCS_TRUE@	 -header '<strong>IcedTea-Web<br/>NetX</strong>' \
+@ENABLE_DOCS_TRUE@	 $(NETX_PKGS)
+	mkdir -p stamps
+	touch stamps/netx-docs.stamp
+
+clean-netx-docs:
+	rm -rf ${abs_top_builddir}/docs/netx
+	rm -f stamps/netx-docs.stamp
+
+stamps/plugin-docs.stamp: stamps/bootstrap-directory.stamp
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	$(BOOT_DIR)/bin/javadoc $(JAVADOC_MEM_OPTS) $(JAVADOC_OPTS) \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 -d ${abs_top_builddir}/docs/plugin -sourcepath $(NETX_SRCDIR):$(LIVECONNECT_SRCS) \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 -doctitle 'IcedTea-Web: Plugin API Specification' \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 -windowtitle 'IcedTea-Web: Plugin ' \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 -header '<strong>IcedTea-Web<br/>Plugin</strong>' \
+@ENABLE_DOCS_TRUE@@ENABLE_PLUGIN_TRUE@	 $(PLUGIN_PKGS)
+	mkdir -p stamps
+	touch stamps/plugin-docs.stamp
+
+clean-plugin-docs:
+	rm -rf ${abs_top_builddir}/docs/plugin
+	rm -f stamps/plugin-docs.stamp
+
+# check
+# ==========================
+
+clean-tests: clean-netx-tests
+	if [ -e $(TESTS_DIR) ]; then \
+		rmdir $(TESTS_DIR) ; \
+	fi
+
+check-pac-functions: stamps/bootstrap-directory.stamp
+	./jrunscript $(abs_top_srcdir)/tests/netx/pac/pac-funcs-test.js \
+	  $$(readlink -f $(abs_top_srcdir)/netx/net/sourceforge/jnlp/runtime/pac-funcs.js)
+
+junit-runner-source-files.txt:
+	find $(JUNIT_RUNNER_SRCDIR) -name '*.java' | sort > $@
+
+$(JUNIT_RUNNER_JAR): junit-runner-source-files.txt
+	mkdir -p $(JUNIT_RUNNER_DIR) && \
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	  -d $(JUNIT_RUNNER_DIR) \
+	  -classpath $(JUNIT_JAR) \
+	  @junit-runner-source-files.txt && \
+	$(BOOT_DIR)/bin/jar cf $@  -C $(JUNIT_RUNNER_DIR) .
+
+netx-unit-tests-source-files.txt:
+	find $(NETX_UNIT_TEST_SRCDIR) -name '*.java' | sort > $@
+
+stamps/netx-unit-tests-compile.stamp: stamps/netx.stamp \
+ netx-unit-tests-source-files.txt
+	mkdir -p $(NETX_UNIT_TEST_DIR) && \
+	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+	 -d $(NETX_UNIT_TEST_DIR) \
+	 -classpath $(JUNIT_JAR):$(NETX_DIR)/lib/classes.jar \
+	 @netx-unit-tests-source-files.txt && \
+	mkdir -p stamps && \
+	touch $@
+
+run-netx-unit-tests: stamps/netx-unit-tests-compile.stamp \
+ $(JUNIT_RUNNER_JAR)
+	cp {$(NETX_UNIT_TEST_SRCDIR),$(NETX_UNIT_TEST_DIR)}/net/sourceforge/jnlp/basic.jnlp
+	cd $(NETX_UNIT_TEST_DIR) ; \
+	class_names= ; \
+	for test in `find -type f` ; do \
+	  class_name=`echo $$test | sed -e 's|\.class$$||' -e 's|^\./||'` ; \
+	  class_name=`echo $$class_name | sed -e 's|/|.|g' ` ; \
+	  class_names="$$class_names $$class_name" ; \
+	done ; \
+	echo $$class_names ; \
+	CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):. \
+	  $(BOOT_DIR)/bin/java -Xbootclasspath:$(RUNTIME) CommandLine $$class_names
+
+clean-netx-tests: clean-netx-unit-tests clean-junit-runner
+	if [ -e $(TESTS_DIR)/netx ]; then \
+	  rmdir $(TESTS_DIR)/netx ; \
+	fi
+
+clean-junit-runner:
+	rm -f junit-runner-source-files.txt
+	rm -rf $(JUNIT_RUNNER_DIR)
+	rm -f $(JUNIT_RUNNER_JAR)
+
+clean-netx-unit-tests:
+	rm -f netx-unit-tests-source-files.txt
+	rm -rf $(NETX_UNIT_TEST_DIR)
+	rm -f stamps/netx-unit-tests-compile.stamp
+
+# plugin tests
+
+@ENABLE_PLUGIN_TRUE@stamps/plugin-tests.stamp: $(PLUGIN_TEST_SRCS) stamps/plugin.stamp
+@ENABLE_PLUGIN_TRUE@	mkdir -p plugin/tests/LiveConnect
+@ENABLE_PLUGIN_TRUE@	$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
+@ENABLE_PLUGIN_TRUE@	 -d plugin/tests/LiveConnect \
+@ENABLE_PLUGIN_TRUE@	 -classpath liveconnect/lib/classes.jar \
+@ENABLE_PLUGIN_TRUE@	 $(PLUGIN_TEST_SRCS) ;
+@ENABLE_PLUGIN_TRUE@	$(BOOT_DIR)/bin/jar cf plugin/tests/LiveConnect/PluginTest.jar \
+@ENABLE_PLUGIN_TRUE@	  plugin/tests/LiveConnect/*.class ;
+@ENABLE_PLUGIN_TRUE@	cp -pPR $(SRC_DIR_LINK) $(abs_top_srcdir)/plugin/tests/LiveConnect/*.{js,html} \
+@ENABLE_PLUGIN_TRUE@	  plugin/tests/LiveConnect ;
+@ENABLE_PLUGIN_TRUE@	echo "Done. Now launch \"firefox file://`pwd`/index.html\"" ;
+@ENABLE_PLUGIN_TRUE@	mkdir -p stamps
+@ENABLE_PLUGIN_TRUE@	touch stamps/plugin-tests.stamp
+
+# Bootstrap Directory Targets
+# ===========================
+
+stamps/native-ecj.stamp: 
+	mkdir -p stamps ; \
+	if test "x$(GCJ)" != "xno"; then \
+	  $(GCJ) $(IT_CFLAGS) -Wl,-Bsymbolic -findirect-dispatch -o native-ecj \
+	    --main=org.eclipse.jdt.internal.compiler.batch.Main ${ECJ_JAR} ; \
+	fi ; \
+	touch stamps/native-ecj.stamp
+
+clean-native-ecj:
+	rm -f native-ecj
+	rm -rf stamps/native-ecj.stamp
+
+# bootstrap
+stamps/bootstrap-directory.stamp: stamps/native-ecj.stamp
+	mkdir -p $(BOOT_DIR)/bin stamps/
+	ln -sf $(JAVA) $(BOOT_DIR)/bin/java
+	ln -sf $(JAR) $(BOOT_DIR)/bin/jar
+	ln -sf $(abs_top_builddir)/javac $(BOOT_DIR)/bin/javac
+	ln -sf $(JAVADOC) $(BOOT_DIR)/bin/javadoc
+	mkdir -p $(BOOT_DIR)/jre/lib && \
+	ln -s $(SYSTEM_JRE_DIR)/lib/rt.jar $(BOOT_DIR)/jre/lib && \
+	if [ -e $(SYSTEM_JRE_DIR)/lib/jsse.jar ] ; then \
+	  ln -s $(SYSTEM_JRE_DIR)/lib/jsse.jar $(BOOT_DIR)/jre/lib ; \
+	else \
+	  ln -s rt.jar $(BOOT_DIR)/jre/lib/jsse.jar ; \
+	fi
+	ln -sf $(SYSTEM_JRE_DIR)/lib/$(JRE_ARCH_DIR) \
+	  $(BOOT_DIR)/jre/lib/ && \
+	if ! test -d $(BOOT_DIR)/jre/lib/$(INSTALL_ARCH_DIR); \
+	  then \
+	  ln -sf ./$(JRE_ARCH_DIR) \
+	    $(BOOT_DIR)/jre/lib/$(INSTALL_ARCH_DIR); \
+	fi;
+	mkdir -p $(BOOT_DIR)/include && \
+	for i in $(SYSTEM_JDK_DIR)/include/*; do \
+	  test -r $$i | continue; \
+	  i=`basename $$i`; \
+	  rm -f $(BOOT_DIR)/include/$$i; \
+	  ln -s $(SYSTEM_JDK_DIR)/include/$$i $(BOOT_DIR)/include/$$i; \
+	done
+	mkdir -p stamps
+	touch stamps/bootstrap-directory.stamp
+
+clean-bootstrap-directory:
+	rm -rf $(BOOT_DIR)
+	if [ -e ${abs_top_builddir}/bootstrap ] ; then \
+	  rmdir ${abs_top_builddir}/bootstrap ; \
+	fi
+	rm -f stamps/bootstrap-directory.stamp
+
+# Target Aliases
+# ===============
+
+add-netx: stamps/add-netx.stamp
+
+add-netx-debug: stamps/add-netx-debug.stamp
+
+netx: stamps/netx.stamp
+
+netx-dist: stamps/netx-dist.stamp
+
+plugin: stamps/plugin.stamp
+
+plugin-tests: stamps/plugin-tests.stamp
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /tags/icedtea-web/beta/Makefile.kmk
===================================================================
--- /tags/icedtea-web/beta/Makefile.kmk	(revision 403)
+++ /tags/icedtea-web/beta/Makefile.kmk	(revision 403)
@@ -0,0 +1,13 @@
+## @file
+#
+
+SUB_DEPTH = .
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Include sub-makefiles.
+#
+include $(PATH_SUB_CURRENT)/netx/Makefile.kmk
+include $(PATH_SUB_CURRENT)/plugin/Makefile.kmk
+
+include $(FILE_KBUILD_SUB_FOOTER)
Index: /tags/icedtea-web/beta/NEWS
===================================================================
--- /tags/icedtea-web/beta/NEWS	(revision 403)
+++ /tags/icedtea-web/beta/NEWS	(revision 403)
@@ -0,0 +1,74 @@
+Key:
+
+SX  - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=X
+PRX - http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=X
+RHX - https://bugzilla.redhat.com/show_bug.cgi?id=X
+DX  - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=X
+GX  - http://bugs.gentoo.org/show_bug.cgi?id=X
+
+CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY
+
+New in release 1.1.2 (2011-08-31):
+* Plugin
+  - PR749: sun.applet.PluginStreamHandler#handleMessage(String) really slow
+  - RH718693: MindTerm SSH Applet doesn't work
+Common
+  - PR768: Signed applets/Web Start apps don't work with OpenJDK7 and up
+  - PR769: IcedTea-Web does not work with some ssl sites with OpenJDK7
+  - RH734081: Javaws cannot use proxy settings from Firefox
+
+New in release 1.1.1 (2011-07-20):
+* Security updates:
+	- RH718164, CVE-2011-2513: Home directory path disclosure to untrusted applications
+	- RH718170, CVE-2011-2514: Java Web Start security warning dialog manipulation
+
+New in release 1.1 (2011-06-08):
+* New Features
+  - IcedTea-Web now installs to a FHS-compliant location
+  - IcedTea-Web can now handle Proxy Auto Config files
+  - Binary launchers replaced with simple shell scripts
+  - Can now use codebase_lookup=false with applets.
+* Common Fixes and Improvements
+  - PR497: Mercurial revision detection not very reliable
+  - PR638: JNLPClassLoader.loadClass(String name) can return null
+  - RH677772: NoSuchAlgorithmException using SSL/TLS in javaws
+  - PR724: Possible NullPointerException in JNLPClassLoader.getClassPathsFromManifest
+* NetX
+  - Use Firefox's proxy settings if possible
+  - The user's default browser (determined from xdg-open or $BROWSER) is used
+  - RH669942: javaws fails to download version/packed files (missing support for jnlp.packEnabled and jnlp.versionEnabled)
+  - PR658: now jnlp.packEnabled works with applets.
+  - PR726: closing javaws -about no longer throws exceptions.
+  - PR727: cache now properly removes files.
+* Plugin
+  - PR475, RH604061: Allow applets from the same page to use the same classloader
+  - PR612: NetDania application ends on java.security.AccessControlException: access denied (java.util.PropertyPermission browser read)
+  - PR664: Sound doesn't play on runescape.com.
+  - PR721: IcedTeaPlugin.so cannot run g_main_context_iteration on a different thread unless a different GMainContext *context is used
+  - PR735: Firefox 4 sometimes freezes if the applet calls showDocument()
+
+New in release 1.0 (2010-XX-XX):
+
+* Initial release of IcedTea-Web
+* Security updates
+  - RH645843, CVE-2010-3860: IcedTea System property information leak via public static
+  - RH672262, CVE-2011-0025: IcedTea jarfile signature verification bypass
+* Plugin
+  - PR542: Plugin fails with NPE on http://www.openprocessing.org/visuals/iframe.php?visualID=2615
+  - PR552: Support for FreeBSD's pthread implementation
+  - PR554: System.err writes content two times
+  - PR556: Applet initialization code is prone to race conditions
+  - PR557: Applet opens in a separate window if tab is closed when the applet loads
+  - PR565: UIDefaults.getUI fails with jgoodies:looks 2.3.1
+  - PR593: Increment of invalidated iterator in IcedTeaPluginUtils (patch from barbara.xxx1975@libero.it)
+  - PR597: Entities are parsed incorrectly in PARAM tag in applet plugin
+  - PR619: Improper finalization by the plugin can crash the browser
+  - Applets are now double-buffered to eliminate flicker in ones that do heavy drawing
+  - RH665104: OpenJDK Firefox Java plugin loses a cookie
+* NetX
+  - Add a new option -Xclearcache
+  - Interfaces javax.jnlp.IntegrationService and javax.jnlp.DownloadService2 are now available
+  - PR592: NetX can create invalid desktop entry files
+  - RH663680, CVE-2010-4351: IcedTea JNLP SecurityManager bypass
+* Control Panel
+  - Modifications to deployments.properties file can now be done through a GUI
Index: /tags/icedtea-web/beta/ODIN.kmk
===================================================================
--- /tags/icedtea-web/beta/ODIN.kmk	(revision 403)
+++ /tags/icedtea-web/beta/ODIN.kmk	(revision 403)
@@ -0,0 +1,28 @@
+## @file
+#
+# Odin SDK, headers and libraries.
+
+SDK_ODIN :=Odin SDK, headers and libraries.
+
+# SDK Specific Properties
+ifndef PATH_SDK_ODIN
+ PATH_SDK_ODIN := /@unixroot/usr
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_SDK_ODIN := $(PATH_SDK_ODIN)
+endif
+ifneq ($(PATH_SDK_ODIN),)
+ PATH_SDK_ODIN_INC ?= $(PATH_SDK_ODIN)/include
+ PATH_SDK_ODIN_LIB ?= $(PATH_SDK_ODIN)/lib
+endif
+
+# This breaks some GCC core defs, disable for now
+#SDK_ODIN_DEFS_FORCE_BSD_TCPIP := \
+#    _POSIX_SOURCE _POSIX_C_SOURCE=200112 _EMX_SOURCE
+#    _XOPEN_SOURCE=600 _SVID_SOURCE
+
+# General Properties used by kBuild
+SDK_ODIN_DEFS ?= __WIN32OS2__ _i386__ $(SDK_ODIN_DEFS_FORCE_BSD_TCPIP)
+SDK_ODIN_INCS ?= $(PATH_SDK_ODIN_INC) $(PATH_SDK_ODIN_INC)/win
+SDK_ODIN_LIBPATH ?= $(PATH_SDK_ODIN_LIB)
+
Index: /tags/icedtea-web/beta/README
===================================================================
--- /tags/icedtea-web/beta/README	(revision 403)
+++ /tags/icedtea-web/beta/README	(revision 403)
@@ -0,0 +1,173 @@
+IcedTea-Web
+===========
+
+The IcedTea-Web project provides a Free Software web browser plugin
+for running applets written in the Java programming language and an
+implementation of Java Web Start, originally based on the NetX
+project.
+
+Homepage (wiki):
+  http://icedtea.classpath.org/
+
+Bugs (bugzilla):
+  http://icedtea.classpath.org/bugzilla
+
+Mailing List: 
+  distro-pkg-dev@openjdk.java.net
+  http://mail.openjdk.java.net/mailman/listinfo/distro-pkg-dev
+
+FAQ:
+  http://icedtea.classpath.org/wiki/FrequentlyAskedQuestions
+
+Anonymous Mercurial checkout:
+  hg clone http://icedtea.classpath.org/hg/icedtea-web
+
+NetX
+====
+
+NetX provides a drop-in replacement for javaws (Java Web Start). Since
+upstream NetX is dormant, we will be hosting and modifying the sources
+in the IcedTea-Web repository, particularly in the netx/net/sourceforge/jnlp
+directory.
+
+IcedTea's NetX currently supports verification of signed jars, trusted
+certificate storing, system certificate store checking, and provides
+the services specified by the jnlp API.
+
+The Browser Plugin
+==================
+
+IcedTea-Web contains a Free Software browser plugin based on NPRuntime
+called NPPlugin.  By default, this will be built, and it can be turned
+off using the -disable-plugin option.
+
+Building IcedTea-Web
+====================
+
+IcedTea-Web is built using the standard:
+
+$ ./autogen.sh (if building from Mercurial rather than a tarball)
+$ ./configure
+$ gmake
+$ gmake install
+
+incantation.  The build requirements are as follows:
+
+* A bootstrap JDK.  At present, only IcedTea6 is supported.
+* A C compiler (for the launchers).
+* libX11
+* zlib-devel
+
+Additionally, the plugin requires:
+
+* A C++ compiler
+* firefox-devel 
+* xulrunner-devel
+
+The plugin can be disabled by passing --disable-plugin.
+
+The following optional dependencies enable additional features
+
+* rhino (enables support for using proxy auto config files)
+* junit4 (enables unit tests)
+
+See ./configure --help if you need to override the defaults.
+
+The following locations are checked for a JDK:
+    * /usr/lib/jvm/java-openjdk
+    * /usr/lib/jvm/icedtea6
+    * /usr/lib/jvm/java-6-openjdk
+    * /usr/lib/jvm/openjdk
+    * /usr/lib/jvm/java-icedtea
+    * /usr/lib/jvm/java-gcj
+    * /usr/lib/jvm/gcj-jdk
+    * /usr/lib/jvm/cacao
+in the order given above.  
+
+At present, some of these options fail due to sun.* classes required
+by IcedTea-Web.  Upstream OpenJDK will only be able to compile
+IcedTea-Web if the patch applet_hole.patch from IcedTea has been
+applied.
+
+Most targets in IcedTea-Web create stamp files in the stamps directory
+to determine what and when dependencies were compiled.  Each target
+has a corresponding clean-x target which removes the output and the
+stamp file, allowing it to be rebuilt.
+
+Build Modification Options
+==========================
+
+The build process may be modified by passing the following options
+to configure:
+
+* --disable-docs: Don't build the Javadoc documentation.
+* --with-gcj: Compile ecj to native code with gcj prior to building.
+* --with-ecj: Specify the location of a 'ecj' binary.  By default, the path
+  is checked for ecj, ecj-3.1, ecj-3.2 and ecj-3.3.
+* --with-javac: Specify the location of a 'javac' binary.  By default, the path
+  is checked for javac.
+* --with-jar: Specify the location of a 'jar' binary.  By default, the path
+  is checked for gjar and jar.
+* --with-ecj-jar: Specify the location of an ecj JAR file.  By default, the
+  following paths are checked:
+    - /usr/share/java/eclipse-ecj.jar
+    - /usr/share/java/ecj.jar
+    - /usr/share/eclipse-ecj-3.{2,3,4,5}/lib/ecj.jar
+
+Other options may be supplied which enable or disable new features.
+These are documented fully in the relevant section below.
+
+* --disable-plugin: Don't build the browser plugin.
+* --with-rhino: Specify the location of rhino jar
+* --with-junit: Specify the location of the junit 4 jar
+
+Rhino Support
+=============
+
+IcedTea-Web needs rhino for using Proxy Auto Config (PAC) files. If rhino is
+not found, or explicitly disabled, then support for PAC files will be disabled.
+
+By default, the following paths are checked for rhino:
+  - /usr/share/java/js.jar
+  - /usr/share/rhino-1.6/lib/js.jar
+  - /usr/share/java/rhino.jar
+
+If a rhino jar is not found, rhino support is disabled. The --with-rhino build
+option can be used to specify the location of the jar file. To explicitly
+disable rhino use --with-rhino=no.
+
+JUnit Support
+=============
+
+JUnit is needed for running some tests. It has no run-time impact.
+
+By default, the following paths are checked:
+  - /usr/share/java/junit4.jar
+
+If JUnit is not found, JUnit support is disabled. The --with-junit option can
+be used to specify the location of the JUnit 4 jar. To disable JUnit support
+explicitly, use --with-junit=no.
+
+A custom JUnit ouput formatter is supplied. This makes the output of JUnit
+tests match the output of other tests. A simple 'Passed:' or 'FAILED:' is
+printed out, followed by <TestClass>.<testMethod>. This is also the format used
+by JTreg.
+
+Testing
+=======
+
+A set of automated tests is supplied for IcedTea-Web. They can be run by using
+'make check'. Currently, this only tests a few parts of IcedTea-Web.
+
+The number and type of tests run by 'make check' may be affected by the build
+options, including JUnit support and rhino support.
+
+A test suite is supplied for the browser plugin.  It can be built
+using 'make plugin-tests' and run by loading the HTML page specified
+into a browser with the plugin installed.
+
+For debugging, the environment variable ICEDTEAPLUGIN_DEBUG should be
+set to 'true'.  This will produce output on the console from the C++
+side, and output from the Java side in $HOME/.icedteaplugin/java.stdout
+and $HOME/.icedteaplugin/java.stderr.  It also starts the debug server
+on port 8787.
Index: /tags/icedtea-web/beta/README.OS2
===================================================================
--- /tags/icedtea-web/beta/README.OS2	(revision 403)
+++ /tags/icedtea-web/beta/README.OS2	(revision 403)
@@ -0,0 +1,114 @@
+IcedTea-Web for OS/2 and eCS
+
+Version 1.1.2 Beta (2012-07-21)
+
+This is an beta release intended for testing purposes.
+
+
+
+INTRODUCTION
+
+This document contains a brief information on the OS/2 version of the
+IcedTea-Web product. Please read it carefully before starting your work.
+You may also visit the project page at
+
+  http://svn.netlabs.org/java/wiki
+
+to get more information and the latest news and also to report bugs.
+
+To get a brief list of OS/2-specific changes from release to release
+please see the CHANGES.OS2 file included in this distribution.
+
+
+
+REQUIREMENTS
+
+In order to use the IcedTea-Web browser plugin, you will need the following:
+
+  - A OS/2 Warp 4 Fixpack 16+, OS/2 Warp 4.5 or eComStation operating system.
+
+  - OpenJDK 1.6.0 Build 25 GA3 or later (and all its requirements):
+
+    ftp://ftp.netlabs.org/pub/java/openjdk6_b25_ga3/openjdk6_b25_jre_os2_ga3-20120721.zip
+
+  - GLib2 libraries version 2.25.15 build 4:
+
+    ftp://ftp.netlabs.org/pub/java/icedtea-web/misc/glib2-2_25_15-4.zip
+
+If you use the YUM/RPM package manager, you may install all the requirements
+with a single command from the command line (except OpenJDK which is not in RPM
+yet):
+
+    yum install glib2
+
+
+
+INSTALLATION
+
+  Make sure that the correct version of OpenJDK is installed and listed in your
+  PATH environment variable and the correct version of GLib2 libraries is
+  installed.
+
+  Unszip the contents of the distribution archive to a directory containing
+  Mozilla plugins in your system. This directory is pointed to by the
+  MOZ_PLUGIN_PATH environment variable and is usually:
+
+    X:\PROGRAMS\MOZ_PLUG
+
+  where X: is your boot drive (check your CONFIG.SYS for the exact location).
+
+  Now (re)start your Mozilla family product (e.g. Firefox). If everything is
+  done correctly, you should now see the IcedTea-Web browser plugin in the list
+  of installed plugins if you visit the special web-page "about:plugins" from
+  the browser.
+
+  You may check the plugin functionality by visiting the following test web-page
+  on the Java web-site:
+
+    http://www.java.com/en/download/testjava.jsp
+
+  Note that you may also specify the location of the Java runtime and plugin
+  jars using the ICEDTEA_WEB_JRE and ICEDTEA_WEB_DATA environment variables,
+  respectively:
+
+    set ICEDTEA_WEB_JRE=<path_to_jre>
+    set ICEDTEA_WEB_DATA=<path_to_jars>
+
+
+
+CURRENT LIMITATIONS
+
+  1. Some Java applets may stop redrawing their contents. You may need to
+     refresh the page or restart the browser. This will be fixed later.
+
+  See the project roadmap for more information on the current progress and
+  future plans:
+
+    http://svn.netlabs.org/java/roadmap
+
+  Feel free to request new features and report bugs using the project bug
+  tracker abaialble at:
+
+    http://svn.netlabs.org/java/report
+
+
+
+CREDITS
+
+Dmitriy Kuminov (development)
+Silvan Scherrer (management)
+
+netlabs.org (hosting & support)
+
+Oracle Corporation (original OpenJDK product)
+
+All IcedTea-Web authors (see AUTHORS)
+
+We also want to THANK all individuals and organizations who made the donations
+to this project and helped to make it happen.
+
+
+Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+OS/2 and OS/2 Warp are trademarks of the IBM Corporation and/or its subsidiary(-ies).
+eComStation is a trademark of Serenity Systems International and/or its subsidiary(-ies).
+Other names may be trademarks of their respective owners.
Index: /tags/icedtea-web/beta/acinclude.m4
===================================================================
--- /tags/icedtea-web/beta/acinclude.m4	(revision 403)
+++ /tags/icedtea-web/beta/acinclude.m4	(revision 403)
@@ -0,0 +1,785 @@
+AC_DEFUN_ONCE([IT_CAN_HARDLINK_TO_SOURCE_TREE],
+[
+  AC_CACHE_CHECK([if we can hard link rather than copy from ${abs_top_srcdir}], it_cv_hardlink_src, [
+    if cp -l ${abs_top_srcdir}/README tmp.$$ >&AS_MESSAGE_LOG_FD 2>&1; then
+      it_cv_hardlink_src=yes;
+    else
+      it_cv_hardlink_src=no;
+    fi
+    rm -f tmp.$$
+  ])
+  AM_CONDITIONAL([SRC_DIR_HARDLINKABLE], test x"${it_cv_hardlink_src}" = "xyes")
+])
+
+AC_DEFUN_ONCE([IT_CP_SUPPORTS_REFLINK],
+[
+  AC_CACHE_CHECK([if cp supports --reflink], it_cv_reflink, [
+    touch tmp.$$
+    if cp --reflink=auto tmp.$$ tmp2.$$ >&AS_MESSAGE_LOG_FD 2>&1; then
+      it_cv_reflink=yes;
+    else
+      it_cv_reflink=no;
+    fi
+    rm -f tmp.$$ tmp2.$$
+  ])
+  AM_CONDITIONAL([CP_SUPPORTS_REFLINK], test x"${it_cv_reflink}" = "xyes")
+])
+
+AC_DEFUN_ONCE([IT_CHECK_FOR_JDK],
+[
+  AC_MSG_CHECKING([for a JDK home directory])
+  AC_ARG_WITH([jdk-home],
+             [AS_HELP_STRING([--with-jdk-home],
+                              [jdk home directory \
+                               (default is first predefined JDK found)])],
+             [
+                if test "x${withval}" = xyes
+                then
+                  SYSTEM_JDK_DIR=
+                elif test "x${withval}" = xno
+                then
+	          SYSTEM_JDK_DIR=
+	        else
+                  SYSTEM_JDK_DIR=${withval}
+                fi
+              ],
+              [
+	        SYSTEM_JDK_DIR=
+              ])
+  if test -z "${SYSTEM_JDK_DIR}"; then
+    for dir in /usr/lib/jvm/java-openjdk /usr/lib/jvm/icedtea6 \
+    	      /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/openjdk \
+              /usr/lib/jvm/java-icedtea /usr/lib/jvm/java-gcj /usr/lib/jvm/gcj-jdk \
+              /usr/lib/jvm/cacao ; do
+       if test -d $dir; then
+         SYSTEM_JDK_DIR=$dir
+	 break
+       fi
+    done
+  fi
+  AC_MSG_RESULT(${SYSTEM_JDK_DIR})
+  if ! test -d "${SYSTEM_JDK_DIR}"; then
+    AC_MSG_ERROR("A JDK home directory could not be found.")
+  fi
+  AC_SUBST(SYSTEM_JDK_DIR)
+])
+
+AC_DEFUN_ONCE([IT_CHECK_FOR_JRE],
+[
+  AC_REQUIRE([IT_CHECK_FOR_JDK])
+  AC_MSG_CHECKING([for a JRE home directory])
+  AC_ARG_WITH([jre-home],
+             [AS_HELP_STRING([--with-jre-home],
+                              [jre home directory \
+                               (default is the JRE under the JDK)])],
+             [
+               SYSTEM_JRE_DIR=${withval}
+             ],
+             [
+               SYSTEM_JRE_DIR=
+             ])
+  if test -z "${SYSTEM_JRE_DIR}" ; then
+    if test -d "${SYSTEM_JDK_DIR}/jre" ; then
+      SYSTEM_JRE_DIR="${SYSTEM_JDK_DIR}/jre"
+    fi
+  fi
+  AC_MSG_RESULT(${SYSTEM_JRE_DIR})
+  if ! test -d "${SYSTEM_JRE_DIR}"; then
+    AC_MSG_ERROR("A JRE home directory could not be found.")
+  fi
+  AC_SUBST(SYSTEM_JRE_DIR)
+])
+
+AC_DEFUN_ONCE([FIND_JAVAC],
+[
+  AC_REQUIRE([IT_CHECK_FOR_JDK])
+  JAVAC=${SYSTEM_JDK_DIR}/bin/javac
+  IT_FIND_JAVAC
+  IT_FIND_ECJ
+  IT_USING_ECJ
+
+  AC_SUBST(JAVAC)
+])
+
+AC_DEFUN([IT_FIND_ECJ],
+[
+  AC_ARG_WITH([ecj],
+	      [AS_HELP_STRING(--with-ecj,bytecode compilation with ecj)],
+  [
+    if test "x${withval}" != x && test "x${withval}" != xyes && test "x${withval}" != xno; then
+      IT_CHECK_ECJ(${withval})
+    else
+      if test "x${withval}" != xno; then
+        IT_CHECK_ECJ
+      fi
+    fi
+  ],
+  [ 
+    IT_CHECK_ECJ
+  ])
+  if test "x${JAVAC}" = "x"; then
+    if test "x{ECJ}" != "x"; then
+      JAVAC="${ECJ} -nowarn"
+    fi
+  fi
+])
+
+AC_DEFUN([IT_CHECK_ECJ],
+[
+  if test "x$1" != x; then
+    if test -f "$1"; then
+      AC_MSG_CHECKING(for ecj)
+      ECJ="$1"
+      AC_MSG_RESULT(${ECJ})
+    else
+      AC_PATH_PROG(ECJ, "$1")
+    fi
+  else
+    AC_PATH_PROG(ECJ, "ecj")
+    if test -z "${ECJ}"; then
+      AC_PATH_PROG(ECJ, "ecj-3.1")
+    fi
+    if test -z "${ECJ}"; then
+      AC_PATH_PROG(ECJ, "ecj-3.2")
+    fi
+    if test -z "${ECJ}"; then
+      AC_PATH_PROG(ECJ, "ecj-3.3")
+    fi
+  fi
+])
+
+AC_DEFUN([IT_FIND_JAVAC],
+[
+  AC_ARG_WITH([javac],
+	      [AS_HELP_STRING(--with-javac,bytecode compilation with javac)],
+  [
+    if test "x${withval}" != x && test "x${withval}" != xyes && test "x${withval}" != xno; then
+      IT_CHECK_JAVAC(${withval})
+    else
+      if test "x${withval}" != xno; then
+        IT_CHECK_JAVAC
+      fi
+    fi
+  ],
+  [ 
+    IT_CHECK_JAVAC
+  ])
+])
+
+AC_DEFUN([IT_CHECK_JAVAC],
+[
+  if test "x$1" != x; then
+    if test -f "$1"; then
+      AC_MSG_CHECKING(for javac)
+      JAVAC="$1"
+      AC_MSG_RESULT(${JAVAC})
+    else
+      AC_PATH_PROG(JAVAC, "$1")
+    fi
+  else
+    AC_PATH_PROG(JAVAC, "javac")
+  fi
+])
+
+AC_DEFUN([FIND_JAR],
+[
+  AC_REQUIRE([IT_CHECK_FOR_JDK])
+  AC_MSG_CHECKING([for jar])
+  AC_ARG_WITH([jar],
+              [AS_HELP_STRING(--with-jar,specify location of Java archive tool (jar))],
+  [
+    JAR="${withval}"
+  ],
+  [
+    JAR=${SYSTEM_JDK_DIR}/bin/jar
+  ])
+  if ! test -f "${JAR}"; then
+    AC_PATH_PROG(JAR, "${JAR}")
+  fi
+  if test -z "${JAR}"; then
+    AC_PATH_PROG(JAR, "gjar")
+  fi
+  if test -z "${JAR}"; then
+    AC_PATH_PROG(JAR, "jar")
+  fi
+  if test -z "${JAR}"; then
+    AC_MSG_ERROR("No Java archive tool was found.")
+  fi
+  AC_MSG_RESULT(${JAR})
+  AC_MSG_CHECKING([whether jar supports @<file> argument])
+  touch _config.txt
+  cat >_config.list <<EOF
+_config.txt
+EOF
+  if $JAR cf _config.jar @_config.list >&AS_MESSAGE_LOG_FD 2>&1; then
+    JAR_KNOWS_ATFILE=1
+    AC_MSG_RESULT(yes)
+  else
+    JAR_KNOWS_ATFILE=
+    AC_MSG_RESULT(no)
+  fi
+  AC_MSG_CHECKING([whether jar supports stdin file arguments])
+  if cat _config.list | $JAR cf@ _config.jar >&AS_MESSAGE_LOG_FD 2>&1; then
+    JAR_ACCEPTS_STDIN_LIST=1
+    AC_MSG_RESULT(yes)
+  else
+    JAR_ACCEPTS_STDIN_LIST=
+    AC_MSG_RESULT(no)
+  fi
+  rm -f _config.list _config.jar
+  AC_MSG_CHECKING([whether jar supports -J options at the end])
+  if $JAR cf _config.jar _config.txt -J-Xmx896m >&AS_MESSAGE_LOG_FD 2>&1; then
+    JAR_KNOWS_J_OPTIONS=1
+    AC_MSG_RESULT(yes)
+  else
+    JAR_KNOWS_J_OPTIONS=
+    AC_MSG_RESULT(no)
+  fi
+  rm -f _config.txt _config.jar
+  AC_SUBST(JAR)
+  AC_SUBST(JAR_KNOWS_ATFILE)
+  AC_SUBST(JAR_ACCEPTS_STDIN_LIST)
+  AC_SUBST(JAR_KNOWS_J_OPTIONS)
+])
+
+AC_DEFUN([FIND_ECJ_JAR],
+[
+  AC_REQUIRE([FIND_JAVAC])
+  AC_MSG_CHECKING([for an ecj JAR file])
+  AC_ARG_WITH([ecj-jar],
+              [AS_HELP_STRING(--with-ecj-jar,specify location of the ECJ jar)],
+  [
+    if test -f "${withval}"; then
+      ECJ_JAR="${withval}"
+    fi
+  ],
+  [
+    ECJ_JAR=
+  ])
+  if test -z "${ECJ_JAR}"; then
+    for jar in /usr/share/java/eclipse-ecj.jar \
+      /usr/share/java/ecj.jar \
+      /usr/share/eclipse-ecj-3.{2,3,4,5}/lib/ecj.jar; do
+        if test -e $jar; then
+          ECJ_JAR=$jar
+	  break
+        fi
+      done
+      if test -z "${ECJ_JAR}"; then
+        ECJ_JAR=no
+      fi
+  fi
+  AC_MSG_RESULT(${ECJ_JAR})
+  if test "x${JAVAC}" = x && test "x${ECJ_JAR}" = "xno" ; then
+      AC_MSG_ERROR([cannot find a Java compiler or ecj JAR file, try --with-javac, --with-ecj or --with-ecj-jar])
+  fi
+  AC_SUBST(ECJ_JAR)
+])
+
+#
+# IT_FIND_OPTIONAL_JAR
+# --------------------
+# Find an optional jar required for building and running
+#
+# $1 : jar/feature name
+# $2 : used to set $2_JAR and WITH_$2
+# $3 (optional) : used to specify additional file paths for searching
+#
+# Sets $2_JAR to the jar location (or blank if not found)
+# Defines WITH_$2 if jar is found
+# Sets $2_AVAILABLE to "true" if jar is found (or "false" if not)
+#
+AC_DEFUN([IT_FIND_OPTIONAL_JAR],
+[
+  AC_MSG_CHECKING([for $1 jar])
+  AC_ARG_WITH([$1],
+              [AS_HELP_STRING(--with-$1,specify location of the $1 jar)],
+  [
+    case "${withval}" in
+      yes)
+        $2_JAR=yes
+        ;;
+      no)
+        $2_JAR=no
+        ;;
+      *)
+        if test -f "${withval}"; then
+          $2_JAR="${withval}"
+        elif test -z "${withval}"; then
+          $2_JAR=yes
+        else
+          AC_MSG_RESULT([not found])
+          AC_MSG_ERROR("The $1 jar ${withval} was not found.")
+        fi
+        ;;
+    esac
+  ],
+  [
+    $2_JAR=yes
+  ])
+  it_extra_paths_$1="$3"
+  if test "x${$2_JAR}" = "xyes"; then
+    for path in ${it_extra_paths_$1}; do
+      if test -f ${path}; then
+        $2_JAR=${path}
+        break
+      fi
+    done
+  fi
+  if test x"${$2_JAR}" = "xyes"; then
+    if test -f "/usr/share/java/$1.jar"; then
+      $2_JAR=/usr/share/java/$1.jar
+    fi
+  fi
+  if test x"${$2_JAR}" = "xyes"; then
+    $2_JAR=no
+  fi
+  AC_MSG_RESULT(${$2_JAR})
+  AM_CONDITIONAL(WITH_$2, test x"${$2_JAR}" != "xno")
+  # Clear $2_JAR if it doesn't contain a valid filename
+  if test x"${$2_JAR}" = "xno"; then
+    $2_JAR=
+  fi
+  if test -n "${$2_JAR}" ; then
+    $2_AVAILABLE=true
+  else
+    $2_AVAILABLE=false
+  fi
+  AC_SUBST($2_JAR)
+  AC_SUBST($2_AVAILABLE)
+])
+
+AC_DEFUN_ONCE([IT_CHECK_PLUGIN],
+[
+AC_MSG_CHECKING([whether to build the browser plugin])
+AC_ARG_ENABLE([plugin],
+              [AS_HELP_STRING([--disable-plugin],
+                              [Disable compilation of browser plugin])],
+              [enable_plugin="${enableval}"], [enable_plugin="yes"])
+AC_MSG_RESULT(${enable_plugin})
+])
+
+AC_DEFUN_ONCE([IT_CHECK_PLUGIN_DEPENDENCIES],
+[
+dnl Check for plugin support headers and libraries.
+dnl FIXME: use unstable
+AC_REQUIRE([IT_CHECK_PLUGIN])
+if test "x${enable_plugin}" = "xyes" ; then
+  PKG_CHECK_MODULES(GTK, gtk+-2.0)
+  PKG_CHECK_MODULES(GLIB, glib-2.0)
+  AC_SUBST(GLIB_CFLAGS)
+  AC_SUBST(GLIB_LIBS)
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+
+  PKG_CHECK_MODULES(MOZILLA, mozilla-plugin)
+    
+  AC_SUBST(MOZILLA_CFLAGS)
+  AC_SUBST(MOZILLA_LIBS)
+fi
+AM_CONDITIONAL(ENABLE_PLUGIN, test "x${enable_plugin}" = "xyes")
+])
+
+AC_DEFUN_ONCE([IT_CHECK_XULRUNNER_VERSION],
+[
+AC_REQUIRE([IT_CHECK_PLUGIN_DEPENDENCIES])
+if test "x${enable_plugin}" = "xyes"
+then
+  AC_CACHE_CHECK([for xulrunner version], [xulrunner_cv_collapsed_version],[
+    if pkg-config --modversion libxul >/dev/null 2>&1
+    then
+      xulrunner_cv_collapsed_version=`pkg-config --modversion libxul | awk -F. '{power=6; v=0; for (i=1; i <= NF; i++) {v += $i * 10 ^ power; power -=2}; print v}'`
+    else
+      AC_MSG_FAILURE([cannot determine xulrunner version])
+    fi])
+  AC_SUBST(MOZILLA_VERSION_COLLAPSED, $xulrunner_cv_collapsed_version)
+fi
+])
+
+dnl Generic macro to check for a Java class
+dnl Takes the name of the class as an argument.  The macro name
+dnl is usually the name of the class with '.'
+dnl replaced by '_' and all letters capitalised.
+dnl e.g. IT_CHECK_FOR_CLASS([JAVA_UTIL_SCANNER],[java.util.Scanner])
+dnl Test class has to be in sun.applet for some internal classes
+AC_DEFUN([IT_CHECK_FOR_CLASS],[
+AC_REQUIRE([IT_FIND_JAVAC])
+AC_REQUIRE([IT_FIND_JAVA])
+AC_CACHE_CHECK([if $2 is available], it_cv_$1, [
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+[/* [#]line __oline__ "configure" */
+package sun.applet;
+
+import $2;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("$2"));
+  }
+}
+]
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&AS_MESSAGE_LOG_FD 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&AS_MESSAGE_LOG_FD 2>&1; then
+      it_cv_$1=yes;
+  else
+      it_cv_$1=no;
+  fi
+else
+  it_cv_$1=no;
+fi
+])
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_$1}" = "xno"; then
+   AC_MSG_ERROR([$2 not found.])
+fi
+AC_PROVIDE([$0])dnl
+])
+
+AC_DEFUN_ONCE([IT_CHECK_FOR_MERCURIAL],
+[
+  AC_PATH_TOOL([HG],[hg])
+  AC_SUBST([HG])
+])
+
+AC_DEFUN_ONCE([IT_OBTAIN_HG_REVISIONS],
+[
+  AC_REQUIRE([IT_CHECK_FOR_MERCURIAL])
+  ICEDTEA_REVISION="none";
+  if which ${HG} >&AS_MESSAGE_LOG_FD 2>&1; then
+    AC_MSG_CHECKING([for IcedTea Mercurial revision ID])
+    if test -e ${abs_top_srcdir}/.hg ; then 
+      ICEDTEA_REVISION="r`(cd ${abs_top_srcdir}; ${HG} id -i)`" ;
+    fi ;
+    AC_MSG_RESULT([${ICEDTEA_REVISION}])
+    AC_SUBST([ICEDTEA_REVISION])
+  fi;
+  AM_CONDITIONAL([HAS_ICEDTEA_REVISION], test "x${ICEDTEA_REVISION}" != xnone)
+])
+
+AC_DEFUN_ONCE([IT_GET_PKGVERSION],
+[
+AC_MSG_CHECKING([for distribution package version])
+AC_ARG_WITH([pkgversion],
+        [AS_HELP_STRING([--with-pkgversion=PKG],
+                        [Use PKG in the version string in addition to "IcedTea"])],
+        [case "$withval" in
+          yes) AC_MSG_ERROR([package version not specified]) ;;
+          no)  PKGVERSION=none ;;
+          *)   PKGVERSION="$withval" ;;
+         esac],
+        [PKGVERSION=none])
+AC_MSG_RESULT([${PKGVERSION}])
+AM_CONDITIONAL(HAS_PKGVERSION, test "x${PKGVERSION}" != "xnone") 
+AC_SUBST(PKGVERSION)
+])
+
+AC_DEFUN([IT_CHECK_WITH_GCJ],
+[
+  AC_MSG_CHECKING([whether to compile ecj natively])
+  AC_ARG_WITH([gcj],
+	      [AS_HELP_STRING(--with-gcj,location of gcj for natively compiling ecj)],
+  [
+    GCJ="${withval}"
+  ],
+  [ 
+    GCJ="no"
+  ])
+  AC_MSG_RESULT([${GCJ}])
+  if test "x${GCJ}" = xyes; then
+    AC_PATH_TOOL([GCJ],[gcj])
+  fi
+  AC_SUBST([GCJ])
+])
+
+AC_DEFUN([IT_USING_ECJ],[
+AC_CACHE_CHECK([if we are using ecj as javac], it_cv_ecj, [
+if $JAVAC -version 2>&1| grep '^Eclipse' >&AS_MESSAGE_LOG_FD ; then
+  it_cv_ecj=yes;
+else
+  it_cv_ecj=no;
+fi
+])
+USING_ECJ=$it_cv_ecj
+AC_SUBST(USING_ECJ)
+AC_PROVIDE([$0])dnl
+])
+
+AC_DEFUN([FIND_TOOL],
+[AC_PATH_TOOL([$1],[$2])
+ if test x"$$1" = x ; then
+   AC_MSG_ERROR([$2 program not found in PATH])
+ fi
+ AC_SUBST([$1])
+])
+
+AC_DEFUN([IT_SET_ARCH_SETTINGS],
+[
+  case "${host_cpu}" in
+    x86_64)
+      BUILD_ARCH_DIR=amd64
+      INSTALL_ARCH_DIR=amd64
+      JRE_ARCH_DIR=amd64
+      ARCHFLAG="-m64"
+      ;;
+    i?86)
+      BUILD_ARCH_DIR=i586
+      INSTALL_ARCH_DIR=i386
+      JRE_ARCH_DIR=i386
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+      ;;
+    alpha*)
+      BUILD_ARCH_DIR=alpha
+      INSTALL_ARCH_DIR=alpha
+      JRE_ARCH_DIR=alpha
+      ;;
+    arm*)
+      BUILD_ARCH_DIR=arm
+      INSTALL_ARCH_DIR=arm
+      JRE_ARCH_DIR=arm
+      ;;
+    mips)
+      BUILD_ARCH_DIR=mips
+      INSTALL_ARCH_DIR=mips
+      JRE_ARCH_DIR=mips
+       ;;
+    mipsel)
+      BUILD_ARCH_DIR=mipsel
+      INSTALL_ARCH_DIR=mipsel
+      JRE_ARCH_DIR=mipsel
+       ;;
+    powerpc)
+      BUILD_ARCH_DIR=ppc
+      INSTALL_ARCH_DIR=ppc
+      JRE_ARCH_DIR=ppc
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+       ;;
+    powerpc64)
+      BUILD_ARCH_DIR=ppc64
+      INSTALL_ARCH_DIR=ppc64
+      JRE_ARCH_DIR=ppc64
+      ARCHFLAG="-m64"
+       ;;
+    sparc)
+      BUILD_ARCH_DIR=sparc
+      INSTALL_ARCH_DIR=sparc
+      JRE_ARCH_DIR=sparc
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+       ;;
+    sparc64)
+      BUILD_ARCH_DIR=sparcv9
+      INSTALL_ARCH_DIR=sparcv9
+      JRE_ARCH_DIR=sparc64
+      ARCHFLAG="-m64"
+       ;;
+    s390)
+      BUILD_ARCH_DIR=s390
+      INSTALL_ARCH_DIR=s390
+      JRE_ARCH_DIR=s390
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m31"
+       ;;
+    s390x)
+      BUILD_ARCH_DIR=s390x
+      INSTALL_ARCH_DIR=s390x
+      JRE_ARCH_DIR=s390x
+      ARCHFLAG="-m64"
+       ;;
+    sh*)
+      BUILD_ARCH_DIR=sh
+      INSTALL_ARCH_DIR=sh
+      JRE_ARCH_DIR=sh
+      ;;
+    *)
+      BUILD_ARCH_DIR=`uname -m`
+      INSTALL_ARCH_DIR=$BUILD_ARCH_DIR
+      JRE_ARCH_DIR=$INSTALL_ARCH_DIR
+      ;;
+  esac
+  AC_SUBST(BUILD_ARCH_DIR)
+  AC_SUBST(INSTALL_ARCH_DIR)
+  AC_SUBST(JRE_ARCH_DIR)
+  AC_SUBST(ARCH_PREFIX)
+  AC_SUBST(ARCHFLAG)
+])
+
+AC_DEFUN_ONCE([IT_FIND_JAVA],
+[
+  AC_REQUIRE([IT_CHECK_FOR_JRE])
+  AC_MSG_CHECKING([for a Java virtual machine])
+  AC_ARG_WITH([java],
+              [AS_HELP_STRING(--with-java,specify location of the 1.5 java vm)],
+  [
+    JAVA="${withval}"
+  ],
+  [
+    JAVA="${SYSTEM_JRE_DIR}/bin/java"
+  ])
+  if ! test -f "${JAVA}"; then
+    AC_PATH_PROG(JAVA, "${JAVA}")
+  fi
+  if test -z "${JAVA}"; then
+    AC_PATH_PROG(JAVA, "java")
+  fi
+  if test -z "${JAVA}"; then
+    AC_PATH_PROG(JAVA, "gij")
+  fi
+  if test -z "${JAVA}"; then
+    AC_MSG_ERROR("A 1.5-compatible Java VM is required.")
+  fi
+  AC_MSG_RESULT(${JAVA})
+  AC_SUBST(JAVA)
+])
+
+AC_DEFUN([IT_FIND_JAVADOC],
+[
+  AC_REQUIRE([IT_CHECK_FOR_JDK])
+  AC_MSG_CHECKING([for javadoc])
+  AC_ARG_WITH([javadoc],
+              [AS_HELP_STRING(--with-javadoc,specify location of Java documentation tool (javadoc))],
+  [
+    JAVADOC="${withval}"
+  ],
+  [
+    JAVADOC=${SYSTEM_JDK_DIR}/bin/javadoc
+  ])
+  if ! test -f "${JAVADOC}"; then
+    AC_PATH_PROG(JAVADOC, "${JAVADOC}")
+  fi
+  if test -z "${JAVADOC}"; then
+    AC_PATH_PROG(JAVADOC, "javadoc")
+  fi
+  if test -z "${JAVADOC}"; then
+    AC_PATH_PROG(JAVADOC, "gjdoc")
+  fi
+  if test -z "${JAVADOC}" && test "x$ENABLE_DOCS" = "xyes"; then
+    AC_MSG_ERROR("No Java documentation tool was found.")
+  fi
+  AC_MSG_RESULT(${JAVADOC})
+  AC_MSG_CHECKING([whether javadoc supports -J options])
+  CLASS=pkg/Test.java
+  mkdir tmp.$$
+  cd tmp.$$
+  mkdir pkg
+  cat << \EOF > $CLASS
+[/* [#]line __oline__ "configure" */
+package pkg;
+
+public class Test
+{
+  /**
+   * Does stuff.
+   *
+   *
+   * @param args arguments from cli.
+   */
+  public static void main(String[] args)
+  {
+    System.out.println("Hello World!");
+  }
+}
+]
+EOF
+  if $JAVADOC -J-Xmx896m pkg >&AS_MESSAGE_LOG_FD 2>&1; then
+    JAVADOC_KNOWS_J_OPTIONS=yes
+  else
+    JAVADOC_KNOWS_J_OPTIONS=no
+  fi
+  cd ..
+  rm -rf tmp.$$
+  AC_MSG_RESULT([${JAVADOC_KNOWS_J_OPTIONS}])
+  AC_SUBST(JAVADOC)
+  AC_SUBST(JAVADOC_KNOWS_J_OPTIONS)
+  AM_CONDITIONAL([JAVADOC_SUPPORTS_J_OPTIONS], test x"${JAVADOC_KNOWS_J_OPTIONS}" = "xyes")
+])
+
+dnl Checks that sun.applet.AppletViewerPanel is available
+dnl and public (via the patch in IcedTea6, applet_hole.patch)
+dnl Can be removed when that is upstream or unneeded
+AC_DEFUN([IT_CHECK_FOR_APPLETVIEWERPANEL_HOLE],[
+AC_REQUIRE([IT_FIND_JAVAC])
+AC_REQUIRE([IT_FIND_JAVA])
+AC_CACHE_CHECK([if sun.applet.AppletViewerPanel is available and public], it_cv_applet_hole, [
+CLASS=TestAppletViewer.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$
+cd tmp.$$
+cat << \EOF > $CLASS
+[/* [#]line __oline__ "configure" */
+import java.lang.reflect.Modifier;
+
+public class TestAppletViewer
+{
+  public static void main(String[] args)
+  {
+    try
+      {
+        Class<?> clazz = Class.forName("sun.applet.AppletViewerPanel");
+        if (Modifier.isPublic(clazz.getModifiers()))
+          {
+            System.err.println("Found public sun.applet.AppletViewerPanel");
+            System.exit(0);
+          }
+        System.err.println("Found non-public sun.applet.AppletViewerPanel");
+        System.exit(2);
+      }
+    catch (ClassNotFoundException e)
+      {
+        System.err.println("Could not find sun.applet.AppletViewerPanel");
+        System.exit(1);
+      }
+  }
+}
+]
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&AS_MESSAGE_LOG_FD 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&AS_MESSAGE_LOG_FD 2>&1; then
+      it_cv_applet_hole=yes;
+  else
+      it_cv_applet_hole=$?;
+  fi
+else
+  it_cv_applet_hole=3;
+fi
+])
+rm -f $CLASS *.class
+cd ..
+rmdir tmp.$$
+if test x"${it_cv_applet_hole}" = "x1"; then
+   AC_MSG_ERROR([sun.applet.AppletViewerPanel is not available.])
+elif test x"${it_cv_applet_hole}" = "x2"; then
+   AC_MSG_ERROR([sun.applet.AppletViewerPanel is not public.])
+elif test x"${it_cv_applet_hole}" = "x3"; then
+   AC_MSG_ERROR([Compilation failed.  See config.log.])
+fi
+AC_PROVIDE([$0])dnl
+])
+
+AC_DEFUN_ONCE([IT_SET_VERSION],
+[
+  AC_REQUIRE([IT_OBTAIN_HG_REVISIONS])
+  AC_REQUIRE([IT_GET_PKGVERSION])
+  AC_MSG_CHECKING([what version string to use])
+  if test "x${ICEDTEA_REVISION}" != xnone; then
+    ICEDTEA_REV="+${ICEDTEA_REVISION}"
+  fi
+  if test "x${PKGVERSION}" != "xnone"; then
+    ICEDTEA_PKG=" (${PKGVERSION})"
+  fi
+  FULL_VERSION="${PACKAGE_VERSION}${ICEDTEA_REV}${ICEDTEA_PKG}"
+  AC_MSG_RESULT([${FULL_VERSION}])
+  AC_SUBST([FULL_VERSION])
+])
Index: /tags/icedtea-web/beta/aclocal.m4
===================================================================
--- /tags/icedtea-web/beta/aclocal.m4	(revision 403)
+++ /tags/icedtea-web/beta/aclocal.m4	(revision 403)
@@ -0,0 +1,1127 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
+[m4_warning([this file was generated for autoconf 2.68.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+# 
+# Copyright Â© 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+   	AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+        else 
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+	m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])
+        ])
+elif test $pkg_failed = untried; then
+     	AC_MSG_RESULT([no])
+	m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])
+        ])
+else
+	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+	$3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES(CC)],
+		  [define([AC_PROG_CC],
+			  defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES(CXX)],
+		  [define([AC_PROG_CXX],
+			  defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES(OBJC)],
+		  [define([AC_PROG_OBJC],
+			  defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acinclude.m4])
Index: /tags/icedtea-web/beta/build.properties.in
===================================================================
--- /tags/icedtea-web/beta/build.properties.in	(revision 403)
+++ /tags/icedtea-web/beta/build.properties.in	(revision 403)
@@ -0,0 +1,2 @@
+# build-time settings
+rhino.available=@RHINO_AVAILABLE@
Index: /tags/icedtea-web/beta/config.guess
===================================================================
--- /tags/icedtea-web/beta/config.guess	(revision 403)
+++ /tags/icedtea-web/beta/config.guess	(revision 403)
@@ -0,0 +1,1501 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	LIBC=gnu
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    i386)
+		eval $set_cc_for_build
+		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		      grep IS_64BIT_ARCH >/dev/null
+		  then
+		      UNAME_PROCESSOR="x86_64"
+		  fi
+		fi ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/icedtea-web/beta/config.sub
===================================================================
--- /tags/icedtea-web/beta/config.sub	(revision 403)
+++ /tags/icedtea-web/beta/config.sub	(revision 403)
@@ -0,0 +1,1705 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze)
+		os=
+		basic_machine=$1
+		;;
+        -bluegene*)
+	        os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+        cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+        microblaze)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+        -auroraux)
+	        os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/icedtea-web/beta/configure
===================================================================
--- /tags/icedtea-web/beta/configure	(revision 403)
+++ /tags/icedtea-web/beta/configure	(revision 403)
@@ -0,0 +1,9165 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68 for icedtea-web 1.1.2.
+#
+# Report bugs to <distro-pkg-dev@openjdk.java.net>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	# Preserve -v and -x to the replacement shell.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	case $- in # ((((
+	  *v*x* | *x*v* ) as_opts=-vx ;;
+	  *v* ) as_opts=-v ;;
+	  *x* ) as_opts=-x ;;
+	  * ) as_opts= ;;
+	esac
+	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: distro-pkg-dev@openjdk.java.net about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='icedtea-web'
+PACKAGE_TARNAME='icedtea-web'
+PACKAGE_VERSION='1.1.2'
+PACKAGE_STRING='icedtea-web 1.1.2'
+PACKAGE_BUGREPORT='distro-pkg-dev@openjdk.java.net'
+PACKAGE_URL='http://icedtea.classpath.org/wiki/IcedTea-Web'
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+JUNIT_AVAILABLE
+JUNIT_JAR
+WITH_JUNIT_FALSE
+WITH_JUNIT_TRUE
+RHINO_AVAILABLE
+RHINO_JAR
+WITH_RHINO_FALSE
+WITH_RHINO_TRUE
+JAVA
+SYSTEM_JRE_DIR
+X11_LIBS
+X11_CFLAGS
+MOZILLA_VERSION_COLLAPSED
+ENABLE_PLUGIN_FALSE
+ENABLE_PLUGIN_TRUE
+MOZILLA_LIBS
+MOZILLA_CFLAGS
+GLIB_LIBS
+GLIB_CFLAGS
+GTK_LIBS
+GTK_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+FULL_VERSION
+PKGVERSION
+HAS_PKGVERSION_FALSE
+HAS_PKGVERSION_TRUE
+HAS_ICEDTEA_REVISION_FALSE
+HAS_ICEDTEA_REVISION_TRUE
+ICEDTEA_REVISION
+HG
+JAVADOC_SUPPORTS_J_OPTIONS_FALSE
+JAVADOC_SUPPORTS_J_OPTIONS_TRUE
+JAVADOC_KNOWS_J_OPTIONS
+JAVADOC
+ECJ_JAR
+JAR_KNOWS_J_OPTIONS
+JAR_ACCEPTS_STDIN_LIST
+JAR_KNOWS_ATFILE
+JAR
+USING_ECJ
+ECJ
+JAVAC
+SYSTEM_JDK_DIR
+ZIP
+GCJ
+ENABLE_DOCS_FALSE
+ENABLE_DOCS_TRUE
+SRC_DIR_HARDLINKABLE_FALSE
+SRC_DIR_HARDLINKABLE_TRUE
+CP_SUPPORTS_REFLINK_FALSE
+CP_SUPPORTS_REFLINK_TRUE
+ARCHFLAG
+ARCH_PREFIX
+JRE_ARCH_DIR
+INSTALL_ARCH_DIR
+BUILD_ARCH_DIR
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+abs_top_srcdir
+abs_top_builddir
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_dependency_tracking
+enable_docs
+with_gcj
+with_jdk_home
+with_javac
+with_ecj
+with_jar
+with_ecj_jar
+with_javadoc
+with_pkgversion
+enable_plugin
+with_jre_home
+with_java
+with_rhino
+with_junit
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+GTK_CFLAGS
+GTK_LIBS
+GLIB_CFLAGS
+GLIB_LIBS
+MOZILLA_CFLAGS
+MOZILLA_LIBS
+X11_CFLAGS
+X11_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used" >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures icedtea-web 1.1.2 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/icedtea-web]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of icedtea-web 1.1.2:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --disable-docs          Disable generation of documentation
+  --disable-plugin        Disable compilation of browser plugin
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gcj              location of gcj for natively compiling ecj
+  --with-jdk-home         jdk home directory (default is first predefined JDK
+                          found)
+  --with-javac            bytecode compilation with javac
+  --with-ecj              bytecode compilation with ecj
+  --with-jar              specify location of Java archive tool (jar)
+  --with-ecj-jar          specify location of the ECJ jar
+  --with-javadoc          specify location of Java documentation tool
+                          (javadoc)
+  --with-pkgversion=PKG   Use PKG in the version string in addition to
+                          "IcedTea"
+  --with-jre-home         jre home directory (default is the JRE under the
+                          JDK)
+  --with-java             specify location of the 1.5 java vm
+  --with-rhino            specify location of the rhino jar
+  --with-junit            specify location of the junit jar
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  GTK_CFLAGS  C compiler flags for GTK, overriding pkg-config
+  GTK_LIBS    linker flags for GTK, overriding pkg-config
+  GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config
+  GLIB_LIBS   linker flags for GLIB, overriding pkg-config
+  MOZILLA_CFLAGS
+              C compiler flags for MOZILLA, overriding pkg-config
+  MOZILLA_LIBS
+              linker flags for MOZILLA, overriding pkg-config
+  X11_CFLAGS  C compiler flags for X11, overriding pkg-config
+  X11_LIBS    linker flags for X11, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <distro-pkg-dev@openjdk.java.net>.
+icedtea-web home page: <http://icedtea.classpath.org/wiki/IcedTea-Web>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+icedtea-web configure 1.1.2
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by icedtea-web $as_me 1.1.2, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.11'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='icedtea-web'
+ VERSION='1.1.2'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5
+$as_echo_n "checking how to create a pax tar archive... " >&6; }
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+_am_tools=${am_cv_prog_tar_pax-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      { echo "$as_me:$LINENO: $_am_tar --version" >&5
+   ($_am_tar --version) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && break
+    done
+    am__tar="$_am_tar --format=posix -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=posix -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x pax -w "$$tardir"'
+    am__tar_='pax -L -x pax -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H pax -L'
+    am__tar_='find "$tardir" -print | cpio -o -H pax -L'
+    am__untar='cpio -i -H pax -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_pax}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+   (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+   ($am__untar <conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+if ${am_cv_prog_tar_pax+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  am_cv_prog_tar_pax=$_am_tool
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5
+$as_echo "$am_cv_prog_tar_pax" >&6; }
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile netx.manifest"
+
+
+# Older automake doesn't generate these correctly
+abs_top_builddir=`pwd -P`
+
+abs_top_srcdir=`dirname $0`
+cd $abs_top_srcdir
+abs_top_srcdir=`pwd`
+cd $abs_top_builddir
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+
+  case "${host_cpu}" in
+    x86_64)
+      BUILD_ARCH_DIR=amd64
+      INSTALL_ARCH_DIR=amd64
+      JRE_ARCH_DIR=amd64
+      ARCHFLAG="-m64"
+      ;;
+    i?86)
+      BUILD_ARCH_DIR=i586
+      INSTALL_ARCH_DIR=i386
+      JRE_ARCH_DIR=i386
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+      ;;
+    alpha*)
+      BUILD_ARCH_DIR=alpha
+      INSTALL_ARCH_DIR=alpha
+      JRE_ARCH_DIR=alpha
+      ;;
+    arm*)
+      BUILD_ARCH_DIR=arm
+      INSTALL_ARCH_DIR=arm
+      JRE_ARCH_DIR=arm
+      ;;
+    mips)
+      BUILD_ARCH_DIR=mips
+      INSTALL_ARCH_DIR=mips
+      JRE_ARCH_DIR=mips
+       ;;
+    mipsel)
+      BUILD_ARCH_DIR=mipsel
+      INSTALL_ARCH_DIR=mipsel
+      JRE_ARCH_DIR=mipsel
+       ;;
+    powerpc)
+      BUILD_ARCH_DIR=ppc
+      INSTALL_ARCH_DIR=ppc
+      JRE_ARCH_DIR=ppc
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+       ;;
+    powerpc64)
+      BUILD_ARCH_DIR=ppc64
+      INSTALL_ARCH_DIR=ppc64
+      JRE_ARCH_DIR=ppc64
+      ARCHFLAG="-m64"
+       ;;
+    sparc)
+      BUILD_ARCH_DIR=sparc
+      INSTALL_ARCH_DIR=sparc
+      JRE_ARCH_DIR=sparc
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m32"
+       ;;
+    sparc64)
+      BUILD_ARCH_DIR=sparcv9
+      INSTALL_ARCH_DIR=sparcv9
+      JRE_ARCH_DIR=sparc64
+      ARCHFLAG="-m64"
+       ;;
+    s390)
+      BUILD_ARCH_DIR=s390
+      INSTALL_ARCH_DIR=s390
+      JRE_ARCH_DIR=s390
+      ARCH_PREFIX=${LINUX32}
+      ARCHFLAG="-m31"
+       ;;
+    s390x)
+      BUILD_ARCH_DIR=s390x
+      INSTALL_ARCH_DIR=s390x
+      JRE_ARCH_DIR=s390x
+      ARCHFLAG="-m64"
+       ;;
+    sh*)
+      BUILD_ARCH_DIR=sh
+      INSTALL_ARCH_DIR=sh
+      JRE_ARCH_DIR=sh
+      ;;
+    *)
+      BUILD_ARCH_DIR=`uname -m`
+      INSTALL_ARCH_DIR=$BUILD_ARCH_DIR
+      JRE_ARCH_DIR=$INSTALL_ARCH_DIR
+      ;;
+  esac
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if cp supports --reflink" >&5
+$as_echo_n "checking if cp supports --reflink... " >&6; }
+if ${it_cv_reflink+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    touch tmp.$$
+    if cp --reflink=auto tmp.$$ tmp2.$$ >&5 2>&1; then
+      it_cv_reflink=yes;
+    else
+      it_cv_reflink=no;
+    fi
+    rm -f tmp.$$ tmp2.$$
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_reflink" >&5
+$as_echo "$it_cv_reflink" >&6; }
+   if test x"${it_cv_reflink}" = "xyes"; then
+  CP_SUPPORTS_REFLINK_TRUE=
+  CP_SUPPORTS_REFLINK_FALSE='#'
+else
+  CP_SUPPORTS_REFLINK_TRUE='#'
+  CP_SUPPORTS_REFLINK_FALSE=
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can hard link rather than copy from ${abs_top_srcdir}" >&5
+$as_echo_n "checking if we can hard link rather than copy from ${abs_top_srcdir}... " >&6; }
+if ${it_cv_hardlink_src+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    if cp -l ${abs_top_srcdir}/README tmp.$$ >&5 2>&1; then
+      it_cv_hardlink_src=yes;
+    else
+      it_cv_hardlink_src=no;
+    fi
+    rm -f tmp.$$
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_hardlink_src" >&5
+$as_echo "$it_cv_hardlink_src" >&6; }
+   if test x"${it_cv_hardlink_src}" = "xyes"; then
+  SRC_DIR_HARDLINKABLE_TRUE=
+  SRC_DIR_HARDLINKABLE_FALSE='#'
+else
+  SRC_DIR_HARDLINKABLE_TRUE='#'
+  SRC_DIR_HARDLINKABLE_FALSE=
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build documentation" >&5
+$as_echo_n "checking whether to build documentation... " >&6; }
+# Check whether --enable-docs was given.
+if test "${enable_docs+set}" = set; then :
+  enableval=$enable_docs; ENABLE_DOCS="${enableval}"
+else
+  ENABLE_DOCS='yes'
+fi
+
+ if test x$ENABLE_DOCS = xyes; then
+  ENABLE_DOCS_TRUE=
+  ENABLE_DOCS_FALSE='#'
+else
+  ENABLE_DOCS_TRUE='#'
+  ENABLE_DOCS_FALSE=
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ENABLE_DOCS}" >&5
+$as_echo "${ENABLE_DOCS}" >&6; }
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile ecj natively" >&5
+$as_echo_n "checking whether to compile ecj natively... " >&6; }
+
+# Check whether --with-gcj was given.
+if test "${with_gcj+set}" = set; then :
+  withval=$with_gcj;
+    GCJ="${withval}"
+
+else
+
+    GCJ="no"
+
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${GCJ}" >&5
+$as_echo "${GCJ}" >&6; }
+  if test "x${GCJ}" = xyes; then
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcj", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcj; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GCJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GCJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GCJ="$GCJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_GCJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GCJ=$ac_cv_path_GCJ
+if test -n "$GCJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCJ" >&5
+$as_echo "$GCJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_GCJ"; then
+  ac_pt_GCJ=$GCJ
+  # Extract the first word of "gcj", so it can be a program name with args.
+set dummy gcj; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_GCJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_GCJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_GCJ="$ac_pt_GCJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_GCJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_GCJ=$ac_cv_path_ac_pt_GCJ
+if test -n "$ac_pt_GCJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GCJ" >&5
+$as_echo "$ac_pt_GCJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_GCJ" = x; then
+    GCJ=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    GCJ=$ac_pt_GCJ
+  fi
+else
+  GCJ="$ac_cv_path_GCJ"
+fi
+
+  fi
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}zip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}zip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ZIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ZIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ZIP=$ac_cv_path_ZIP
+if test -n "$ZIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP" >&5
+$as_echo "$ZIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_ZIP"; then
+  ac_pt_ZIP=$ZIP
+  # Extract the first word of "zip", so it can be a program name with args.
+set dummy zip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_ZIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_ZIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_ZIP="$ac_pt_ZIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_ZIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_ZIP=$ac_cv_path_ac_pt_ZIP
+if test -n "$ac_pt_ZIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ZIP" >&5
+$as_echo "$ac_pt_ZIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_ZIP" = x; then
+    ZIP=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    ZIP=$ac_pt_ZIP
+  fi
+else
+  ZIP="$ac_cv_path_ZIP"
+fi
+
+ if test x"$ZIP" = x ; then
+   as_fn_error $? "zip program not found in PATH" "$LINENO" 5
+ fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a JDK home directory" >&5
+$as_echo_n "checking for a JDK home directory... " >&6; }
+
+# Check whether --with-jdk-home was given.
+if test "${with_jdk_home+set}" = set; then :
+  withval=$with_jdk_home;
+                if test "x${withval}" = xyes
+                then
+                  SYSTEM_JDK_DIR=
+                elif test "x${withval}" = xno
+                then
+	          SYSTEM_JDK_DIR=
+	        else
+                  SYSTEM_JDK_DIR=${withval}
+                fi
+
+else
+
+	        SYSTEM_JDK_DIR=
+
+fi
+
+  if test -z "${SYSTEM_JDK_DIR}"; then
+    for dir in /usr/lib/jvm/java-openjdk /usr/lib/jvm/icedtea6 \
+    	      /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/openjdk \
+              /usr/lib/jvm/java-icedtea /usr/lib/jvm/java-gcj /usr/lib/jvm/gcj-jdk \
+              /usr/lib/jvm/cacao ; do
+       if test -d $dir; then
+         SYSTEM_JDK_DIR=$dir
+	 break
+       fi
+    done
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${SYSTEM_JDK_DIR}" >&5
+$as_echo "${SYSTEM_JDK_DIR}" >&6; }
+  if ! test -d "${SYSTEM_JDK_DIR}"; then
+    as_fn_error $? "\"A JDK home directory could not be found.\"" "$LINENO" 5
+  fi
+
+
+
+
+  JAVAC=${SYSTEM_JDK_DIR}/bin/javac
+
+
+# Check whether --with-javac was given.
+if test "${with_javac+set}" = set; then :
+  withval=$with_javac;
+    if test "x${withval}" != x && test "x${withval}" != xyes && test "x${withval}" != xno; then
+
+  if test "x${withval}" != x; then
+    if test -f "${withval}"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for javac" >&5
+$as_echo_n "checking for javac... " >&6; }
+      JAVAC="${withval}"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVAC}" >&5
+$as_echo "${JAVAC}" >&6; }
+    else
+      # Extract the first word of ""${withval}"", so it can be a program name with args.
+set dummy "${withval}"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""javac"", so it can be a program name with args.
+set dummy "javac"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+
+    else
+      if test "x${withval}" != xno; then
+
+  if test "x" != x; then
+    if test -f ""; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for javac" >&5
+$as_echo_n "checking for javac... " >&6; }
+      JAVAC=""
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVAC}" >&5
+$as_echo "${JAVAC}" >&6; }
+    else
+      # Extract the first word of """", so it can be a program name with args.
+set dummy ""; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""javac"", so it can be a program name with args.
+set dummy "javac"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+
+      fi
+    fi
+
+else
+
+
+  if test "x" != x; then
+    if test -f ""; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for javac" >&5
+$as_echo_n "checking for javac... " >&6; }
+      JAVAC=""
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVAC}" >&5
+$as_echo "${JAVAC}" >&6; }
+    else
+      # Extract the first word of """", so it can be a program name with args.
+set dummy ""; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""javac"", so it can be a program name with args.
+set dummy "javac"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+
+
+fi
+
+
+
+
+# Check whether --with-ecj was given.
+if test "${with_ecj+set}" = set; then :
+  withval=$with_ecj;
+    if test "x${withval}" != x && test "x${withval}" != xyes && test "x${withval}" != xno; then
+
+  if test "x${withval}" != x; then
+    if test -f "${withval}"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ecj" >&5
+$as_echo_n "checking for ecj... " >&6; }
+      ECJ="${withval}"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ECJ}" >&5
+$as_echo "${ECJ}" >&6; }
+    else
+      # Extract the first word of ""${withval}"", so it can be a program name with args.
+set dummy "${withval}"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""ecj"", so it can be a program name with args.
+set dummy "ecj"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.1"", so it can be a program name with args.
+set dummy "ecj-3.1"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.2"", so it can be a program name with args.
+set dummy "ecj-3.2"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.3"", so it can be a program name with args.
+set dummy "ecj-3.3"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  fi
+
+    else
+      if test "x${withval}" != xno; then
+
+  if test "x" != x; then
+    if test -f ""; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ecj" >&5
+$as_echo_n "checking for ecj... " >&6; }
+      ECJ=""
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ECJ}" >&5
+$as_echo "${ECJ}" >&6; }
+    else
+      # Extract the first word of """", so it can be a program name with args.
+set dummy ""; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""ecj"", so it can be a program name with args.
+set dummy "ecj"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.1"", so it can be a program name with args.
+set dummy "ecj-3.1"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.2"", so it can be a program name with args.
+set dummy "ecj-3.2"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.3"", so it can be a program name with args.
+set dummy "ecj-3.3"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  fi
+
+      fi
+    fi
+
+else
+
+
+  if test "x" != x; then
+    if test -f ""; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ecj" >&5
+$as_echo_n "checking for ecj... " >&6; }
+      ECJ=""
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ECJ}" >&5
+$as_echo "${ECJ}" >&6; }
+    else
+      # Extract the first word of """", so it can be a program name with args.
+set dummy ""; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  else
+    # Extract the first word of ""ecj"", so it can be a program name with args.
+set dummy "ecj"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.1"", so it can be a program name with args.
+set dummy "ecj-3.1"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.2"", so it can be a program name with args.
+set dummy "ecj-3.2"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+    if test -z "${ECJ}"; then
+      # Extract the first word of ""ecj-3.3"", so it can be a program name with args.
+set dummy "ecj-3.3"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ECJ+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ECJ in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ECJ="$ECJ" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ECJ="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ECJ=$ac_cv_path_ECJ
+if test -n "$ECJ"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECJ" >&5
+$as_echo "$ECJ" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    fi
+  fi
+
+
+fi
+
+  if test "x${JAVAC}" = "x"; then
+    if test "x{ECJ}" != "x"; then
+      JAVAC="${ECJ} -nowarn"
+    fi
+  fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we are using ecj as javac" >&5
+$as_echo_n "checking if we are using ecj as javac... " >&6; }
+if ${it_cv_ecj+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+if $JAVAC -version 2>&1| grep '^Eclipse' >&5 ; then
+  it_cv_ecj=yes;
+else
+  it_cv_ecj=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_ecj" >&5
+$as_echo "$it_cv_ecj" >&6; }
+USING_ECJ=$it_cv_ecj
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jar" >&5
+$as_echo_n "checking for jar... " >&6; }
+
+# Check whether --with-jar was given.
+if test "${with_jar+set}" = set; then :
+  withval=$with_jar;
+    JAR="${withval}"
+
+else
+
+    JAR=${SYSTEM_JDK_DIR}/bin/jar
+
+fi
+
+  if ! test -f "${JAR}"; then
+    # Extract the first word of ""${JAR}"", so it can be a program name with args.
+set dummy "${JAR}"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAR="$JAR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAR=$ac_cv_path_JAR
+if test -n "$JAR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5
+$as_echo "$JAR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAR}"; then
+    # Extract the first word of ""gjar"", so it can be a program name with args.
+set dummy "gjar"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAR="$JAR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAR=$ac_cv_path_JAR
+if test -n "$JAR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5
+$as_echo "$JAR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAR}"; then
+    # Extract the first word of ""jar"", so it can be a program name with args.
+set dummy "jar"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAR="$JAR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAR=$ac_cv_path_JAR
+if test -n "$JAR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5
+$as_echo "$JAR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAR}"; then
+    as_fn_error $? "\"No Java archive tool was found.\"" "$LINENO" 5
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAR}" >&5
+$as_echo "${JAR}" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether jar supports @<file> argument" >&5
+$as_echo_n "checking whether jar supports @<file> argument... " >&6; }
+  touch _config.txt
+  cat >_config.list <<EOF
+_config.txt
+EOF
+  if $JAR cf _config.jar @_config.list >&5 2>&1; then
+    JAR_KNOWS_ATFILE=1
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    JAR_KNOWS_ATFILE=
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether jar supports stdin file arguments" >&5
+$as_echo_n "checking whether jar supports stdin file arguments... " >&6; }
+  if cat _config.list | $JAR cf@ _config.jar >&5 2>&1; then
+    JAR_ACCEPTS_STDIN_LIST=1
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    JAR_ACCEPTS_STDIN_LIST=
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  rm -f _config.list _config.jar
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether jar supports -J options at the end" >&5
+$as_echo_n "checking whether jar supports -J options at the end... " >&6; }
+  if $JAR cf _config.jar _config.txt -J-Xmx896m >&5 2>&1; then
+    JAR_KNOWS_J_OPTIONS=1
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    JAR_KNOWS_J_OPTIONS=
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  rm -f _config.txt _config.jar
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ecj JAR file" >&5
+$as_echo_n "checking for an ecj JAR file... " >&6; }
+
+# Check whether --with-ecj-jar was given.
+if test "${with_ecj_jar+set}" = set; then :
+  withval=$with_ecj_jar;
+    if test -f "${withval}"; then
+      ECJ_JAR="${withval}"
+    fi
+
+else
+
+    ECJ_JAR=
+
+fi
+
+  if test -z "${ECJ_JAR}"; then
+    for jar in /usr/share/java/eclipse-ecj.jar \
+      /usr/share/java/ecj.jar \
+      /usr/share/eclipse-ecj-3.{2,3,4,5}/lib/ecj.jar; do
+        if test -e $jar; then
+          ECJ_JAR=$jar
+	  break
+        fi
+      done
+      if test -z "${ECJ_JAR}"; then
+        ECJ_JAR=no
+      fi
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ECJ_JAR}" >&5
+$as_echo "${ECJ_JAR}" >&6; }
+  if test "x${JAVAC}" = x && test "x${ECJ_JAR}" = "xno" ; then
+      as_fn_error $? "cannot find a Java compiler or ecj JAR file, try --with-javac, --with-ecj or --with-ecj-jar" "$LINENO" 5
+  fi
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for javadoc" >&5
+$as_echo_n "checking for javadoc... " >&6; }
+
+# Check whether --with-javadoc was given.
+if test "${with_javadoc+set}" = set; then :
+  withval=$with_javadoc;
+    JAVADOC="${withval}"
+
+else
+
+    JAVADOC=${SYSTEM_JDK_DIR}/bin/javadoc
+
+fi
+
+  if ! test -f "${JAVADOC}"; then
+    # Extract the first word of ""${JAVADOC}"", so it can be a program name with args.
+set dummy "${JAVADOC}"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVADOC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVADOC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVADOC="$JAVADOC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVADOC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVADOC=$ac_cv_path_JAVADOC
+if test -n "$JAVADOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVADOC" >&5
+$as_echo "$JAVADOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVADOC}"; then
+    # Extract the first word of ""javadoc"", so it can be a program name with args.
+set dummy "javadoc"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVADOC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVADOC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVADOC="$JAVADOC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVADOC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVADOC=$ac_cv_path_JAVADOC
+if test -n "$JAVADOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVADOC" >&5
+$as_echo "$JAVADOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVADOC}"; then
+    # Extract the first word of ""gjdoc"", so it can be a program name with args.
+set dummy "gjdoc"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVADOC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVADOC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVADOC="$JAVADOC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVADOC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVADOC=$ac_cv_path_JAVADOC
+if test -n "$JAVADOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVADOC" >&5
+$as_echo "$JAVADOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVADOC}" && test "x$ENABLE_DOCS" = "xyes"; then
+    as_fn_error $? "\"No Java documentation tool was found.\"" "$LINENO" 5
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVADOC}" >&5
+$as_echo "${JAVADOC}" >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether javadoc supports -J options" >&5
+$as_echo_n "checking whether javadoc supports -J options... " >&6; }
+  CLASS=pkg/Test.java
+  mkdir tmp.$$
+  cd tmp.$$
+  mkdir pkg
+  cat << \EOF > $CLASS
+/* [#]line 5834 "configure" */
+package pkg;
+
+public class Test
+{
+  /**
+   * Does stuff.
+   *
+   *
+   * @param args arguments from cli.
+   */
+  public static void main(String[] args)
+  {
+    System.out.println("Hello World!");
+  }
+}
+
+EOF
+  if $JAVADOC -J-Xmx896m pkg >&5 2>&1; then
+    JAVADOC_KNOWS_J_OPTIONS=yes
+  else
+    JAVADOC_KNOWS_J_OPTIONS=no
+  fi
+  cd ..
+  rm -rf tmp.$$
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVADOC_KNOWS_J_OPTIONS}" >&5
+$as_echo "${JAVADOC_KNOWS_J_OPTIONS}" >&6; }
+
+
+   if test x"${JAVADOC_KNOWS_J_OPTIONS}" = "xyes"; then
+  JAVADOC_SUPPORTS_J_OPTIONS_TRUE=
+  JAVADOC_SUPPORTS_J_OPTIONS_FALSE='#'
+else
+  JAVADOC_SUPPORTS_J_OPTIONS_TRUE='#'
+  JAVADOC_SUPPORTS_J_OPTIONS_FALSE=
+fi
+
+
+ac_config_files="$ac_config_files javac"
+
+
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}hg", so it can be a program name with args.
+set dummy ${ac_tool_prefix}hg; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_HG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $HG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_HG="$HG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_HG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+HG=$ac_cv_path_HG
+if test -n "$HG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HG" >&5
+$as_echo "$HG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_HG"; then
+  ac_pt_HG=$HG
+  # Extract the first word of "hg", so it can be a program name with args.
+set dummy hg; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_HG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_HG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_HG="$ac_pt_HG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_HG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_HG=$ac_cv_path_ac_pt_HG
+if test -n "$ac_pt_HG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_HG" >&5
+$as_echo "$ac_pt_HG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_HG" = x; then
+    HG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    HG=$ac_pt_HG
+  fi
+else
+  HG="$ac_cv_path_HG"
+fi
+
+
+
+
+
+  ICEDTEA_REVISION="none";
+  if which ${HG} >&5 2>&1; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IcedTea Mercurial revision ID" >&5
+$as_echo_n "checking for IcedTea Mercurial revision ID... " >&6; }
+    if test -e ${abs_top_srcdir}/.hg ; then
+      ICEDTEA_REVISION="r`(cd ${abs_top_srcdir}; ${HG} id -i)`" ;
+    fi ;
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ICEDTEA_REVISION}" >&5
+$as_echo "${ICEDTEA_REVISION}" >&6; }
+
+  fi;
+   if test "x${ICEDTEA_REVISION}" != xnone; then
+  HAS_ICEDTEA_REVISION_TRUE=
+  HAS_ICEDTEA_REVISION_FALSE='#'
+else
+  HAS_ICEDTEA_REVISION_TRUE='#'
+  HAS_ICEDTEA_REVISION_FALSE=
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for distribution package version" >&5
+$as_echo_n "checking for distribution package version... " >&6; }
+
+# Check whether --with-pkgversion was given.
+if test "${with_pkgversion+set}" = set; then :
+  withval=$with_pkgversion; case "$withval" in
+          yes) as_fn_error $? "package version not specified" "$LINENO" 5 ;;
+          no)  PKGVERSION=none ;;
+          *)   PKGVERSION="$withval" ;;
+         esac
+else
+  PKGVERSION=none
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${PKGVERSION}" >&5
+$as_echo "${PKGVERSION}" >&6; }
+ if test "x${PKGVERSION}" != "xnone"; then
+  HAS_PKGVERSION_TRUE=
+  HAS_PKGVERSION_FALSE='#'
+else
+  HAS_PKGVERSION_TRUE='#'
+  HAS_PKGVERSION_FALSE=
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking what version string to use" >&5
+$as_echo_n "checking what version string to use... " >&6; }
+  if test "x${ICEDTEA_REVISION}" != xnone; then
+    ICEDTEA_REV="+${ICEDTEA_REVISION}"
+  fi
+  if test "x${PKGVERSION}" != "xnone"; then
+    ICEDTEA_PKG=" (${PKGVERSION})"
+  fi
+  FULL_VERSION="${PACKAGE_VERSION}${ICEDTEA_REV}${ICEDTEA_PKG}"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${FULL_VERSION}" >&5
+$as_echo "${FULL_VERSION}" >&6; }
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build the browser plugin" >&5
+$as_echo_n "checking whether to build the browser plugin... " >&6; }
+# Check whether --enable-plugin was given.
+if test "${enable_plugin+set}" = set; then :
+  enableval=$enable_plugin; enable_plugin="${enableval}"
+else
+  enable_plugin="yes"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_plugin}" >&5
+$as_echo "${enable_plugin}" >&6; }
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+fi
+
+
+if test "x${enable_plugin}" = "xyes" ; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5
+$as_echo_n "checking for GTK... " >&6; }
+
+if test -n "$GTK_CFLAGS"; then
+    pkg_cv_GTK_CFLAGS="$GTK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GTK_LIBS"; then
+    pkg_cv_GTK_LIBS="$GTK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gtk+-2.0" 2>&1`
+        else
+	        GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors "gtk+-2.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$GTK_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (gtk+-2.0) were not met:
+
+$GTK_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GTK_CFLAGS
+and GTK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GTK_CFLAGS
+and GTK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+
+else
+	GTK_CFLAGS=$pkg_cv_GTK_CFLAGS
+	GTK_LIBS=$pkg_cv_GTK_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5
+$as_echo_n "checking for GLIB... " >&6; }
+
+if test -n "$GLIB_CFLAGS"; then
+    pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GLIB_LIBS"; then
+    pkg_cv_GLIB_LIBS="$GLIB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "glib-2.0" 2>&1`
+        else
+	        GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors "glib-2.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$GLIB_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (glib-2.0) were not met:
+
+$GLIB_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+
+else
+	GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
+	GLIB_LIBS=$pkg_cv_GLIB_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MOZILLA" >&5
+$as_echo_n "checking for MOZILLA... " >&6; }
+
+if test -n "$MOZILLA_CFLAGS"; then
+    pkg_cv_MOZILLA_CFLAGS="$MOZILLA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mozilla-plugin\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "mozilla-plugin") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_MOZILLA_CFLAGS=`$PKG_CONFIG --cflags "mozilla-plugin" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$MOZILLA_LIBS"; then
+    pkg_cv_MOZILLA_LIBS="$MOZILLA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mozilla-plugin\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "mozilla-plugin") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_MOZILLA_LIBS=`$PKG_CONFIG --libs "mozilla-plugin" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        MOZILLA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "mozilla-plugin" 2>&1`
+        else
+	        MOZILLA_PKG_ERRORS=`$PKG_CONFIG --print-errors "mozilla-plugin" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$MOZILLA_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (mozilla-plugin) were not met:
+
+$MOZILLA_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables MOZILLA_CFLAGS
+and MOZILLA_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables MOZILLA_CFLAGS
+and MOZILLA_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+
+else
+	MOZILLA_CFLAGS=$pkg_cv_MOZILLA_CFLAGS
+	MOZILLA_LIBS=$pkg_cv_MOZILLA_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+
+fi
+ if test "x${enable_plugin}" = "xyes"; then
+  ENABLE_PLUGIN_TRUE=
+  ENABLE_PLUGIN_FALSE='#'
+else
+  ENABLE_PLUGIN_TRUE='#'
+  ENABLE_PLUGIN_FALSE=
+fi
+
+
+
+
+if test "x${enable_plugin}" = "xyes"
+then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xulrunner version" >&5
+$as_echo_n "checking for xulrunner version... " >&6; }
+if ${xulrunner_cv_collapsed_version+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    if pkg-config --modversion libxul >/dev/null 2>&1
+    then
+      xulrunner_cv_collapsed_version=`pkg-config --modversion libxul | awk -F. '{power=6; v=0; for (i=1; i <= NF; i++) {v += $i * 10 ^ power; power -=2}; print v}'`
+    else
+      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot determine xulrunner version
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xulrunner_cv_collapsed_version" >&5
+$as_echo "$xulrunner_cv_collapsed_version" >&6; }
+  MOZILLA_VERSION_COLLAPSED=$xulrunner_cv_collapsed_version
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5
+$as_echo_n "checking for main in -lz... " >&6; }
+if ${ac_cv_lib_z_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_z_main=yes
+else
+  ac_cv_lib_z_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5
+$as_echo "$ac_cv_lib_z_main" >&6; }
+if test "x$ac_cv_lib_z_main" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+  LIBS="-lz $LIBS"
+
+else
+  as_fn_error $? "\"zlib not found - try installing zlib-devel\"" "$LINENO" 5
+fi
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11" >&5
+$as_echo_n "checking for X11... " >&6; }
+
+if test -n "$X11_CFLAGS"; then
+    pkg_cv_X11_CFLAGS="$X11_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "x11") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_X11_CFLAGS=`$PKG_CONFIG --cflags "x11" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$X11_LIBS"; then
+    pkg_cv_X11_LIBS="$X11_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "x11") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_X11_LIBS=`$PKG_CONFIG --libs "x11" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        X11_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "x11" 2>&1`
+        else
+	        X11_PKG_ERRORS=`$PKG_CONFIG --print-errors "x11" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$X11_PKG_ERRORS" >&5
+
+	X11_FOUND=no
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	X11_FOUND=no
+else
+	X11_CFLAGS=$pkg_cv_X11_CFLAGS
+	X11_LIBS=$pkg_cv_X11_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	X11_FOUND=yes
+fi
+if test "x${X11_FOUND}" = xno
+then
+  as_fn_error $? "Could not find x11 - \
+  Try installing libX11-devel." "$LINENO" 5
+fi
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a JRE home directory" >&5
+$as_echo_n "checking for a JRE home directory... " >&6; }
+
+# Check whether --with-jre-home was given.
+if test "${with_jre_home+set}" = set; then :
+  withval=$with_jre_home;
+               SYSTEM_JRE_DIR=${withval}
+
+else
+
+               SYSTEM_JRE_DIR=
+
+fi
+
+  if test -z "${SYSTEM_JRE_DIR}" ; then
+    if test -d "${SYSTEM_JDK_DIR}/jre" ; then
+      SYSTEM_JRE_DIR="${SYSTEM_JDK_DIR}/jre"
+    fi
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${SYSTEM_JRE_DIR}" >&5
+$as_echo "${SYSTEM_JRE_DIR}" >&6; }
+  if ! test -d "${SYSTEM_JRE_DIR}"; then
+    as_fn_error $? "\"A JRE home directory could not be found.\"" "$LINENO" 5
+  fi
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Java virtual machine" >&5
+$as_echo_n "checking for a Java virtual machine... " >&6; }
+
+# Check whether --with-java was given.
+if test "${with_java+set}" = set; then :
+  withval=$with_java;
+    JAVA="${withval}"
+
+else
+
+    JAVA="${SYSTEM_JRE_DIR}/bin/java"
+
+fi
+
+  if ! test -f "${JAVA}"; then
+    # Extract the first word of ""${JAVA}"", so it can be a program name with args.
+set dummy "${JAVA}"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVA+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVA in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVA="$JAVA" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVA="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVA=$ac_cv_path_JAVA
+if test -n "$JAVA"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5
+$as_echo "$JAVA" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVA}"; then
+    # Extract the first word of ""java"", so it can be a program name with args.
+set dummy "java"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVA+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVA in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVA="$JAVA" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVA="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVA=$ac_cv_path_JAVA
+if test -n "$JAVA"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5
+$as_echo "$JAVA" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVA}"; then
+    # Extract the first word of ""gij"", so it can be a program name with args.
+set dummy "gij"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVA+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVA in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVA="$JAVA" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_JAVA="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVA=$ac_cv_path_JAVA
+if test -n "$JAVA"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5
+$as_echo "$JAVA" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+  if test -z "${JAVA}"; then
+    as_fn_error $? "\"A 1.5-compatible Java VM is required.\"" "$LINENO" 5
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JAVA}" >&5
+$as_echo "${JAVA}" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if java.util.jar.Pack200 is available" >&5
+$as_echo_n "checking if java.util.jar.Pack200 is available... " >&6; }
+if ${it_cv_JAVA_UTIL_JAR_PACK200+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 6804 "configure" */
+package sun.applet;
+
+import java.util.jar.Pack200;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("java.util.jar.Pack200"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_JAVA_UTIL_JAR_PACK200=yes;
+  else
+      it_cv_JAVA_UTIL_JAR_PACK200=no;
+  fi
+else
+  it_cv_JAVA_UTIL_JAR_PACK200=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_JAVA_UTIL_JAR_PACK200" >&5
+$as_echo "$it_cv_JAVA_UTIL_JAR_PACK200" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_JAVA_UTIL_JAR_PACK200}" = "xno"; then
+   as_fn_error $? "java.util.jar.Pack200 not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if java.net.CookieManager is available" >&5
+$as_echo_n "checking if java.net.CookieManager is available... " >&6; }
+if ${it_cv_JAVA_NET_COOKIEMANAGER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 6854 "configure" */
+package sun.applet;
+
+import java.net.CookieManager;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("java.net.CookieManager"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_JAVA_NET_COOKIEMANAGER=yes;
+  else
+      it_cv_JAVA_NET_COOKIEMANAGER=no;
+  fi
+else
+  it_cv_JAVA_NET_COOKIEMANAGER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_JAVA_NET_COOKIEMANAGER" >&5
+$as_echo "$it_cv_JAVA_NET_COOKIEMANAGER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_JAVA_NET_COOKIEMANAGER}" = "xno"; then
+   as_fn_error $? "java.net.CookieManager not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if java.net.HttpCookie is available" >&5
+$as_echo_n "checking if java.net.HttpCookie is available... " >&6; }
+if ${it_cv_JAVA_NET_HTTPCOOKIE+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 6904 "configure" */
+package sun.applet;
+
+import java.net.HttpCookie;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("java.net.HttpCookie"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_JAVA_NET_HTTPCOOKIE=yes;
+  else
+      it_cv_JAVA_NET_HTTPCOOKIE=no;
+  fi
+else
+  it_cv_JAVA_NET_HTTPCOOKIE=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_JAVA_NET_HTTPCOOKIE" >&5
+$as_echo "$it_cv_JAVA_NET_HTTPCOOKIE" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_JAVA_NET_HTTPCOOKIE}" = "xno"; then
+   as_fn_error $? "java.net.HttpCookie not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if java.net.CookieHandler is available" >&5
+$as_echo_n "checking if java.net.CookieHandler is available... " >&6; }
+if ${it_cv_JAVA_NET_COOKIEHANDLER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 6954 "configure" */
+package sun.applet;
+
+import java.net.CookieHandler;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("java.net.CookieHandler"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_JAVA_NET_COOKIEHANDLER=yes;
+  else
+      it_cv_JAVA_NET_COOKIEHANDLER=no;
+  fi
+else
+  it_cv_JAVA_NET_COOKIEHANDLER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_JAVA_NET_COOKIEHANDLER" >&5
+$as_echo "$it_cv_JAVA_NET_COOKIEHANDLER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_JAVA_NET_COOKIEHANDLER}" = "xno"; then
+   as_fn_error $? "java.net.CookieHandler not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.security.provider.X509Factory is available" >&5
+$as_echo_n "checking if sun.security.provider.X509Factory is available... " >&6; }
+if ${it_cv_SUN_SECURITY_PROVIDER_X509FACTORY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7004 "configure" */
+package sun.applet;
+
+import sun.security.provider.X509Factory;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.security.provider.X509Factory"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_SECURITY_PROVIDER_X509FACTORY=yes;
+  else
+      it_cv_SUN_SECURITY_PROVIDER_X509FACTORY=no;
+  fi
+else
+  it_cv_SUN_SECURITY_PROVIDER_X509FACTORY=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_SECURITY_PROVIDER_X509FACTORY" >&5
+$as_echo "$it_cv_SUN_SECURITY_PROVIDER_X509FACTORY" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_SECURITY_PROVIDER_X509FACTORY}" = "xno"; then
+   as_fn_error $? "sun.security.provider.X509Factory not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.security.util.SecurityConstants is available" >&5
+$as_echo_n "checking if sun.security.util.SecurityConstants is available... " >&6; }
+if ${it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7054 "configure" */
+package sun.applet;
+
+import sun.security.util.SecurityConstants;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.security.util.SecurityConstants"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS=yes;
+  else
+      it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS=no;
+  fi
+else
+  it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS" >&5
+$as_echo "$it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_SECURITY_UTIL_SECURITYCONSTANTS}" = "xno"; then
+   as_fn_error $? "sun.security.util.SecurityConstants not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.security.util.HostnameChecker is available" >&5
+$as_echo_n "checking if sun.security.util.HostnameChecker is available... " >&6; }
+if ${it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7104 "configure" */
+package sun.applet;
+
+import sun.security.util.HostnameChecker;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.security.util.HostnameChecker"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER=yes;
+  else
+      it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER=no;
+  fi
+else
+  it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER" >&5
+$as_echo "$it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_SECURITY_UTIL_HOSTNAMECHECKER}" = "xno"; then
+   as_fn_error $? "sun.security.util.HostnameChecker not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.security.x509.X500Name is available" >&5
+$as_echo_n "checking if sun.security.x509.X500Name is available... " >&6; }
+if ${it_cv_SUN_SECURITY_X509_X500NAME+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7154 "configure" */
+package sun.applet;
+
+import sun.security.x509.X500Name;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.security.x509.X500Name"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_SECURITY_X509_X500NAME=yes;
+  else
+      it_cv_SUN_SECURITY_X509_X500NAME=no;
+  fi
+else
+  it_cv_SUN_SECURITY_X509_X500NAME=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_SECURITY_X509_X500NAME" >&5
+$as_echo "$it_cv_SUN_SECURITY_X509_X500NAME" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_SECURITY_X509_X500NAME}" = "xno"; then
+   as_fn_error $? "sun.security.x509.X500Name not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.misc.BASE64Encoder is available" >&5
+$as_echo_n "checking if sun.misc.BASE64Encoder is available... " >&6; }
+if ${it_cv_SUN_MISC_BASE64ENCODER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7204 "configure" */
+package sun.applet;
+
+import sun.misc.BASE64Encoder;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.misc.BASE64Encoder"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_MISC_BASE64ENCODER=yes;
+  else
+      it_cv_SUN_MISC_BASE64ENCODER=no;
+  fi
+else
+  it_cv_SUN_MISC_BASE64ENCODER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_MISC_BASE64ENCODER" >&5
+$as_echo "$it_cv_SUN_MISC_BASE64ENCODER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_MISC_BASE64ENCODER}" = "xno"; then
+   as_fn_error $? "sun.misc.BASE64Encoder not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.misc.HexDumpEncoder is available" >&5
+$as_echo_n "checking if sun.misc.HexDumpEncoder is available... " >&6; }
+if ${it_cv_SUN_MISC_HEXDUMPENCODER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7254 "configure" */
+package sun.applet;
+
+import sun.misc.HexDumpEncoder;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.misc.HexDumpEncoder"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_MISC_HEXDUMPENCODER=yes;
+  else
+      it_cv_SUN_MISC_HEXDUMPENCODER=no;
+  fi
+else
+  it_cv_SUN_MISC_HEXDUMPENCODER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_MISC_HEXDUMPENCODER" >&5
+$as_echo "$it_cv_SUN_MISC_HEXDUMPENCODER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_MISC_HEXDUMPENCODER}" = "xno"; then
+   as_fn_error $? "sun.misc.HexDumpEncoder not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.security.validator.ValidatorException is available" >&5
+$as_echo_n "checking if sun.security.validator.ValidatorException is available... " >&6; }
+if ${it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7304 "configure" */
+package sun.applet;
+
+import sun.security.validator.ValidatorException;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.security.validator.ValidatorException"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION=yes;
+  else
+      it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION=no;
+  fi
+else
+  it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION" >&5
+$as_echo "$it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION}" = "xno"; then
+   as_fn_error $? "sun.security.validator.ValidatorException not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager is available" >&5
+$as_echo_n "checking if com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager is available... " >&6; }
+if ${it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7354 "configure" */
+package sun.applet;
+
+import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER=yes;
+  else
+      it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER=no;
+  fi
+else
+  it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER" >&5
+$as_echo "$it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER}" = "xno"; then
+   as_fn_error $? "com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.awt.X11.XEmbeddedFrame is available" >&5
+$as_echo_n "checking if sun.awt.X11.XEmbeddedFrame is available... " >&6; }
+if ${it_cv_SUN_AWT_X11_XEMBEDDEDFRAME+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7404 "configure" */
+package sun.applet;
+
+import sun.awt.X11.XEmbeddedFrame;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.awt.X11.XEmbeddedFrame"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_AWT_X11_XEMBEDDEDFRAME=yes;
+  else
+      it_cv_SUN_AWT_X11_XEMBEDDEDFRAME=no;
+  fi
+else
+  it_cv_SUN_AWT_X11_XEMBEDDEDFRAME=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_AWT_X11_XEMBEDDEDFRAME" >&5
+$as_echo "$it_cv_SUN_AWT_X11_XEMBEDDEDFRAME" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_AWT_X11_XEMBEDDEDFRAME}" = "xno"; then
+   as_fn_error $? "sun.awt.X11.XEmbeddedFrame not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.misc.Ref is available" >&5
+$as_echo_n "checking if sun.misc.Ref is available... " >&6; }
+if ${it_cv_SUN_MISC_REF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7454 "configure" */
+package sun.applet;
+
+import sun.misc.Ref;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.misc.Ref"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_MISC_REF=yes;
+  else
+      it_cv_SUN_MISC_REF=no;
+  fi
+else
+  it_cv_SUN_MISC_REF=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_MISC_REF" >&5
+$as_echo "$it_cv_SUN_MISC_REF" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_MISC_REF}" = "xno"; then
+   as_fn_error $? "sun.misc.Ref not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if com.sun.jndi.toolkit.url.UrlUtil is available" >&5
+$as_echo_n "checking if com.sun.jndi.toolkit.url.UrlUtil is available... " >&6; }
+if ${it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7504 "configure" */
+package sun.applet;
+
+import com.sun.jndi.toolkit.url.UrlUtil;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("com.sun.jndi.toolkit.url.UrlUtil"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL=yes;
+  else
+      it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL=no;
+  fi
+else
+  it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL" >&5
+$as_echo "$it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_COM_SUN_JNDI_TOOLKIT_URL_URLUTIL}" = "xno"; then
+   as_fn_error $? "com.sun.jndi.toolkit.url.UrlUtil not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.applet.AppletImageRef is available" >&5
+$as_echo_n "checking if sun.applet.AppletImageRef is available... " >&6; }
+if ${it_cv_SUN_APPLET_APPLETIMAGEREF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=sun/applet/Test.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$/$(dirname $CLASS)
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7554 "configure" */
+package sun.applet;
+
+import sun.applet.AppletImageRef;
+
+public class Test
+{
+  public static void main(String[] args)
+    throws Exception
+  {
+    System.out.println(Class.forName("sun.applet.AppletImageRef"));
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_SUN_APPLET_APPLETIMAGEREF=yes;
+  else
+      it_cv_SUN_APPLET_APPLETIMAGEREF=no;
+  fi
+else
+  it_cv_SUN_APPLET_APPLETIMAGEREF=no;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_SUN_APPLET_APPLETIMAGEREF" >&5
+$as_echo "$it_cv_SUN_APPLET_APPLETIMAGEREF" >&6; }
+rm -f $CLASS *.class
+cd ..
+# should be rmdir but has to be rm -rf due to sun.applet usage
+rm -rf tmp.$$
+if test x"${it_cv_SUN_APPLET_APPLETIMAGEREF}" = "xno"; then
+   as_fn_error $? "sun.applet.AppletImageRef not found." "$LINENO" 5
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sun.applet.AppletViewerPanel is available and public" >&5
+$as_echo_n "checking if sun.applet.AppletViewerPanel is available and public... " >&6; }
+if ${it_cv_applet_hole+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+CLASS=TestAppletViewer.java
+BYTECODE=$(echo $CLASS|sed 's#\.java##')
+mkdir -p tmp.$$
+cd tmp.$$
+cat << \EOF > $CLASS
+/* [#]line 7604 "configure" */
+import java.lang.reflect.Modifier;
+
+public class TestAppletViewer
+{
+  public static void main(String[] args)
+  {
+    try
+      {
+        Class<?> clazz = Class.forName("sun.applet.AppletViewerPanel");
+        if (Modifier.isPublic(clazz.getModifiers()))
+          {
+            System.err.println("Found public sun.applet.AppletViewerPanel");
+            System.exit(0);
+          }
+        System.err.println("Found non-public sun.applet.AppletViewerPanel");
+        System.exit(2);
+      }
+    catch (ClassNotFoundException e)
+      {
+        System.err.println("Could not find sun.applet.AppletViewerPanel");
+        System.exit(1);
+      }
+  }
+}
+
+EOF
+if $JAVAC -cp . $JAVACFLAGS -nowarn $CLASS >&5 2>&1; then
+  if $JAVA -classpath . $BYTECODE >&5 2>&1; then
+      it_cv_applet_hole=yes;
+  else
+      it_cv_applet_hole=$?;
+  fi
+else
+  it_cv_applet_hole=3;
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $it_cv_applet_hole" >&5
+$as_echo "$it_cv_applet_hole" >&6; }
+rm -f $CLASS *.class
+cd ..
+rmdir tmp.$$
+if test x"${it_cv_applet_hole}" = "x1"; then
+   as_fn_error $? "sun.applet.AppletViewerPanel is not available." "$LINENO" 5
+elif test x"${it_cv_applet_hole}" = "x2"; then
+   as_fn_error $? "sun.applet.AppletViewerPanel is not public." "$LINENO" 5
+elif test x"${it_cv_applet_hole}" = "x3"; then
+   as_fn_error $? "Compilation failed.  See config.log." "$LINENO" 5
+fi
+
+
+#
+# Find optional depedencies
+#
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rhino jar" >&5
+$as_echo_n "checking for rhino jar... " >&6; }
+
+# Check whether --with-rhino was given.
+if test "${with_rhino+set}" = set; then :
+  withval=$with_rhino;
+    case "${withval}" in
+      yes)
+        RHINO_JAR=yes
+        ;;
+      no)
+        RHINO_JAR=no
+        ;;
+      *)
+        if test -f "${withval}"; then
+          RHINO_JAR="${withval}"
+        elif test -z "${withval}"; then
+          RHINO_JAR=yes
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+          as_fn_error $? "\"The rhino jar ${withval} was not found.\"" "$LINENO" 5
+        fi
+        ;;
+    esac
+
+else
+
+    RHINO_JAR=yes
+
+fi
+
+  it_extra_paths_rhino="/usr/share/java/js.jar /usr/share/rhino-1.6/lib/js.jar"
+  if test "x${RHINO_JAR}" = "xyes"; then
+    for path in ${it_extra_paths_rhino}; do
+      if test -f ${path}; then
+        RHINO_JAR=${path}
+        break
+      fi
+    done
+  fi
+  if test x"${RHINO_JAR}" = "xyes"; then
+    if test -f "/usr/share/java/rhino.jar"; then
+      RHINO_JAR=/usr/share/java/rhino.jar
+    fi
+  fi
+  if test x"${RHINO_JAR}" = "xyes"; then
+    RHINO_JAR=no
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${RHINO_JAR}" >&5
+$as_echo "${RHINO_JAR}" >&6; }
+   if test x"${RHINO_JAR}" != "xno"; then
+  WITH_RHINO_TRUE=
+  WITH_RHINO_FALSE='#'
+else
+  WITH_RHINO_TRUE='#'
+  WITH_RHINO_FALSE=
+fi
+
+  # Clear RHINO_JAR if it doesn't contain a valid filename
+  if test x"${RHINO_JAR}" = "xno"; then
+    RHINO_JAR=
+  fi
+  if test -n "${RHINO_JAR}" ; then
+    RHINO_AVAILABLE=true
+  else
+    RHINO_AVAILABLE=false
+  fi
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for junit jar" >&5
+$as_echo_n "checking for junit jar... " >&6; }
+
+# Check whether --with-junit was given.
+if test "${with_junit+set}" = set; then :
+  withval=$with_junit;
+    case "${withval}" in
+      yes)
+        JUNIT_JAR=yes
+        ;;
+      no)
+        JUNIT_JAR=no
+        ;;
+      *)
+        if test -f "${withval}"; then
+          JUNIT_JAR="${withval}"
+        elif test -z "${withval}"; then
+          JUNIT_JAR=yes
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+          as_fn_error $? "\"The junit jar ${withval} was not found.\"" "$LINENO" 5
+        fi
+        ;;
+    esac
+
+else
+
+    JUNIT_JAR=yes
+
+fi
+
+  it_extra_paths_junit="/usr/share/java/junit4.jar /usr/share/junit-4/lib/junit.jar"
+  if test "x${JUNIT_JAR}" = "xyes"; then
+    for path in ${it_extra_paths_junit}; do
+      if test -f ${path}; then
+        JUNIT_JAR=${path}
+        break
+      fi
+    done
+  fi
+  if test x"${JUNIT_JAR}" = "xyes"; then
+    if test -f "/usr/share/java/junit.jar"; then
+      JUNIT_JAR=/usr/share/java/junit.jar
+    fi
+  fi
+  if test x"${JUNIT_JAR}" = "xyes"; then
+    JUNIT_JAR=no
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JUNIT_JAR}" >&5
+$as_echo "${JUNIT_JAR}" >&6; }
+   if test x"${JUNIT_JAR}" != "xno"; then
+  WITH_JUNIT_TRUE=
+  WITH_JUNIT_FALSE='#'
+else
+  WITH_JUNIT_TRUE='#'
+  WITH_JUNIT_FALSE=
+fi
+
+  # Clear JUNIT_JAR if it doesn't contain a valid filename
+  if test x"${JUNIT_JAR}" = "xno"; then
+    JUNIT_JAR=
+  fi
+  if test -n "${JUNIT_JAR}" ; then
+    JUNIT_AVAILABLE=true
+  else
+    JUNIT_AVAILABLE=false
+  fi
+
+
+
+
+ac_config_files="$ac_config_files jrunscript"
+
+ac_config_files="$ac_config_files build.properties"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CP_SUPPORTS_REFLINK_TRUE}" && test -z "${CP_SUPPORTS_REFLINK_FALSE}"; then
+  as_fn_error $? "conditional \"CP_SUPPORTS_REFLINK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SRC_DIR_HARDLINKABLE_TRUE}" && test -z "${SRC_DIR_HARDLINKABLE_FALSE}"; then
+  as_fn_error $? "conditional \"SRC_DIR_HARDLINKABLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_DOCS_TRUE}" && test -z "${ENABLE_DOCS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_DOCS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${JAVADOC_SUPPORTS_J_OPTIONS_TRUE}" && test -z "${JAVADOC_SUPPORTS_J_OPTIONS_FALSE}"; then
+  as_fn_error $? "conditional \"JAVADOC_SUPPORTS_J_OPTIONS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAS_ICEDTEA_REVISION_TRUE}" && test -z "${HAS_ICEDTEA_REVISION_FALSE}"; then
+  as_fn_error $? "conditional \"HAS_ICEDTEA_REVISION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAS_PKGVERSION_TRUE}" && test -z "${HAS_PKGVERSION_FALSE}"; then
+  as_fn_error $? "conditional \"HAS_PKGVERSION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_PLUGIN_TRUE}" && test -z "${ENABLE_PLUGIN_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_PLUGIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_RHINO_TRUE}" && test -z "${WITH_RHINO_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_RHINO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_JUNIT_TRUE}" && test -z "${WITH_JUNIT_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_JUNIT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by icedtea-web $as_me 1.1.2, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to <distro-pkg-dev@openjdk.java.net>.
+icedtea-web home page: <http://icedtea.classpath.org/wiki/IcedTea-Web>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+icedtea-web config.status 1.1.2
+configured by $0, generated by GNU Autoconf 2.68,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "netx.manifest") CONFIG_FILES="$CONFIG_FILES netx.manifest" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "javac") CONFIG_FILES="$CONFIG_FILES javac" ;;
+    "jrunscript") CONFIG_FILES="$CONFIG_FILES jrunscript" ;;
+    "build.properties") CONFIG_FILES="$CONFIG_FILES build.properties" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "javac":F) chmod +x javac ;;
+    "jrunscript":F) chmod u+x jrunscript ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
Index: /tags/icedtea-web/beta/configure.ac
===================================================================
--- /tags/icedtea-web/beta/configure.ac	(revision 403)
+++ /tags/icedtea-web/beta/configure.ac	(revision 403)
@@ -0,0 +1,94 @@
+AC_INIT([icedtea-web],[1.1.2],[distro-pkg-dev@openjdk.java.net], [icedtea-web], [http://icedtea.classpath.org/wiki/IcedTea-Web])
+AM_INIT_AUTOMAKE([1.9 tar-pax foreign])
+AC_CONFIG_FILES([Makefile netx.manifest])
+
+# Older automake doesn't generate these correctly
+abs_top_builddir=`pwd -P`
+AC_SUBST(abs_top_builddir)
+abs_top_srcdir=`dirname $0`
+cd $abs_top_srcdir
+abs_top_srcdir=`pwd`
+cd $abs_top_builddir
+AC_SUBST(abs_top_srcdir)
+
+AC_CANONICAL_HOST
+AC_PROG_CC
+AC_PROG_CXX
+IT_SET_ARCH_SETTINGS
+
+IT_CP_SUPPORTS_REFLINK
+IT_CAN_HARDLINK_TO_SOURCE_TREE
+
+AC_MSG_CHECKING([whether to build documentation])
+AC_ARG_ENABLE([docs],
+	      [AS_HELP_STRING([--disable-docs],
+	      		      [Disable generation of documentation])],
+	      [ENABLE_DOCS="${enableval}"], [ENABLE_DOCS='yes'])
+AM_CONDITIONAL([ENABLE_DOCS], [test x$ENABLE_DOCS = xyes])
+AC_MSG_RESULT(${ENABLE_DOCS})
+
+IT_CHECK_WITH_GCJ
+FIND_TOOL([ZIP], [zip])
+FIND_JAVAC
+FIND_JAR
+FIND_ECJ_JAR
+IT_FIND_JAVADOC
+AC_CONFIG_FILES([javac], [chmod +x javac])
+
+IT_SET_VERSION
+IT_CHECK_XULRUNNER_VERSION
+
+AC_CHECK_LIB(z, main,, [AC_MSG_ERROR("zlib not found - try installing zlib-devel")])
+dnl Check for libX11 headers and libraries.
+PKG_CHECK_MODULES(X11, x11,[X11_FOUND=yes],[X11_FOUND=no])
+if test "x${X11_FOUND}" = xno
+then
+  AC_MSG_ERROR([Could not find x11 - \
+  Try installing libX11-devel.])
+fi
+AC_SUBST(X11_CFLAGS)
+AC_SUBST(X11_LIBS)
+
+dnl PR46074 (gcc) - Missing java.net cookie code required by IcedTea plugin
+dnl IT563 - NetX uses sun.security code
+dnl IT564 - NetX depends on sun.misc.BASE64Encoder
+dnl IT605 - NetX depends on sun.misc.HexDumpEncoder
+dnl IT570 - NetX depends on sun.applet.AppletViewPanel
+dnl IT571 - NetX depends on com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager.java
+dnl IT573 - Plugin depends on sun.awt,X11.XEmbeddedFrame.java
+dnl IT574 - Plugin depends on sun.misc.Ref
+dnl IT575 - Plugin depends on com.sun/jndi.toolkit.url.UrlUtil
+dnl IT576 - Plugin depends on sun.applet.AppletImageRef
+dnl IT578 - Remove need for patching AppletPanel for Plugin/Webstart
+IT_CHECK_FOR_CLASS(JAVA_UTIL_JAR_PACK200, [java.util.jar.Pack200])
+IT_CHECK_FOR_CLASS(JAVA_NET_COOKIEMANAGER, [java.net.CookieManager])
+IT_CHECK_FOR_CLASS(JAVA_NET_HTTPCOOKIE, [java.net.HttpCookie])
+IT_CHECK_FOR_CLASS(JAVA_NET_COOKIEHANDLER, [java.net.CookieHandler])
+IT_CHECK_FOR_CLASS(SUN_SECURITY_PROVIDER_X509FACTORY, [sun.security.provider.X509Factory])
+IT_CHECK_FOR_CLASS(SUN_SECURITY_UTIL_SECURITYCONSTANTS, [sun.security.util.SecurityConstants])
+IT_CHECK_FOR_CLASS(SUN_SECURITY_UTIL_HOSTNAMECHECKER, [sun.security.util.HostnameChecker])
+IT_CHECK_FOR_CLASS(SUN_SECURITY_X509_X500NAME, [sun.security.x509.X500Name])
+IT_CHECK_FOR_CLASS(SUN_MISC_BASE64ENCODER, [sun.misc.BASE64Encoder])
+IT_CHECK_FOR_CLASS(SUN_MISC_HEXDUMPENCODER, [sun.misc.HexDumpEncoder])
+IT_CHECK_FOR_CLASS(SUN_SECURITY_VALIDATOR_VALIDATOREXCEPTION, [sun.security.validator.ValidatorException])
+IT_CHECK_FOR_CLASS(COM_SUN_NET_SSL_INTERNAL_SSL_X509EXTENDEDTRUSTMANAGER,
+	[com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager])
+IT_CHECK_FOR_CLASS(SUN_AWT_X11_XEMBEDDEDFRAME, [sun.awt.X11.XEmbeddedFrame])
+IT_CHECK_FOR_CLASS(SUN_MISC_REF, [sun.misc.Ref])
+IT_CHECK_FOR_CLASS(COM_SUN_JNDI_TOOLKIT_URL_URLUTIL, [com.sun.jndi.toolkit.url.UrlUtil])
+IT_CHECK_FOR_CLASS(SUN_APPLET_APPLETIMAGEREF, [sun.applet.AppletImageRef])
+IT_CHECK_FOR_APPLETVIEWERPANEL_HOLE
+
+#
+# Find optional depedencies
+#
+
+IT_FIND_OPTIONAL_JAR([rhino], RHINO,
+    [/usr/share/java/js.jar /usr/share/rhino-1.6/lib/js.jar])
+IT_FIND_OPTIONAL_JAR([junit], JUNIT,
+    [/usr/share/java/junit4.jar /usr/share/junit-4/lib/junit.jar])
+
+AC_CONFIG_FILES([jrunscript], [chmod u+x jrunscript])
+AC_CONFIG_FILES([build.properties])
+
+AC_OUTPUT
Index: /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/HTMLPanel.java
===================================================================
--- /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/HTMLPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/HTMLPanel.java	(revision 403)
@@ -0,0 +1,59 @@
+/* HTMLPanel.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.javaws.about;
+
+import java.awt.BorderLayout;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JEditorPane;
+
+public class HTMLPanel extends JPanel {
+
+	JEditorPane pane;
+	
+	public HTMLPanel(URL url) throws IOException {
+		super(new BorderLayout());
+		pane = new JEditorPane(url);
+		pane.setEditable(false);
+		JScrollPane scroller = new JScrollPane(pane);
+		add(scroller, BorderLayout.CENTER);
+	}
+}
Index: /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/Main.java
===================================================================
--- /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/Main.java	(revision 403)
+++ /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/Main.java	(revision 403)
@@ -0,0 +1,117 @@
+/* Main.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.javaws.about;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.io.IOException;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.UIManager;
+
+
+public class Main extends JPanel  {
+
+	private final String notes = "/net/sourceforge/javaws/about/resources/notes.html";
+	private final String apps = "/net/sourceforge/javaws/about/resources/applications.html";
+	private final String about = "/net/sourceforge/javaws/about/resources/about.html";
+	JTabbedPane tabbedPane;
+
+	public Main() throws IOException {
+		super(new BorderLayout());
+		
+		HTMLPanel notesPanel = new HTMLPanel(getClass().getResource(notes));
+		HTMLPanel appsPanel = new HTMLPanel(getClass().getResource(apps));
+		HTMLPanel aboutPanel = new HTMLPanel(getClass().getResource(about));
+		
+	
+		
+		tabbedPane = new JTabbedPane();
+
+		tabbedPane.add("About NetX", aboutPanel);
+		tabbedPane.add("Applications", appsPanel);
+		tabbedPane.add("Notes", notesPanel);
+		
+		tabbedPane.setPreferredSize(new Dimension(550,410));
+		add(tabbedPane, BorderLayout.CENTER);
+	}
+
+	private static void createAndShowGUI() {
+		
+		try {
+			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch (Exception e) {	
+		}
+		
+		JFrame frame = new JFrame("About NetX");
+		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+		Main demo = null;
+		try {
+			demo = new Main();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+		demo.setOpaque(true);
+		frame.setContentPane(demo);
+		frame.pack();
+		centerDialog(frame);
+		frame.setVisible(true);
+	}
+	
+    private static void centerDialog(JFrame frame) {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = frame.getSize();
+
+        frame.setLocation((screen.width - dialogSize.width)/2,
+            (screen.height - dialogSize.height)/2);
+    }
+
+	public static void main(String[] args) {
+		javax.swing.SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				createAndShowGUI();
+			}
+		});
+	}
+
+
+}
Index: /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/about.html
===================================================================
--- /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/about.html	(revision 403)
+++ /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/about.html	(revision 403)
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+    <head>
+        <title>
+        </title>
+    </head>
+    <body>
+        <b>NetX</b> is a high-quality JNLP client that executes
+        network-based applications.  
+        <br>NetX downloads code over the
+        network, caches it, and runs it in a secure sandbox
+        environment (unless signed).
+        <br><br><big><b>
+                Features of NetX:
+        </b></big>
+        <ul>
+            <li><b>Modular: </b>Easily add JNLP capabilities to an application.</li>
+            <li><b>Small Size: </b>Loads from a ~130K JAR file.</li>
+            <li><b>Saves Memory: </b>Launch programs in a shared JVM.</li>
+            <li><b>Fast startup:</b> Runs applications from a cache for fast starting. </li>
+            <li><b>Security:</b> Run any application in a sandbox or log its activities.</li>
+            <li><b>Auto-Update:</b> Applications can auto-update without special code.</li>
+            <li><b>Network Deployment:</b> Deploy to the internet, not with installers. </li>
+            <li><b>Open Source:</b> GNU Lesser General Public License.</li>
+        </ul>
+    </body>
+</html>
+
Index: /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/applications.html
===================================================================
--- /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/applications.html	(revision 403)
+++ /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/applications.html	(revision 403)
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Applications</title>
+</head>
+<body>
+
+<big><b>Sample Applications:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp">jDiskReport</a> -</b> http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp">jPathReport</a> -</b> http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.L2FProd.com/software/skinlf/jnlp/demo.php">Skin L2F Demo</a> -</b> http://www.L2FProd.com/software/skinlf/jnlp/demo.php<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.glub.com/products/secureftp/secureftp.jnlp">Secure FTP</a> -</b> http://www.glub.com/products/secureftp/secureftp.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jext.org/apps/jext.jnlp">Jext</a> -</b> http://www.jext.org/apps/jext.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.javazoom.net/jlgui/jws/jlgui.jnlp">Java Music Player</a> -</b> http://www.javazoom.net/jlgui/jws/jlgui.jnlp<br>
+<br>
+<big><b>Apps using netx:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://jnlp.sourceforge.net/netx/start/start.jnlp">Java Start Button</a> -</b> http://jnlp.sourceforge.net/netx/start/start.jnlp<br>
+<br>
+<big><b>Sun Demos:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/swingset2.jnlp">SwingSet2</a> -</b> http://java.sun.com/products/javawebstart/apps/swingset2.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/notepad.jnlp">Notepad</a> -</b> http://java.sun.com/products/javawebstart/apps/notepad.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/draw.jnlp">Draw</a> -</b> http://java.sun.com/products/javawebstart/apps/draw.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/mg.jnlp">Military Game</a> -</b> http://java.sun.com/products/javawebstart/apps/mg.jnlp<br>
+<br>
+<big><b>Tests:</b></big><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTest.jnlp">Security Test</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTestSigned.jnlp">Security Test (signed)</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/StrictTest.jnlp">Security Test (signed; fail strict JNLP)</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionList.jnlp">Permission Test</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionListSigned.jnlp">Permission Test (signed)</a>
+<table cellpadding="0" cellspacing="0" border="0">
+		<tbody><tr><td valign="Top" nowrap="true" bgcolor="#ffffff" width="500"><br>
+		</td></tr></tbody>
+</table>
+</body>
+</html>
Index: /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/notes.html
===================================================================
--- /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/notes.html	(revision 403)
+++ /tags/icedtea-web/beta/extra/net/sourceforge/javaws/about/resources/notes.html	(revision 403)
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+	<head>
+		<title>Release Notes</title>
+	</head>
+	<body>
+	<br>
+	<table cellpadding="2" cellspacing="2" border="0" width="100%">
+		<tbody>
+		<tr>
+			<td valign="Top" width="15"></td>
+			<td valign="Top" width="100%">
+				<table cellpadding="0" cellspacing="0" border="0" align="Center">
+					<tbody>
+						<tr>
+							<td valign="Middle" align="Center" nowrap="true"><div align="Center">
+								<img src="jamIcon.jpg" alt="Jam Icon" width="87" height="84" align="Center">
+								</div>
+							</td>
+						</tr>
+						<tr>
+							<td valign="Middle" nowrap="true" align="Justify">
+								<div align="Center">
+								<b>Lillian Angel</b> <br>
+								<b>Deepak Bhole</b> <br>
+								<b>Thomas Fitzsimmons</b> <br>
+								<b>Andrew John Hughes</b> <br>
+								<b>Matthias Klose </b> <br>
+								<b>Francis Kung</b> <br>
+								<b>Omair Majid</b> <br>
+								<b>Jon A. Maxwell</b> <br>
+								<b>Andrew Su</b> <br>
+								<b>Joshua Sumali</b> <br>
+								<b>Mark Wielaard</b> <br>
+								<b>Man Lung Wong</b> <br>
+								</div>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</td>
+		</tr>
+		</tbody>
+	</table>
+<br>
+<big><b>Release Notes</b></big>
+<br>
+<table cellpadding="0" cellspacing="0" border="0">
+	<tbody>
+		<tr>
+			<td valign="Top" width="15"><br></td>
+			
+
+			<td valign="Top"> 
+			NetX on IcedTea: Security Support
+			<ul>
+				<li> Full signed application support </li>
+				<li> User trusted certificates support </li>
+				<li> Some JNLP API Services implemented </li>
+				<li> Improved unsigned application sandboxing with JNLP API </li>
+			</ul>
+			</td>
+		</tr>
+		<tr>
+			<td valign="Top" width="15"><br></td>
+			<td valign="Top"> 
+			Version 0.5: Refines multi-app capabilities + native code support
+			<ul>
+				<li> Released under LGPL. </li> 
+				<li> Separate event queue, look and feel, etc for each application. </li> 
+				<li> Native code support. </li> 
+				<li> Supports headless mode. </li> 
+				<li> Internationalized messages. </li> 
+				<li> Uses NanoXML parser. </li> 
+				<li> Minor changes listed on project web site... </li> 
+			</ul>
+
+			</td>
+		</tr>
+	</tbody>
+</table>
+<b>Please visit the SourceForge site
+	<a href="http://jnlp.sourceforge.net/netx/index.html">
+		http://jnlp.sourceforge.net/netx/index.html
+	</a>
+	and the IcedTea site
+	<a href="http://iced-tea.org">http://iced-tea.org</a>
+	 for more information.</b><br>
+</body>
+</html>
Index: /tags/icedtea-web/beta/install-sh
===================================================================
--- /tags/icedtea-web/beta/install-sh	(revision 403)
+++ /tags/icedtea-web/beta/install-sh	(revision 403)
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	-*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
Index: /tags/icedtea-web/beta/itweb-settings.desktop.in
===================================================================
--- /tags/icedtea-web/beta/itweb-settings.desktop.in	(revision 403)
+++ /tags/icedtea-web/beta/itweb-settings.desktop.in	(revision 403)
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=IcedTea Web Control Panel
+Comment=Configure IcedTea Web (javaws and plugin)
+Exec=PATH_TO_ITWEB_SETTINGS
+Icon=javaws
+Terminal=false
+Type=Application
+Categories=Settings;
Index: /tags/icedtea-web/beta/javac.in
===================================================================
--- /tags/icedtea-web/beta/javac.in	(revision 403)
+++ /tags/icedtea-web/beta/javac.in	(revision 403)
@@ -0,0 +1,62 @@
+#!/usr/bin/perl -w
+use strict;
+use constant NO_DUP_ARGS => qw(-source -target -d -encoding);
+use constant STRIP_ARGS => qw(-Werror -implicit:none);
+
+my $ECJ_WARNINGS="-warn:-unused,-serial";
+my $JAVAC_WARNINGS="-Xlint:all,-serial";
+
+my @bcoption;
+push @bcoption, '-bootclasspath', glob '@abs_top_builddir@/bootstrap/jdk1.6.0/jre/lib/rt.jar'
+    unless grep {$_ eq '-bootclasspath'} @ARGV;
+my @ecj_parms = ($ECJ_WARNINGS, @bcoption);
+
+# Work around ecj's inability to handle duplicate command-line
+# options and unknown javac options.
+sub gen_ecj_opts
+{
+    my @new_args = @{$_[0]};
+
+    for my $opt (NO_DUP_ARGS) 
+    {
+	my @indices = reverse grep {$new_args[$_] eq $opt} 0..$#new_args;
+	if (@indices > 1) {
+	    shift @indices;    # keep last instance only
+	    splice @new_args, $_, 2 for @indices;
+	}
+    }
+
+    for my $opt (STRIP_ARGS) 
+    {
+	my @indices = reverse grep {$new_args[$_] eq $opt} 0..$#new_args;
+	splice @new_args, $_, 1 for @indices;
+    }
+
+    return @new_args;
+}
+
+if ( -e "@abs_top_builddir@/native-ecj" )
+{
+    my @ecj_args = gen_ecj_opts( \@ARGV );
+    exec '@abs_top_builddir@/native-ecj', @ecj_parms, @ecj_args ;
+}
+elsif ( -e "@JAVAC@" )
+{
+    if ("@USING_ECJ@" eq "yes")
+    {
+	my @ecj_args = gen_ecj_opts( \@ARGV );
+	exec '@JAVAC@', @ecj_parms, @ecj_args ;
+    }
+    else
+    {
+	exec '@JAVAC@', $JAVAC_WARNINGS, @ARGV ;
+    }
+}
+else
+{
+    my @ecj_args = gen_ecj_opts( \@ARGV );
+    my @CLASSPATH = ('@ECJ_JAR@');
+    push @CLASSPATH, split /:/, $ENV{"CLASSPATH"} if exists $ENV{"CLASSPATH"};
+    $ENV{"CLASSPATH"} = join ':', @CLASSPATH;
+    exec '@JAVA@', 'org.eclipse.jdt.internal.compiler.batch.Main', @ecj_parms, @ecj_args;
+}
Index: /tags/icedtea-web/beta/javaws.desktop.in
===================================================================
--- /tags/icedtea-web/beta/javaws.desktop.in	(revision 403)
+++ /tags/icedtea-web/beta/javaws.desktop.in	(revision 403)
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=IcedTea Web Start
+Comment=IcedTea Application Launcher
+Exec=PATH_TO_JAVAWS %f
+Icon=javaws
+Terminal=false
+Type=Application
+NoDisplay=true
+Categories=Network;WebBrowser;
+MimeType=application/x-java-jnlp-file;
Index: /tags/icedtea-web/beta/jrunscript.in
===================================================================
--- /tags/icedtea-web/beta/jrunscript.in	(revision 403)
+++ /tags/icedtea-web/beta/jrunscript.in	(revision 403)
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [ x"@RHINO_JAR@" == x ] ; then
+  echo "jrunscript requires rhino support"
+  exit 1
+fi
+
+@JAVA@ -cp "@RHINO_JAR@" org.mozilla.javascript.tools.shell.Main $@
Index: /tags/icedtea-web/beta/launcher/itweb-settings.in
===================================================================
--- /tags/icedtea-web/beta/launcher/itweb-settings.in	(revision 403)
+++ /tags/icedtea-web/beta/launcher/itweb-settings.in	(revision 403)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+JAVA=@JAVA@
+LAUNCHER_BOOTCLASSPATH=@LAUNCHER_BOOTCLASSPATH@
+LAUNCHER_FLAGS=-Xms8m
+CLASSNAME=net.sourceforge.jnlp.controlpanel.CommandLine
+BINARY_LOCATION=@ITWEB_SETTINGS_BIN_LOCATION@
+PROGRAM_NAME=itweb-settings
+
+${JAVA} ${LAUNCHER_BOOTCLASSPATH} ${LAUNCHER_FLAGS} \
+  -Dicedtea-web.bin.name=${PROGRAM_NAME} \
+  -Dicedtea-web.bin.location=${BINARY_LOCATION} \
+  ${CLASSNAME} \
+  $@
+
Index: /tags/icedtea-web/beta/launcher/java.c
===================================================================
--- /tags/icedtea-web/beta/launcher/java.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/java.c	(revision 403)
@@ -0,0 +1,2019 @@
+/*
+ * Copyright (c) 1995, 2008, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/*
+ * Shared source for 'java' command line tool.
+ *
+ * If JAVA_ARGS is defined, then acts as a launcher for applications. For
+ * instance, the JDK command line tools such as javac and javadoc (see
+ * makefiles for more details) are built with this program.  Any arguments
+ * prefixed with '-J' will be passed directly to the 'java' command.
+ */
+
+/*
+ * One job of the launcher is to remove command line options which the
+ * vm does not understand and will not process.  These options include
+ * options which select which style of vm is run (e.g. -client and
+ * -server) as well as options which select the data model to use.
+ * Additionally, for tools which invoke an underlying vm "-J-foo"
+ * options are turned into "-foo" options to the vm.  This option
+ * filtering is handled in a number of places in the launcher, some of
+ * it in machine-dependent code.  In this file, the function
+ * CheckJVMType removes vm style options and TranslateApplicationArgs
+ * removes "-J" prefixes.  On unix platforms, the
+ * CreateExecutionEnvironment function from the unix java_md.c file
+ * processes and removes -d<n> options.  However, in case
+ * CreateExecutionEnvironment does not need to exec because
+ * LD_LIBRARY_PATH is set acceptably and the data model does not need
+ * to be changed, ParseArguments will screen out the redundant -d<n>
+ * options and prevent them from being passed to the vm; this is done
+ * by using the machine-dependent call
+ * RemovableMachineDependentOption.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jvm.h>
+#include "java.h"
+#include "manifest_info.h"
+#include "version_comp.h"
+#include "wildcard.h"
+#include "splashscreen.h"
+
+#ifndef FULL_VERSION
+#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
+#endif
+
+/*
+ * The following environment variable is used to influence the behavior
+ * of the jre exec'd through the SelectVersion routine.  The command line
+ * options which specify the version are not passed to the exec'd version,
+ * because that jre may be an older version which wouldn't recognize them.
+ * This environment variable is known to this (and later) version and serves
+ * to suppress the version selection code.  This is not only for efficiency,
+ * but also for correctness, since any command line options have been
+ * removed which would cause any value found in the manifest to be used.
+ * This would be incorrect because the command line options are defined
+ * to take precedence.
+ *
+ * The value associated with this environment variable is the MainClass
+ * name from within the executable jar file (if any). This is strictly a
+ * performance enhancement to avoid re-reading the jar file manifest.
+ *
+ * A NOTE TO DEVELOPERS: For performance reasons it is important that
+ * the program image remain relatively small until after SelectVersion
+ * CreateExecutionEnvironment have finished their possibly recursive
+ * processing. Watch everything, but resist all temptations to use Java
+ * interfaces.
+ */
+#define ENV_ENTRY "_JAVA_VERSION_SET"
+
+#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
+#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
+
+static jboolean printVersion = JNI_FALSE; /* print and exit */
+static jboolean showVersion = JNI_FALSE;  /* print but continue */
+static jboolean printUsage = JNI_FALSE;   /* print and exit*/
+static jboolean printXUsage = JNI_FALSE;  /* print and exit*/
+static char *progname;
+static char *launchername;
+jboolean _launcher_debug = JNI_FALSE;
+
+/*
+ * Entries for splash screen environment variables.
+ * putenv is performed in SelectVersion. We need
+ * them in memory until UnsetEnv, so they are made static
+ * global instead of auto local.
+ */
+static char* splash_file_entry = NULL;
+static char* splash_jar_entry = NULL;
+
+/*
+ * List of VM options to be specified when the VM is created.
+ */
+static JavaVMOption *options;
+static int numOptions, maxOptions;
+
+/*
+ * Prototypes for functions internal to launcher.
+ */
+static void SetClassPath(const char *s);
+static void SelectVersion(int argc, char **argv, char **main_class);
+static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
+                               char **pclassname, int *pret, const char *jvmpath);
+static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
+                              InvocationFunctions *ifn);
+static jstring NewPlatformString(JNIEnv *env, char *s);
+static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
+static jclass LoadClass(JNIEnv *env, char *name);
+static jstring GetMainClassName(JNIEnv *env, char *jarname);
+static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
+static void SetJavaLauncherProp(void);
+
+#ifdef JAVA_ARGS
+static void TranslateApplicationArgs(int *pargc, char ***pargv);
+static jboolean AddApplicationOptions(void);
+#endif
+
+static void PrintJavaVersion(JNIEnv *env);
+static void PrintUsage(JNIEnv* env, jboolean doXUsage);
+
+static void SetPaths(int argc, char **argv);
+
+
+/* Maximum supported entries from jvm.cfg. */
+#define INIT_MAX_KNOWN_VMS      10
+/* Values for vmdesc.flag */
+#define VM_UNKNOWN              -1
+#define VM_KNOWN                 0
+#define VM_ALIASED_TO            1
+#define VM_WARN                  2
+#define VM_ERROR                 3
+#define VM_IF_SERVER_CLASS       4
+#define VM_IGNORE                5
+struct vmdesc {
+    char *name;
+    int flag;
+    char *alias;
+    char *server_class;
+};
+static struct vmdesc *knownVMs = NULL;
+static int knownVMsCount = 0;
+static int knownVMsLimit = 0;
+
+static void GrowKnownVMs();
+static int  KnownVMIndex(const char* name);
+static void FreeKnownVMs();
+static void ShowSplashScreen();
+
+jboolean ServerClassMachine();
+
+/* flag which if set suppresses error messages from the launcher */
+static int noExitErrorMessage = 0;
+
+/*
+ * Running Java code in primordial thread caused many problems. We will
+ * create a new thread to invoke JVM. See 6316197 for more information.
+ */
+static jlong threadStackSize = 0;  /* stack size of the new thread */
+
+int JNICALL JavaMain(void * args); /* entry point                  */
+
+struct JavaMainArgs {
+  int     argc;
+  char ** argv;
+  char *  jarfile;
+  char *  classname;
+  InvocationFunctions ifn;
+};
+
+/*
+ * Entry point.
+ */
+int
+main(int argc, char ** argv)
+{
+    char *jarfile = 0;
+    char *classname = 0;
+    char *s = 0;
+    char *main_class = NULL;
+    int ret;
+    InvocationFunctions ifn;
+    jlong start, end;
+    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
+    char ** original_argv = argv;
+
+    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
+      int i;
+      _launcher_debug = JNI_TRUE;
+      printf("----_JAVA_LAUNCHER_DEBUG----\n");
+      printf("Command line Args:\n");
+      for(i = 0; i < argc+1; i++) {
+        if (argv[i] != NULL){
+          printf("\targv[%d] = '%s'\n",i,argv[i]);
+        }
+      }
+    }
+
+
+
+    /*
+     * Make sure the specified version of the JRE is running.
+     *
+     * There are three things to note about the SelectVersion() routine:
+     *  1) If the version running isn't correct, this routine doesn't
+     *     return (either the correct version has been exec'd or an error
+     *     was issued).
+     *  2) Argc and Argv in this scope are *not* altered by this routine.
+     *     It is the responsibility of subsequent code to ignore the
+     *     arguments handled by this routine.
+     *  3) As a side-effect, the variable "main_class" is guaranteed to
+     *     be set (if it should ever be set).  This isn't exactly the
+     *     poster child for structured programming, but it is a small
+     *     price to pay for not processing a jar file operand twice.
+     *     (Note: This side effect has been disabled.  See comment on
+     *     bugid 5030265 below.)
+     */
+    SelectVersion(argc, argv, &main_class);
+
+    /* copy original argv */
+    {
+      int i;
+      original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
+      for(i = 0; i < argc+1; i++) {
+        original_argv[i] = argv[i];
+      }
+    }
+
+    CreateExecutionEnvironment(&argc, &argv,
+                               jrepath, sizeof(jrepath),
+                               jvmpath, sizeof(jvmpath),
+                               original_argv);
+
+    ifn.CreateJavaVM = 0;
+    ifn.GetDefaultJavaVMInitArgs = 0;
+
+    if (_launcher_debug)
+      start = CounterGet();
+    if (!LoadJavaVM(jvmpath, &ifn)) {
+      exit(6);
+    }
+    if (_launcher_debug) {
+      end   = CounterGet();
+      printf("%ld micro seconds to LoadJavaVM\n",
+             (long)(jint)Counter2Micros(end-start));
+    }
+
+#ifdef JAVA_ARGS  /* javac, jar and friends. */
+    progname = "java";
+#else             /* java, oldjava, javaw and friends */
+#ifdef PROGNAME
+    progname = PROGNAME;
+#else
+    progname = *argv;
+    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
+        progname = s + 1;
+    }
+#endif /* PROGNAME */
+#endif /* JAVA_ARGS */
+
+#ifdef LAUNCHER_NAME
+    launchername = LAUNCHER_NAME;
+#else
+    launchername = progname;
+#endif /* LAUNCHER_NAME */
+
+    ++argv;
+    --argc;
+
+#ifdef JAVA_ARGS
+    /* Preprocess wrapper arguments */
+    TranslateApplicationArgs(&argc, &argv);
+    if (!AddApplicationOptions()) {
+        exit(1);
+    }
+#endif
+
+    /* Set default CLASSPATH */
+    if ((s = getenv("CLASSPATH")) == 0) {
+        s = ".";
+    }
+#ifndef JAVA_ARGS
+    SetClassPath(s);
+#endif
+
+    /*
+     *  Parse command line options; if the return value of
+     *  ParseArguments is false, the program should exit.
+     */
+    if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) {
+      exit(ret);
+    }
+
+    /* Override class path if -jar flag was specified */
+    if (jarfile != 0) {
+        SetClassPath(jarfile);
+    }
+
+    /* set the -Dsun.java.command pseudo property */
+    SetJavaCommandLineProp(classname, jarfile, argc, argv);
+
+    /* Set the -Dsun.java.launcher pseudo property */
+    SetJavaLauncherProp();
+
+    /* set the -Dsun.java.launcher.* platform properties */
+    SetJavaLauncherPlatformProps();
+
+    /* Show the splash screen if needed */
+    ShowSplashScreen();
+
+    /*
+     * Done with all command line processing and potential re-execs so
+     * clean up the environment.
+     */
+    (void)UnsetEnv(ENV_ENTRY);
+    (void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
+    (void)UnsetEnv(SPLASH_JAR_ENV_ENTRY);
+
+    JLI_MemFree(splash_jar_entry);
+    JLI_MemFree(splash_file_entry);
+
+    /*
+     * If user doesn't specify stack size, check if VM has a preference.
+     * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
+     * return its default stack size through the init args structure.
+     */
+    if (threadStackSize == 0) {
+      struct JDK1_1InitArgs args1_1;
+      memset((void*)&args1_1, 0, sizeof(args1_1));
+      args1_1.version = JNI_VERSION_1_1;
+      ifn.GetDefaultJavaVMInitArgs(&args1_1);  /* ignore return value */
+      if (args1_1.javaStackSize > 0) {
+         threadStackSize = args1_1.javaStackSize;
+      }
+    }
+
+    { /* Create a new thread to create JVM and invoke main method */
+      struct JavaMainArgs args;
+
+      args.argc = argc;
+      args.argv = argv;
+      args.jarfile = jarfile;
+      args.classname = classname;
+      args.ifn = ifn;
+
+      return ContinueInNewThread(JavaMain, threadStackSize, (void*)&args, ret);
+    }
+}
+
+int JNICALL
+JavaMain(void * _args)
+{
+    struct JavaMainArgs *args = (struct JavaMainArgs *)_args;
+    int argc = args->argc;
+    char **argv = args->argv;
+    char *jarfile = args->jarfile;
+    char *classname = args->classname;
+    InvocationFunctions ifn = args->ifn;
+
+    JavaVM *vm = 0;
+    JNIEnv *env = 0;
+    jstring mainClassName;
+    jclass mainClass;
+    jmethodID mainID;
+    jobjectArray mainArgs;
+    int ret = 0;
+    jlong start, end;
+
+    /*
+     * Error message to print or display; by default the message will
+     * only be displayed in a window.
+     */
+    char * message = "Fatal exception occurred.  Program will exit.";
+    jboolean messageDest = JNI_FALSE;
+
+    /* Initialize the virtual machine */
+
+    if (_launcher_debug)
+        start = CounterGet();
+    if (!InitializeJVM(&vm, &env, &ifn)) {
+        ReportErrorMessage("Could not create the Java virtual machine.",
+                           JNI_TRUE);
+        exit(1);
+    }
+
+    if (printVersion || showVersion) {
+        PrintJavaVersion(env);
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        if (printVersion) {
+            ret = 0;
+            message = NULL;
+            goto leave;
+        }
+        if (showVersion) {
+            fprintf(stderr, "\n");
+        }
+    }
+
+    /* If the user specified neither a class name nor a JAR file */
+    if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
+        PrintUsage(env, printXUsage);
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            ret=1;
+        }
+        message = NULL;
+        goto leave;
+    }
+
+
+
+    FreeKnownVMs();  /* after last possible PrintUsage() */
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to InitializeJVM\n",
+               (long)(jint)Counter2Micros(end-start));
+    }
+
+    /* At this stage, argc/argv have the applications' arguments */
+    if (_launcher_debug) {
+        int i = 0;
+        printf("Main-Class is '%s'\n", classname ? classname : "");
+        printf("Apps' argc is %d\n", argc);
+        for (; i < argc; i++) {
+            printf("    argv[%2d] = '%s'\n", i, argv[i]);
+        }
+    }
+
+    ret = 1;
+
+    /*
+     * Get the application's main class.
+     *
+     * See bugid 5030265.  The Main-Class name has already been parsed
+     * from the manifest, but not parsed properly for UTF-8 support.
+     * Hence the code here ignores the value previously extracted and
+     * uses the pre-existing code to reextract the value.  This is
+     * possibly an end of release cycle expedient.  However, it has
+     * also been discovered that passing some character sets through
+     * the environment has "strange" behavior on some variants of
+     * Windows.  Hence, maybe the manifest parsing code local to the
+     * launcher should never be enhanced.
+     *
+     * Hence, future work should either:
+     *     1)   Correct the local parsing code and verify that the
+     *          Main-Class attribute gets properly passed through
+     *          all environments,
+     *     2)   Remove the vestages of maintaining main_class through
+     *          the environment (and remove these comments).
+     */
+    if (jarfile != 0) {
+        mainClassName = GetMainClassName(env, jarfile);
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        if (mainClassName == NULL) {
+          const char * format = "Failed to load Main-Class manifest "
+                                "attribute from\n%s";
+          message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) *
+                                    sizeof(char));
+          sprintf(message, format, jarfile);
+          messageDest = JNI_TRUE;
+          goto leave;
+        }
+        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
+        if (classname == NULL) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        mainClass = LoadClass(env, classname);
+        if(mainClass == NULL) { /* exception occured */
+            const char * format = "Could not find the main class: %s. Program will exit.";
+            ReportExceptionDescription(env);
+            message = (char *)JLI_MemAlloc((strlen(format) +
+					   strlen(classname)) * sizeof(char));
+            messageDest = JNI_TRUE;
+	    sprintf(message, format, classname);
+            goto leave;
+        }
+        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
+    } else {
+      mainClassName = NewPlatformString(env, classname);
+      if (mainClassName == NULL) {
+        const char * format = "Failed to load Main Class: %s";
+        message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) *
+                                   sizeof(char) );
+        sprintf(message, format, classname);
+        messageDest = JNI_TRUE;
+        goto leave;
+      }
+      classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
+      if (classname == NULL) {
+        ReportExceptionDescription(env);
+        goto leave;
+      }
+      mainClass = LoadClass(env, classname);
+      if(mainClass == NULL) { /* exception occured */
+        const char * format = "Could not find the main class: %s. Program will exit.";
+        ReportExceptionDescription(env);
+        message = (char *)JLI_MemAlloc((strlen(format) +
+                                          strlen(classname)) * sizeof(char));
+        messageDest = JNI_TRUE;
+        sprintf(message, format, classname);
+        goto leave;
+      }
+      (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
+    }
+
+    /* Get the application's main method */
+    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
+                                       "([Ljava/lang/String;)V");
+    if (mainID == NULL) {
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+        } else {
+          message = "No main method found in specified class.";
+          messageDest = JNI_TRUE;
+        }
+        goto leave;
+    }
+
+    {    /* Make sure the main method is public */
+        jint mods;
+        jmethodID mid;
+        jobject obj = (*env)->ToReflectedMethod(env, mainClass,
+                                                mainID, JNI_TRUE);
+
+        if( obj == NULL) { /* exception occurred */
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+
+        mid =
+          (*env)->GetMethodID(env,
+                              (*env)->GetObjectClass(env, obj),
+                              "getModifiers", "()I");
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+
+        mods = (*env)->CallIntMethod(env, obj, mid);
+        if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
+            message = "Main method not public.";
+            messageDest = JNI_TRUE;
+            goto leave;
+        }
+    }
+
+    /* Build argument array */
+    mainArgs = NewPlatformStringArray(env, argv, argc);
+    if (mainArgs == NULL) {
+        ReportExceptionDescription(env);
+        goto leave;
+    }
+
+    /* Invoke main method. */
+    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
+
+    /*
+     * The launcher's exit code (in the absence of calls to
+     * System.exit) will be non-zero if main threw an exception.
+     */
+    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+
+    /*
+     * Detach the main thread so that it appears to have ended when
+     * the application's main method exits.  This will invoke the
+     * uncaught exception handler machinery if main threw an
+     * exception.  An uncaught exception handler cannot change the
+     * launcher's return code except by calling System.exit.
+     */
+    if ((*vm)->DetachCurrentThread(vm) != 0) {
+        message = "Could not detach main thread.";
+        messageDest = JNI_TRUE;
+        ret = 1;
+        goto leave;
+    }
+
+    message = NULL;
+
+ leave:
+    /*
+     * Wait for all non-daemon threads to end, then destroy the VM.
+     * This will actually create a trivial new Java waiter thread
+     * named "DestroyJavaVM", but this will be seen as a different
+     * thread from the one that executed main, even though they are
+     * the same C thread.  This allows mainThread.join() and
+     * mainThread.isAlive() to work as expected.
+     */
+    (*vm)->DestroyJavaVM(vm);
+
+    if(message != NULL && !noExitErrorMessage)
+      ReportErrorMessage(message, messageDest);
+    return ret;
+}
+
+
+/*
+ * Checks the command line options to find which JVM type was
+ * specified.  If no command line option was given for the JVM type,
+ * the default type is used.  The environment variable
+ * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
+ * checked as ways of specifying which JVM type to invoke.
+ */
+char *
+CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
+    int i, argi;
+    int argc;
+    char **newArgv;
+    int newArgvIdx = 0;
+    int isVMType;
+    int jvmidx = -1;
+    char *jvmtype = getenv("JDK_ALTERNATE_VM");
+
+    argc = *pargc;
+
+    /* To make things simpler we always copy the argv array */
+    newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));
+
+    /* The program name is always present */
+    newArgv[newArgvIdx++] = (*argv)[0];
+
+    for (argi = 1; argi < argc; argi++) {
+        char *arg = (*argv)[argi];
+        isVMType = 0;
+
+#ifdef JAVA_ARGS
+        if (arg[0] != '-') {
+            newArgv[newArgvIdx++] = arg;
+            continue;
+        }
+#else
+        if (strcmp(arg, "-classpath") == 0 ||
+            strcmp(arg, "-cp") == 0) {
+            newArgv[newArgvIdx++] = arg;
+            argi++;
+            if (argi < argc) {
+                newArgv[newArgvIdx++] = (*argv)[argi];
+            }
+            continue;
+        }
+        if (arg[0] != '-') break;
+#endif
+
+        /* Did the user pass an explicit VM type? */
+        i = KnownVMIndex(arg);
+        if (i >= 0) {
+            jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
+            isVMType = 1;
+            *pargc = *pargc - 1;
+        }
+
+        /* Did the user specify an "alternate" VM? */
+        else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
+            isVMType = 1;
+            jvmtype = arg+((arg[1]=='X')? 10 : 12);
+            jvmidx = -1;
+        }
+
+        if (!isVMType) {
+            newArgv[newArgvIdx++] = arg;
+        }
+    }
+
+    /*
+     * Finish copying the arguments if we aborted the above loop.
+     * NOTE that if we aborted via "break" then we did NOT copy the
+     * last argument above, and in addition argi will be less than
+     * argc.
+     */
+    while (argi < argc) {
+        newArgv[newArgvIdx++] = (*argv)[argi];
+        argi++;
+    }
+
+    /* argv is null-terminated */
+    newArgv[newArgvIdx] = 0;
+
+    /* Copy back argv */
+    *argv = newArgv;
+    *pargc = newArgvIdx;
+
+    /* use the default VM type if not specified (no alias processing) */
+    if (jvmtype == NULL) {
+      char* result = knownVMs[0].name+1;
+      /* Use a different VM type if we are on a server class machine? */
+      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
+          (ServerClassMachine() == JNI_TRUE)) {
+        result = knownVMs[0].server_class+1;
+      }
+      if (_launcher_debug) {
+        printf("Default VM: %s\n", result);
+      }
+      return result;
+    }
+
+    /* if using an alternate VM, no alias processing */
+    if (jvmidx < 0)
+      return jvmtype;
+
+    /* Resolve aliases first */
+    {
+      int loopCount = 0;
+      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
+        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);
+
+        if (loopCount > knownVMsCount) {
+          if (!speculative) {
+            ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
+                               JNI_TRUE);
+            exit(1);
+          } else {
+            return "ERROR";
+            /* break; */
+          }
+        }
+
+        if (nextIdx < 0) {
+          if (!speculative) {
+            ReportErrorMessage2("Error: Unable to resolve VM alias %s",
+                                knownVMs[jvmidx].alias, JNI_TRUE);
+            exit(1);
+          } else {
+            return "ERROR";
+          }
+        }
+        jvmidx = nextIdx;
+        jvmtype = knownVMs[jvmidx].name+1;
+        loopCount++;
+      }
+    }
+
+    switch (knownVMs[jvmidx].flag) {
+    case VM_WARN:
+        if (!speculative) {
+            fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n",
+                    jvmtype, knownVMs[0].name + 1);
+        }
+        /* fall through */
+    case VM_IGNORE:
+        jvmtype = knownVMs[jvmidx=0].name + 1;
+        /* fall through */
+    case VM_KNOWN:
+        break;
+    case VM_ERROR:
+        if (!speculative) {
+            ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
+            exit(1);
+        } else {
+            return "ERROR";
+        }
+    }
+
+    return jvmtype;
+}
+
+# define KB (1024UL)
+# define MB (1024UL * KB)
+# define GB (1024UL * MB)
+
+/* copied from HotSpot function "atomll()" */
+static int
+parse_stack_size(const char *s, jlong *result) {
+  jlong n = 0;
+  int args_read = sscanf(s, jlong_format_specifier(), &n);
+  if (args_read != 1) {
+    return 0;
+  }
+  while (*s != '\0' && *s >= '0' && *s <= '9') {
+    s++;
+  }
+  // 4705540: illegal if more characters are found after the first non-digit
+  if (strlen(s) > 1) {
+    return 0;
+  }
+  switch (*s) {
+    case 'T': case 't':
+      *result = n * GB * KB;
+      return 1;
+    case 'G': case 'g':
+      *result = n * GB;
+      return 1;
+    case 'M': case 'm':
+      *result = n * MB;
+      return 1;
+    case 'K': case 'k':
+      *result = n * KB;
+      return 1;
+    case '\0':
+      *result = n;
+      return 1;
+    default:
+      /* Create JVM with default stack and let VM handle malformed -Xss string*/
+      return 0;
+  }
+}
+
+/*
+ * Adds a new VM option with the given given name and value.
+ */
+void
+AddOption(char *str, void *info)
+{
+    /*
+     * Expand options array if needed to accommodate at least one more
+     * VM option.
+     */
+    if (numOptions >= maxOptions) {
+        if (options == 0) {
+            maxOptions = 4;
+            options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
+        } else {
+            JavaVMOption *tmp;
+            maxOptions *= 2;
+            tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
+            memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
+            JLI_MemFree(options);
+            options = tmp;
+        }
+    }
+    options[numOptions].optionString = str;
+    options[numOptions++].extraInfo = info;
+
+    if (strncmp(str, "-Xss", 4) == 0) {
+      jlong tmp;
+      if (parse_stack_size(str + 4, &tmp)) {
+        threadStackSize = tmp;
+      }
+    }
+}
+
+static void
+SetClassPath(const char *s)
+{
+    char *def;
+    s = JLI_WildcardExpandClasspath(s);
+    def = JLI_MemAlloc(strlen(s) + 40);
+    sprintf(def, "-Djava.class.path=%s", s);
+    AddOption(def, NULL);
+}
+
+/*
+ * The SelectVersion() routine ensures that an appropriate version of
+ * the JRE is running.  The specification for the appropriate version
+ * is obtained from either the manifest of a jar file (preferred) or
+ * from command line options.
+ * The routine also parses splash screen command line options and
+ * passes on their values in private environment variables.
+ */
+static void
+SelectVersion(int argc, char **argv, char **main_class)
+{
+    char    *arg;
+    char    **new_argv;
+    char    **new_argp;
+    char    *operand;
+    char    *version = NULL;
+    char    *jre = NULL;
+    int     jarflag = 0;
+    int     headlessflag = 0;
+    int     restrict_search = -1;               /* -1 implies not known */
+    manifest_info info;
+    char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
+    char    *splash_file_name = NULL;
+    char    *splash_jar_name = NULL;
+    char    *env_in;
+    int     res;
+
+    /*
+     * If the version has already been selected, set *main_class
+     * with the value passed through the environment (if any) and
+     * simply return.
+     */
+    if ((env_in = getenv(ENV_ENTRY)) != NULL) {
+        if (*env_in != '\0')
+            *main_class = JLI_StringDup(env_in);
+        return;
+    }
+
+    /*
+     * Scan through the arguments for options relevant to multiple JRE
+     * support.  For reference, the command line syntax is defined as:
+     *
+     * SYNOPSIS
+     *      java [options] class [argument...]
+     *
+     *      java [options] -jar file.jar [argument...]
+     *
+     * As the scan is performed, make a copy of the argument list with
+     * the version specification options (new to 1.5) removed, so that
+     * a version less than 1.5 can be exec'd.
+     *
+     * Note that due to the syntax of the native Windows interface
+     * CreateProcess(), processing similar to the following exists in
+     * the Windows platform specific routine ExecJRE (in java_md.c).
+     * Changes here should be reproduced there.
+     */
+    new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*));
+    new_argv[0] = argv[0];
+    new_argp = &new_argv[1];
+    argc--;
+    argv++;
+    while ((arg = *argv) != 0 && *arg == '-') {
+        if (strncmp(arg, "-version:", 9) == 0) {
+            version = arg + 9;
+        } else if (strcmp(arg, "-jre-restrict-search") == 0) {
+            restrict_search = 1;
+        } else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
+            restrict_search = 0;
+        } else {
+            if (strcmp(arg, "-jar") == 0)
+                jarflag = 1;
+            /* deal with "unfortunate" classpath syntax */
+            if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) &&
+              (argc >= 2)) {
+                *new_argp++ = arg;
+                argc--;
+                argv++;
+                arg = *argv;
+            }
+
+            /*
+             * Checking for headless toolkit option in the some way as AWT does:
+             * "true" means true and any other value means false
+             */
+            if (strcmp(arg, "-Djava.awt.headless=true") == 0) {
+                headlessflag = 1;
+            } else if (strncmp(arg, "-Djava.awt.headless=", 20) == 0) {
+                headlessflag = 0;
+            } else if (strncmp(arg, "-splash:", 8) == 0) {
+                splash_file_name = arg+8;
+            }
+            *new_argp++ = arg;
+        }
+        argc--;
+        argv++;
+    }
+    if (argc <= 0) {    /* No operand? Possibly legit with -[full]version */
+        operand = NULL;
+    } else {
+        argc--;
+        *new_argp++ = operand = *argv++;
+    }
+    while (argc-- > 0)  /* Copy over [argument...] */
+        *new_argp++ = *argv++;
+    *new_argp = NULL;
+
+    /*
+     * If there is a jar file, read the manifest. If the jarfile can't be
+     * read, the manifest can't be read from the jar file, or the manifest
+     * is corrupt, issue the appropriate error messages and exit.
+     *
+     * Even if there isn't a jar file, construct a manifest_info structure
+     * containing the command line information.  It's a convenient way to carry
+     * this data around.
+     */
+    if (jarflag && operand) {
+        if ((res = JLI_ParseManifest(operand, &info)) != 0) {
+            if (res == -1)
+                ReportErrorMessage2("Unable to access jarfile %s",
+                  operand, JNI_TRUE);
+            else
+                ReportErrorMessage2("Invalid or corrupt jarfile %s",
+                  operand, JNI_TRUE);
+            exit(1);
+        }
+
+        /*
+         * Command line splash screen option should have precedence
+         * over the manifest, so the manifest data is used only if
+         * splash_file_name has not been initialized above during command
+         * line parsing
+         */
+        if (!headlessflag && !splash_file_name && info.splashscreen_image_file_name) {
+            splash_file_name = info.splashscreen_image_file_name;
+            splash_jar_name = operand;
+        }
+    } else {
+        info.manifest_version = NULL;
+        info.main_class = NULL;
+        info.jre_version = NULL;
+        info.jre_restrict_search = 0;
+    }
+
+    /*
+     * Passing on splash screen info in environment variables
+     */
+    if (splash_file_name && !headlessflag) {
+        char* splash_file_entry = JLI_MemAlloc(strlen(SPLASH_FILE_ENV_ENTRY "=")+strlen(splash_file_name)+1);
+        strcpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
+        strcat(splash_file_entry, splash_file_name);
+        putenv(splash_file_entry);
+    }
+    if (splash_jar_name && !headlessflag) {
+        char* splash_jar_entry = JLI_MemAlloc(strlen(SPLASH_JAR_ENV_ENTRY "=")+strlen(splash_jar_name)+1);
+        strcpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
+        strcat(splash_jar_entry, splash_jar_name);
+        putenv(splash_jar_entry);
+    }
+
+    /*
+     * The JRE-Version and JRE-Restrict-Search values (if any) from the
+     * manifest are overwritten by any specified on the command line.
+     */
+    if (version != NULL)
+        info.jre_version = version;
+    if (restrict_search != -1)
+        info.jre_restrict_search = restrict_search;
+
+    /*
+     * "Valid" returns (other than unrecoverable errors) follow.  Set
+     * main_class as a side-effect of this routine.
+     */
+    if (info.main_class != NULL)
+        *main_class = JLI_StringDup(info.main_class);
+
+    /*
+     * If no version selection information is found either on the command
+     * line or in the manifest, simply return.
+     */
+    if (info.jre_version == NULL) {
+        JLI_FreeManifest();
+        JLI_MemFree(new_argv);
+        return;
+    }
+
+    /*
+     * Check for correct syntax of the version specification (JSR 56).
+     */
+    if (!JLI_ValidVersionString(info.jre_version)) {
+        ReportErrorMessage2("Syntax error in version specification \"%s\"",
+          info.jre_version, JNI_TRUE);
+        exit(1);
+    }
+
+    /*
+     * Find the appropriate JVM on the system. Just to be as forgiving as
+     * possible, if the standard algorithms don't locate an appropriate
+     * jre, check to see if the one running will satisfy the requirements.
+     * This can happen on systems which haven't been set-up for multiple
+     * JRE support.
+     */
+    jre = LocateJRE(&info);
+    if (_launcher_debug)
+        printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
+          (info.jre_version?info.jre_version:"null"),
+          (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
+    if (jre == NULL) {
+        if (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) {
+            JLI_FreeManifest();
+            JLI_MemFree(new_argv);
+            return;
+        } else {
+            ReportErrorMessage2(
+              "Unable to locate JRE meeting specification \"%s\"",
+              info.jre_version, JNI_TRUE);
+            exit(1);
+        }
+    }
+
+    /*
+     * If I'm not the chosen one, exec the chosen one.  Returning from
+     * ExecJRE indicates that I am indeed the chosen one.
+     *
+     * The private environment variable _JAVA_VERSION_SET is used to
+     * prevent the chosen one from re-reading the manifest file and
+     * using the values found within to override the (potential) command
+     * line flags stripped from argv (because the target may not
+     * understand them).  Passing the MainClass value is an optimization
+     * to avoid locating, expanding and parsing the manifest extra
+     * times.
+     */
+    if (info.main_class != NULL) {
+        if (strlen(info.main_class) <= MAXNAMELEN) {
+            (void)strcat(env_entry, info.main_class);
+        } else {
+            ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE);
+	    exit(1);
+        }
+    }
+    (void)putenv(env_entry);
+    ExecJRE(jre, new_argv);
+    JLI_FreeManifest();
+    JLI_MemFree(new_argv);
+    return;
+}
+
+/*
+ * Parses command line arguments.  Returns JNI_FALSE if launcher
+ * should exit without starting vm, returns JNI_TRUE if vm needs
+ * to be started to process  given options. *pret (the launcher
+ * process return value) is set to 0 for a normal exit.
+ */
+static jboolean
+ParseArguments(int *pargc, char ***pargv, char **pjarfile,
+                       char **pclassname, int *pret, const char *jvmpath)
+{
+    int argc = *pargc;
+    char **argv = *pargv;
+    jboolean jarflag = JNI_FALSE;
+    char *arg;
+
+    *pret = 0;
+
+    while ((arg = *argv) != 0 && *arg == '-') {
+        argv++; --argc;
+        if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
+            if (argc < 1) {
+                ReportErrorMessage2("%s requires class path specification",
+                                    arg, JNI_TRUE);
+                printUsage = JNI_TRUE;
+                *pret = 1;
+                return JNI_TRUE;
+            }
+            SetClassPath(*argv);
+            argv++; --argc;
+        } else if (strcmp(arg, "-jar") == 0) {
+            jarflag = JNI_TRUE;
+        } else if (strcmp(arg, "-help") == 0 ||
+                   strcmp(arg, "-h") == 0 ||
+                   strcmp(arg, "-?") == 0) {
+            printUsage = JNI_TRUE;
+            return JNI_TRUE;
+        } else if (strcmp(arg, "-version") == 0) {
+            printVersion = JNI_TRUE;
+            return JNI_TRUE;
+        } else if (strcmp(arg, "-showversion") == 0) {
+            showVersion = JNI_TRUE;
+        } else if (strcmp(arg, "-X") == 0) {
+            printXUsage = JNI_TRUE;
+            return JNI_TRUE;
+/*
+ * The following case provide backward compatibility with old-style
+ * command line options.
+ */
+        } else if (strcmp(arg, "-fullversion") == 0) {
+            fprintf(stderr, "%s full version \"%s\"\n", launchername,
+                    FULL_VERSION);
+            return JNI_FALSE;
+        } else if (strcmp(arg, "-verbosegc") == 0) {
+            AddOption("-verbose:gc", NULL);
+        } else if (strcmp(arg, "-t") == 0) {
+            AddOption("-Xt", NULL);
+        } else if (strcmp(arg, "-tm") == 0) {
+            AddOption("-Xtm", NULL);
+        } else if (strcmp(arg, "-debug") == 0) {
+            AddOption("-Xdebug", NULL);
+        } else if (strcmp(arg, "-noclassgc") == 0) {
+            AddOption("-Xnoclassgc", NULL);
+        } else if (strcmp(arg, "-Xfuture") == 0) {
+            AddOption("-Xverify:all", NULL);
+        } else if (strcmp(arg, "-verify") == 0) {
+            AddOption("-Xverify:all", NULL);
+        } else if (strcmp(arg, "-verifyremote") == 0) {
+            AddOption("-Xverify:remote", NULL);
+        } else if (strcmp(arg, "-noverify") == 0) {
+            AddOption("-Xverify:none", NULL);
+        } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
+            noExitErrorMessage = 1;
+        } else if (strncmp(arg, "-prof", 5) == 0) {
+            char *p = arg + 5;
+            char *tmp = JLI_MemAlloc(strlen(arg) + 50);
+            if (*p) {
+                sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
+            } else {
+                sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
+            }
+            AddOption(tmp, NULL);
+        } else if (strncmp(arg, "-ss", 3) == 0 ||
+                   strncmp(arg, "-oss", 4) == 0 ||
+                   strncmp(arg, "-ms", 3) == 0 ||
+                   strncmp(arg, "-mx", 3) == 0) {
+            char *tmp = JLI_MemAlloc(strlen(arg) + 6);
+            sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
+            AddOption(tmp, NULL);
+        } else if (strcmp(arg, "-checksource") == 0 ||
+                   strcmp(arg, "-cs") == 0 ||
+                   strcmp(arg, "-noasyncgc") == 0) {
+            /* No longer supported */
+            fprintf(stderr,
+                    "Warning: %s option is no longer supported.\n",
+                    arg);
+        } else if (strncmp(arg, "-version:", 9) == 0 ||
+                   strcmp(arg, "-no-jre-restrict-search") == 0 ||
+                   strcmp(arg, "-jre-restrict-search") == 0 ||
+                   strncmp(arg, "-splash:", 8) == 0) {
+            ; /* Ignore machine independent options already handled */
+        } else if (RemovableMachineDependentOption(arg) ) {
+            ; /* Do not pass option to vm. */
+        }
+        else {
+            AddOption(arg, NULL);
+        }
+    }
+
+    if (--argc >= 0) {
+        if (jarflag) {
+            *pjarfile = *argv++;
+            *pclassname = 0;
+        } else {
+            *pjarfile = 0;
+            *pclassname = *argv++;
+        }
+        *pargc = argc;
+        *pargv = argv;
+    }
+
+    return JNI_TRUE;
+}
+
+/*
+ * Initializes the Java Virtual Machine. Also frees options array when
+ * finished.
+ */
+static jboolean
+InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
+{
+    JavaVMInitArgs args;
+    jint r;
+
+    memset(&args, 0, sizeof(args));
+    args.version  = JNI_VERSION_1_2;
+    args.nOptions = numOptions;
+    args.options  = options;
+    args.ignoreUnrecognized = JNI_FALSE;
+
+    if (_launcher_debug) {
+        int i = 0;
+        printf("JavaVM args:\n    ");
+        printf("version 0x%08lx, ", (long)args.version);
+        printf("ignoreUnrecognized is %s, ",
+               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
+        printf("nOptions is %ld\n", (long)args.nOptions);
+        for (i = 0; i < numOptions; i++)
+            printf("    option[%2d] = '%s'\n",
+                   i, args.options[i].optionString);
+    }
+
+    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
+    JLI_MemFree(options);
+    return r == JNI_OK;
+}
+
+#define JNI_ERROR "Error: A JNI error has occurred, please check your installation and try again"
+
+#define NULL_CHECK0(e) if ((e) == 0) { \
+    ReportErrorMessage(JNI_ERROR, JNI_TRUE); \
+    return 0; \
+  }
+
+#define NULL_CHECK(e) if ((e) == 0) { \
+    ReportErrorMessage(JNI_ERROR, JNI_TRUE); \
+    return; \
+  }
+
+static jstring platformEncoding = NULL;
+static jstring getPlatformEncoding(JNIEnv *env) {
+    if (platformEncoding == NULL) {
+        jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
+        if (propname) {
+            jclass cls;
+            jmethodID mid;
+            NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
+            NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
+                                   env, cls,
+                                   "getProperty",
+                                   "(Ljava/lang/String;)Ljava/lang/String;"));
+            platformEncoding = (*env)->CallStaticObjectMethod (
+                                    env, cls, mid, propname);
+        }
+    }
+    return platformEncoding;
+}
+
+static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
+    jclass cls;
+    jmethodID mid;
+    NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
+    NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
+                           env, cls,
+                           "isSupported",
+                           "(Ljava/lang/String;)Z"));
+    return (*env)->CallStaticBooleanMethod(env, cls, mid, enc);
+}
+
+/*
+ * Returns a new Java string object for the specified platform string.
+ */
+static jstring
+NewPlatformString(JNIEnv *env, char *s)
+{
+    int len = (int)strlen(s);
+    jclass cls;
+    jmethodID mid;
+    jbyteArray ary;
+    jstring enc;
+
+    if (s == NULL)
+        return 0;
+    enc = getPlatformEncoding(env);
+
+    ary = (*env)->NewByteArray(env, len);
+    if (ary != 0) {
+        jstring str = 0;
+        (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
+        if (!(*env)->ExceptionOccurred(env)) {
+            if (isEncodingSupported(env, enc) == JNI_TRUE) {
+                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "([BLjava/lang/String;)V"));
+                str = (*env)->NewObject(env, cls, mid, ary, enc);
+            } else {
+                /*If the encoding specified in sun.jnu.encoding is not
+                  endorsed by "Charset.isSupported" we have to fall back
+                  to use String(byte[]) explicitly here without specifying
+                  the encoding name, in which the StringCoding class will
+                  pickup the iso-8859-1 as the fallback converter for us.
+                */
+                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "([B)V"));
+                str = (*env)->NewObject(env, cls, mid, ary);
+            }
+            (*env)->DeleteLocalRef(env, ary);
+            return str;
+        }
+    }
+    return 0;
+}
+
+/*
+ * Returns a new array of Java string objects for the specified
+ * array of platform strings.
+ */
+static jobjectArray
+NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
+{
+    jarray cls;
+    jarray ary;
+    int i;
+
+    NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+    NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
+    for (i = 0; i < strc; i++) {
+        jstring str = NewPlatformString(env, *strv++);
+        NULL_CHECK0(str);
+        (*env)->SetObjectArrayElement(env, ary, i, str);
+        (*env)->DeleteLocalRef(env, str);
+    }
+    return ary;
+}
+
+/*
+ * Loads a class, convert the '.' to '/'.
+ */
+static jclass
+LoadClass(JNIEnv *env, char *name)
+{
+    char *buf = JLI_MemAlloc(strlen(name) + 1);
+    char *s = buf, *t = name, c;
+    jclass cls;
+    jlong start, end;
+
+    if (_launcher_debug)
+        start = CounterGet();
+
+    do {
+        c = *t++;
+        *s++ = (c == '.') ? '/' : c;
+    } while (c != '\0');
+    cls = (*env)->FindClass(env, buf);
+    JLI_MemFree(buf);
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to load main class\n",
+               (long)(jint)Counter2Micros(end-start));
+        printf("----_JAVA_LAUNCHER_DEBUG----\n");
+    }
+
+    return cls;
+}
+
+
+/*
+ * Returns the main class name for the specified jar file.
+ */
+static jstring
+GetMainClassName(JNIEnv *env, char *jarname)
+{
+#define MAIN_CLASS "Main-Class"
+    jclass cls;
+    jmethodID mid;
+    jobject jar, man, attr;
+    jstring str, result = 0;
+
+    NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile"));
+    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "(Ljava/lang/String;)V"));
+    NULL_CHECK0(str = NewPlatformString(env, jarname));
+    NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str));
+    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest",
+                                          "()Ljava/util/jar/Manifest;"));
+    man = (*env)->CallObjectMethod(env, jar, mid);
+    if (man != 0) {
+        NULL_CHECK0(mid = (*env)->GetMethodID(env,
+                                    (*env)->GetObjectClass(env, man),
+                                    "getMainAttributes",
+                                    "()Ljava/util/jar/Attributes;"));
+        attr = (*env)->CallObjectMethod(env, man, mid);
+        if (attr != 0) {
+            NULL_CHECK0(mid = (*env)->GetMethodID(env,
+                                    (*env)->GetObjectClass(env, attr),
+                                    "getValue",
+                                    "(Ljava/lang/String;)Ljava/lang/String;"));
+            NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS));
+            result = (*env)->CallObjectMethod(env, attr, mid, str);
+        }
+    }
+    return result;
+}
+
+#ifdef JAVA_ARGS
+static char *java_args[] = JAVA_ARGS;
+static char *app_classpath[] = APP_CLASSPATH;
+
+/*
+ * For tools, convert command line args thus:
+ *   javac -cp foo:foo/"*" -J-ms32m ...
+ *   java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ...
+ */
+static void
+TranslateApplicationArgs(int *pargc, char ***pargv)
+{
+    const int NUM_ARGS = (sizeof(java_args) / sizeof(char *));
+    int argc = *pargc;
+    char **argv = *pargv;
+    int nargc = argc + NUM_ARGS;
+    char **nargv = JLI_MemAlloc((nargc + 1) * sizeof(char *));
+    int i;
+
+    *pargc = nargc;
+    *pargv = nargv;
+
+    /* Copy the VM arguments (i.e. prefixed with -J) */
+    for (i = 0; i < NUM_ARGS; i++) {
+        char *arg = java_args[i];
+        if (arg[0] == '-' && arg[1] == 'J') {
+            *nargv++ = arg + 2;
+        }
+    }
+
+    for (i = 0; i < argc; i++) {
+        char *arg = argv[i];
+        if (arg[0] == '-' && arg[1] == 'J') {
+            if (arg[2] == '\0') {
+                ReportErrorMessage("Error: the -J option should not be "
+                                   "followed by a space.", JNI_TRUE);
+                exit(1);
+            }
+            *nargv++ = arg + 2;
+        }
+    }
+
+    /* Copy the rest of the arguments */
+    for (i = 0; i < NUM_ARGS; i++) {
+        char *arg = java_args[i];
+        if (arg[0] != '-' || arg[1] != 'J') {
+            *nargv++ = arg;
+        }
+    }
+    for (i = 0; i < argc; i++) {
+        char *arg = argv[i];
+        if (arg[0] == '-') {
+            if (arg[1] == 'J')
+                continue;
+#ifdef EXPAND_CLASSPATH_WILDCARDS
+            if (arg[1] == 'c'
+                && (strcmp(arg, "-cp") == 0 ||
+                    strcmp(arg, "-classpath") == 0)
+                && i < argc - 1) {
+                *nargv++ = arg;
+                *nargv++ = (char *) JLI_WildcardExpandClasspath(argv[i+1]);
+                i++;
+                continue;
+            }
+#endif
+        }
+        *nargv++ = arg;
+    }
+    *nargv = 0;
+}
+
+/*
+ * For our tools, we try to add 3 VM options:
+ *      -Denv.class.path=<envcp>
+ *      -Dapplication.home=<apphome>
+ *      -Djava.class.path=<appcp>
+ * <envcp>   is the user's setting of CLASSPATH -- for instance the user
+ *           tells javac where to find binary classes through this environment
+ *           variable.  Notice that users will be able to compile against our
+ *           tools classes (sun.tools.javac.Main) only if they explicitly add
+ *           tools.jar to CLASSPATH.
+ * <apphome> is the directory where the application is installed.
+ * <appcp>   is the classpath to where our apps' classfiles are.
+ */
+static jboolean
+AddApplicationOptions()
+{
+    const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
+    char *envcp, *appcp, *apphome;
+    char home[MAXPATHLEN]; /* application home */
+    char separator[] = { PATH_SEPARATOR, '\0' };
+    int size, i;
+    int strlenHome;
+
+    {
+        const char *s = getenv("CLASSPATH");
+        if (s) {
+            s = (char *) JLI_WildcardExpandClasspath(s);
+            /* 40 for -Denv.class.path= */
+            envcp = (char *)JLI_MemAlloc(strlen(s) + 40);
+            sprintf(envcp, "-Denv.class.path=%s", s);
+            AddOption(envcp, NULL);
+        }
+    }
+
+    if (!GetApplicationHome(home, sizeof(home))) {
+        ReportErrorMessage("Can't determine application home", JNI_TRUE);
+        return JNI_FALSE;
+    }
+
+    /* 40 for '-Dapplication.home=' */
+    apphome = (char *)JLI_MemAlloc(strlen(home) + 40);
+    sprintf(apphome, "-Dapplication.home=%s", home);
+    AddOption(apphome, NULL);
+
+    /* How big is the application's classpath? */
+    size = 40;                                 /* 40: "-Djava.class.path=" */
+    strlenHome = (int)strlen(home);
+    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
+        size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */
+    }
+    appcp = (char *)JLI_MemAlloc(size + 1);
+    strcpy(appcp, "-Djava.class.path=");
+    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
+        strcat(appcp, home);                    /* c:\program files\myapp */
+        strcat(appcp, app_classpath[i]);        /* \lib\myapp.jar         */
+        strcat(appcp, separator);               /* ;                      */
+    }
+    appcp[strlen(appcp)-1] = '\0';  /* remove trailing path separator */
+    AddOption(appcp, NULL);
+    return JNI_TRUE;
+}
+#endif /* JAVA_ARGS */
+
+/*
+ * inject the -Dsun.java.command pseudo property into the args structure
+ * this pseudo property is used in the HotSpot VM to expose the
+ * Java class name and arguments to the main method to the VM. The
+ * HotSpot VM uses this pseudo property to store the Java class name
+ * (or jar file name) and the arguments to the class's main method
+ * to the instrumentation memory region. The sun.java.command pseudo
+ * property is not exported by HotSpot to the Java layer.
+ */
+void
+SetJavaCommandLineProp(char *classname, char *jarfile,
+                       int argc, char **argv)
+{
+
+    int i = 0;
+    size_t len = 0;
+    char* javaCommand = NULL;
+    char* dashDstr = "-Dsun.java.command=";
+
+    if (classname == NULL && jarfile == NULL) {
+        /* unexpected, one of these should be set. just return without
+         * setting the property
+         */
+        return;
+    }
+
+    /* if the class name is not set, then use the jarfile name */
+    if (classname == NULL) {
+        classname = jarfile;
+    }
+
+    /* determine the amount of memory to allocate assuming
+     * the individual components will be space separated
+     */
+    len = strlen(classname);
+    for (i = 0; i < argc; i++) {
+        len += strlen(argv[i]) + 1;
+    }
+
+    /* allocate the memory */
+    javaCommand = (char*) JLI_MemAlloc(len + strlen(dashDstr) + 1);
+
+    /* build the -D string */
+    *javaCommand = '\0';
+    strcat(javaCommand, dashDstr);
+    strcat(javaCommand, classname);
+
+    for (i = 0; i < argc; i++) {
+        /* the components of the string are space separated. In
+         * the case of embedded white space, the relationship of
+         * the white space separated components to their true
+         * positional arguments will be ambiguous. This issue may
+         * be addressed in a future release.
+         */
+        strcat(javaCommand, " ");
+        strcat(javaCommand, argv[i]);
+    }
+
+    AddOption(javaCommand, NULL);
+}
+
+/*
+ * JVM would like to know if it's created by a standard Sun launcher, or by
+ * user native application, the following property indicates the former.
+ */
+void SetJavaLauncherProp() {
+  AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL);
+}
+
+/*
+ * Prints the version information from the java.version and other properties.
+ */
+static void
+PrintJavaVersion(JNIEnv *env)
+{
+    jclass ver;
+    jmethodID print;
+
+    NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
+    NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
+
+    (*env)->CallStaticVoidMethod(env, ver, print);
+}
+
+/*
+ * Prints default usage or the Xusage message, see sun.launcher.LauncherHelp.java
+ */
+static void
+PrintUsage(JNIEnv* env, jboolean doXUsage)
+{
+  jclass cls;
+  jmethodID initHelp, vmSelect, vmSynonym, vmErgo, printHelp, printXUsageMessage;
+  jstring jprogname, vm1, vm2;
+  int i;
+
+  NULL_CHECK(cls = (*env)->FindClass(env, "sun/launcher/LauncherHelp"));
+
+
+  if (doXUsage) {
+    NULL_CHECK(printXUsageMessage = (*env)->GetStaticMethodID(env, cls,
+                                        "printXUsageMessage", "(Z)V"));
+    (*env)->CallStaticVoidMethod(env, cls, printXUsageMessage, JNI_TRUE);
+  } else {
+    NULL_CHECK(initHelp = (*env)->GetStaticMethodID(env, cls,
+                                        "initHelpMessage", "(Ljava/lang/String;)V"));
+
+    NULL_CHECK(vmSelect = (*env)->GetStaticMethodID(env, cls, "appendVmSelectMessage",
+                                        "(Ljava/lang/String;Ljava/lang/String;)V"));
+
+    NULL_CHECK(vmSynonym = (*env)->GetStaticMethodID(env, cls,
+                                        "appendVmSynonymMessage",
+                                        "(Ljava/lang/String;Ljava/lang/String;)V"));
+    NULL_CHECK(vmErgo = (*env)->GetStaticMethodID(env, cls,
+                                        "appendVmErgoMessage", "(ZLjava/lang/String;)V"));
+
+    NULL_CHECK(printHelp = (*env)->GetStaticMethodID(env, cls,
+                                        "printHelpMessage", "(Z)V"));
+
+    jprogname = (*env)->NewStringUTF(env, progname);
+
+    /* Initialize the usage message with the usual preamble */
+    (*env)->CallStaticVoidMethod(env, cls, initHelp, jprogname);
+
+
+    /* Assemble the other variant part of the usage */
+    if ((knownVMs[0].flag == VM_KNOWN) ||
+        (knownVMs[0].flag == VM_IF_SERVER_CLASS)) {
+      vm1 = (*env)->NewStringUTF(env, knownVMs[0].name);
+      vm2 =  (*env)->NewStringUTF(env, knownVMs[0].name+1);
+      (*env)->CallStaticVoidMethod(env, cls, vmSelect, vm1, vm2);
+    }
+    for (i=1; i<knownVMsCount; i++) {
+      if (knownVMs[i].flag == VM_KNOWN) {
+        vm1 =  (*env)->NewStringUTF(env, knownVMs[i].name);
+        vm2 =  (*env)->NewStringUTF(env, knownVMs[i].name+1);
+        (*env)->CallStaticVoidMethod(env, cls, vmSelect, vm1, vm2);
+      }
+    }
+    for (i=1; i<knownVMsCount; i++) {
+      if (knownVMs[i].flag == VM_ALIASED_TO) {
+        vm1 =  (*env)->NewStringUTF(env, knownVMs[i].name);
+        vm2 =  (*env)->NewStringUTF(env, knownVMs[i].alias+1);
+        (*env)->CallStaticVoidMethod(env, cls, vmSynonym, vm1, vm2);
+      }
+    }
+
+    /* The first known VM is the default */
+    {
+      jboolean isServerClassMachine = ServerClassMachine();
+
+      const char* defaultVM  =  knownVMs[0].name+1;
+      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) && isServerClassMachine) {
+        defaultVM = knownVMs[0].server_class+1;
+      }
+
+      vm1 =  (*env)->NewStringUTF(env, defaultVM);
+      (*env)->CallStaticVoidMethod(env, cls, vmErgo, isServerClassMachine,  vm1);
+    }
+
+    /* Complete the usage message and print to stderr*/
+    (*env)->CallStaticVoidMethod(env, cls, printHelp, JNI_TRUE);
+  }
+  return;
+}
+
+/*
+ * Read the jvm.cfg file and fill the knownJVMs[] array.
+ *
+ * The functionality of the jvm.cfg file is subject to change without
+ * notice and the mechanism will be removed in the future.
+ *
+ * The lexical structure of the jvm.cfg file is as follows:
+ *
+ *     jvmcfg         :=  { vmLine }
+ *     vmLine         :=  knownLine
+ *                    |   aliasLine
+ *                    |   warnLine
+ *                    |   ignoreLine
+ *                    |   errorLine
+ *                    |   predicateLine
+ *                    |   commentLine
+ *     knownLine      :=  flag  "KNOWN"                  EOL
+ *     warnLine       :=  flag  "WARN"                   EOL
+ *     ignoreLine     :=  flag  "IGNORE"                 EOL
+ *     errorLine      :=  flag  "ERROR"                  EOL
+ *     aliasLine      :=  flag  "ALIASED_TO"       flag  EOL
+ *     predicateLine  :=  flag  "IF_SERVER_CLASS"  flag  EOL
+ *     commentLine    :=  "#" text                       EOL
+ *     flag           :=  "-" identifier
+ *
+ * The semantics are that when someone specifies a flag on the command line:
+ * - if the flag appears on a knownLine, then the identifier is used as
+ *   the name of the directory holding the JVM library (the name of the JVM).
+ * - if the flag appears as the first flag on an aliasLine, the identifier
+ *   of the second flag is used as the name of the JVM.
+ * - if the flag appears on a warnLine, the identifier is used as the
+ *   name of the JVM, but a warning is generated.
+ * - if the flag appears on an ignoreLine, the identifier is recognized as the
+ *   name of a JVM, but the identifier is ignored and the default vm used
+ * - if the flag appears on an errorLine, an error is generated.
+ * - if the flag appears as the first flag on a predicateLine, and
+ *   the machine on which you are running passes the predicate indicated,
+ *   then the identifier of the second flag is used as the name of the JVM,
+ *   otherwise the identifier of the first flag is used as the name of the JVM.
+ * If no flag is given on the command line, the first vmLine of the jvm.cfg
+ * file determines the name of the JVM.
+ * PredicateLines are only interpreted on first vmLine of a jvm.cfg file,
+ * since they only make sense if someone hasn't specified the name of the
+ * JVM on the command line.
+ *
+ * The intent of the jvm.cfg file is to allow several JVM libraries to
+ * be installed in different subdirectories of a single JRE installation,
+ * for space-savings and convenience in testing.
+ * The intent is explicitly not to provide a full aliasing or predicate
+ * mechanism.
+ */
+jint
+ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
+{
+    FILE *jvmCfg;
+    char jvmCfgName[MAXPATHLEN+20];
+    char line[MAXPATHLEN+20];
+    int cnt = 0;
+    int lineno = 0;
+    jlong start, end;
+    int vmType;
+    char *tmpPtr;
+    char *altVMName = NULL;
+    char *serverClassVMName = NULL;
+    static char *whiteSpace = " \t";
+    if (_launcher_debug) {
+        start = CounterGet();
+    }
+
+    strcpy(jvmCfgName, jrepath);
+    strcat(jvmCfgName, FILESEP "lib" FILESEP);
+    strcat(jvmCfgName, arch);
+    strcat(jvmCfgName, FILESEP "jvm.cfg");
+
+    jvmCfg = fopen(jvmCfgName, "r");
+    if (jvmCfg == NULL) {
+      if (!speculative) {
+        ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
+                            JNI_TRUE);
+        exit(1);
+      } else {
+        return -1;
+      }
+    }
+    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
+        vmType = VM_UNKNOWN;
+        lineno++;
+        if (line[0] == '#')
+            continue;
+        if (line[0] != '-') {
+            fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
+                    lineno, jvmCfgName);
+        }
+        if (cnt >= knownVMsLimit) {
+            GrowKnownVMs(cnt);
+        }
+        line[strlen(line)-1] = '\0'; /* remove trailing newline */
+        tmpPtr = line + strcspn(line, whiteSpace);
+        if (*tmpPtr == 0) {
+            fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
+                    lineno, jvmCfgName);
+        } else {
+            /* Null-terminate this string for JLI_StringDup below */
+            *tmpPtr++ = 0;
+            tmpPtr += strspn(tmpPtr, whiteSpace);
+            if (*tmpPtr == 0) {
+                fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
+                        lineno, jvmCfgName);
+            } else {
+                if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
+                    vmType = VM_KNOWN;
+                } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
+                    tmpPtr += strcspn(tmpPtr, whiteSpace);
+                    if (*tmpPtr != 0) {
+                        tmpPtr += strspn(tmpPtr, whiteSpace);
+                    }
+                    if (*tmpPtr == 0) {
+                        fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
+                                lineno, jvmCfgName);
+                    } else {
+                        /* Null terminate altVMName */
+                        altVMName = tmpPtr;
+                        tmpPtr += strcspn(tmpPtr, whiteSpace);
+                        *tmpPtr = 0;
+                        vmType = VM_ALIASED_TO;
+                    }
+                } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
+                    vmType = VM_WARN;
+                } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) {
+                    vmType = VM_IGNORE;
+                } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
+                    vmType = VM_ERROR;
+                } else if (!strncmp(tmpPtr,
+                                    "IF_SERVER_CLASS",
+                                    strlen("IF_SERVER_CLASS"))) {
+                    tmpPtr += strcspn(tmpPtr, whiteSpace);
+                    if (*tmpPtr != 0) {
+                        tmpPtr += strspn(tmpPtr, whiteSpace);
+                    }
+                    if (*tmpPtr == 0) {
+                        fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n",
+                                lineno, jvmCfgName);
+                    } else {
+                        /* Null terminate server class VM name */
+                        serverClassVMName = tmpPtr;
+                        tmpPtr += strcspn(tmpPtr, whiteSpace);
+                        *tmpPtr = 0;
+                        vmType = VM_IF_SERVER_CLASS;
+                    }
+                } else {
+                    fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
+                            lineno, &jvmCfgName[0]);
+                    vmType = VM_KNOWN;
+                }
+            }
+        }
+
+        if (_launcher_debug)
+            printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
+        if (vmType != VM_UNKNOWN) {
+            knownVMs[cnt].name = JLI_StringDup(line);
+            knownVMs[cnt].flag = vmType;
+            switch (vmType) {
+            default:
+                break;
+            case VM_ALIASED_TO:
+                knownVMs[cnt].alias = JLI_StringDup(altVMName);
+                if (_launcher_debug) {
+                    printf("    name: %s  vmType: %s  alias: %s\n",
+                           knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
+                }
+                break;
+            case VM_IF_SERVER_CLASS:
+                knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName);
+                if (_launcher_debug) {
+                    printf("    name: %s  vmType: %s  server_class: %s\n",
+                           knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
+                }
+                break;
+            }
+            cnt++;
+        }
+    }
+    fclose(jvmCfg);
+    knownVMsCount = cnt;
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to parse jvm.cfg\n",
+               (long)(jint)Counter2Micros(end-start));
+    }
+
+    return cnt;
+}
+
+
+static void
+GrowKnownVMs(int minimum)
+{
+    struct vmdesc* newKnownVMs;
+    int newMax;
+
+    newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
+    if (newMax <= minimum) {
+        newMax = minimum;
+    }
+    newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc));
+    if (knownVMs != NULL) {
+        memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
+    }
+    JLI_MemFree(knownVMs);
+    knownVMs = newKnownVMs;
+    knownVMsLimit = newMax;
+}
+
+
+/* Returns index of VM or -1 if not found */
+static int
+KnownVMIndex(const char* name)
+{
+    int i;
+    if (strncmp(name, "-J", 2) == 0) name += 2;
+    for (i = 0; i < knownVMsCount; i++) {
+        if (!strcmp(name, knownVMs[i].name)) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+static void
+FreeKnownVMs()
+{
+    int i;
+    for (i = 0; i < knownVMsCount; i++) {
+        JLI_MemFree(knownVMs[i].name);
+        knownVMs[i].name = NULL;
+    }
+    JLI_MemFree(knownVMs);
+}
+
+
+/*
+ * Displays the splash screen according to the jar file name
+ * and image file names stored in environment variables
+ */
+static void
+ShowSplashScreen()
+{
+    const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY);
+    const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY);
+    int data_size;
+    void *image_data;
+    if (jar_name) {
+        image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size);
+        if (image_data) {
+            DoSplashInit();
+            DoSplashLoadMemory(image_data, data_size);
+            JLI_MemFree(image_data);
+        }
+    } else if (file_name) {
+        DoSplashInit();
+        DoSplashLoadFile(file_name);
+    } else {
+        return;
+    }
+    DoSplashSetFileJarName(file_name, jar_name);
+}
Index: /tags/icedtea-web/beta/launcher/java.h
===================================================================
--- /tags/icedtea-web/beta/launcher/java.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/java.h	(revision 403)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1998, 2007, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _JAVA_H_
+#define _JAVA_H_
+
+/*
+ * Get system specific defines.
+ */
+#include "jni.h"
+#include "java_md.h"
+#include "jli_util.h"
+
+#include <limits.h>
+
+#define CURRENT_DATA_MODEL (CHAR_BIT * sizeof(void*))
+
+/*
+ * Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
+ */
+typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
+typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
+
+typedef struct {
+    CreateJavaVM_t CreateJavaVM;
+    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
+} InvocationFunctions;
+
+/*
+ * Prototypes for launcher functions in the system specific java_md.c.
+ */
+
+jboolean
+LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
+
+void
+GetXUsagePath(char *buf, jint bufsize);
+
+jboolean
+GetApplicationHome(char *buf, jint bufsize);
+
+const char *
+GetArch();
+
+void CreateExecutionEnvironment(int *_argc,
+                                       char ***_argv,
+                                       char jrepath[],
+                                       jint so_jrepath,
+                                       char jvmpath[],
+                                       jint so_jvmpath,
+                                       char **original_argv);
+
+/*
+ * Report an error message to stderr or a window as appropriate.  The
+ * flag always is set to JNI_TRUE if message is to be reported to both
+ * strerr and windows and set to JNI_FALSE if the message should only
+ * be sent to a window.
+ */
+void ReportErrorMessage(char * message, jboolean always);
+void ReportErrorMessage2(char * format, char * string, jboolean always);
+
+/*
+ * Report an exception which terminates the vm to stderr or a window
+ * as appropriate.
+ */
+void ReportExceptionDescription(JNIEnv * env);
+
+jboolean RemovableMachineDependentOption(char * option);
+void PrintMachineDependentOptions();
+
+const char *jlong_format_specifier();
+/*
+ * Block current thread and continue execution in new thread
+ */
+int ContinueInNewThread(int (JNICALL *continuation)(void *),
+                        jlong stack_size, void * args, int ret);
+
+/* sun.java.launcher.* platform properties. */
+void SetJavaLauncherPlatformProps(void);
+
+/*
+ * Functions defined in java.c and used in java_md.c.
+ */
+jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
+char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
+void AddOption(char *str, void *info);
+
+/*
+ * Make launcher spit debug output.
+ */
+extern jboolean _launcher_debug;
+
+#endif /* _JAVA_H_ */
Index: /tags/icedtea-web/beta/launcher/java_md.c
===================================================================
--- /tags/icedtea-web/beta/launcher/java_md.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/java_md.c	(revision 403)
@@ -0,0 +1,1814 @@
+/*
+ * Copyright (c) 1998, 2007, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include "java.h"
+#include <dirent.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "manifest_info.h"
+#include "version_comp.h"
+
+#ifdef __linux__
+#include <pthread.h>
+#else
+#include <thread.h>
+#endif
+
+#define JVM_DLL "libjvm.so"
+#define JAVA_DLL "libjava.so"
+
+/*
+ * If a processor / os combination has the ability to run binaries of
+ * two data models and cohabitation of jre/jdk bits with both data
+ * models is supported, then DUAL_MODE is defined.  When DUAL_MODE is
+ * defined, the architecture names for the narrow and wide version of
+ * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME.  Currently
+ * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
+ * i586/amd64 could be defined as DUAL_MODE but that is not the
+ * current policy.
+ */
+
+#ifndef LIBARCHNAME
+#  error "The macro LIBARCHNAME was not defined on the compile line"
+#endif
+
+#ifdef __sun
+#  define DUAL_MODE
+#  ifndef LIBARCH32NAME
+#    error "The macro LIBARCH32NAME was not defined on the compile line"
+#  endif
+#  ifndef LIBARCH64NAME
+#    error "The macro LIBARCH64NAME was not defined on the compile line"
+#  endif
+#  include <sys/systeminfo.h>
+#  include <sys/elf.h>
+#  include <stdio.h>
+#endif
+
+/* pointer to environment */
+extern char **environ;
+
+/*
+ *      A collection of useful strings. One should think of these as #define
+ *      entries, but actual strings can be more efficient (with many compilers).
+ */
+#ifdef __linux__
+static const char *system_dir   = "/usr/java";
+static const char *user_dir     = "/java";
+#else /* Solaris */
+static const char *system_dir   = "/usr/jdk";
+static const char *user_dir     = "/jdk";
+#endif
+
+/*
+ * Flowchart of launcher execs and options processing on unix
+ *
+ * The selection of the proper vm shared library to open depends on
+ * several classes of command line options, including vm "flavor"
+ * options (-client, -server) and the data model options, -d32  and
+ * -d64, as well as a version specification which may have come from
+ * the command line or from the manifest of an executable jar file.
+ * The vm selection options are not passed to the running
+ * virtual machine; they must be screened out by the launcher.
+ *
+ * The version specification (if any) is processed first by the
+ * platform independent routine SelectVersion.  This may result in
+ * the exec of the specified launcher version.
+ *
+ * Typically, the launcher execs at least once to ensure a suitable
+ * LD_LIBRARY_PATH is in effect for the process.  The first exec
+ * screens out all the data model options; leaving the choice of data
+ * model implicit in the binary selected to run.  However, in case no
+ * exec is done, the data model options are screened out before the vm
+ * is invoked.
+ *
+ *  incoming argv ------------------------------
+ *  |                                          |
+ * \|/                                         |
+ * CheckJVMType                                |
+ * (removes -client, -server, etc.)            |
+ *                                            \|/
+ *                                            CreateExecutionEnvironment
+ *                                            (removes -d32 and -d64,
+ *                                             determines desired data model,
+ *                                             sets up LD_LIBRARY_PATH,
+ *                                             and exec's)
+ *                                             |
+ *  --------------------------------------------
+ *  |
+ * \|/
+ * exec child 1 incoming argv -----------------
+ *  |                                          |
+ * \|/                                         |
+ * CheckJVMType                                |
+ * (removes -client, -server, etc.)            |
+ *  |                                         \|/
+ *  |                                          CreateExecutionEnvironment
+ *  |                                          (verifies desired data model
+ *  |                                           is running and acceptable
+ *  |                                           LD_LIBRARY_PATH;
+ *  |                                           no-op in child)
+ *  |
+ * \|/
+ * TranslateDashJArgs...
+ * (Prepare to pass args to vm)
+ *  |
+ *  |
+ *  |
+ * \|/
+ * ParseArguments
+ * (ignores -d32 and -d64,
+ *  processes version options,
+ *  creates argument list for vm,
+ *  etc.)
+ *
+ */
+
+static char *SetExecname(char **argv);
+static char * GetExecname();
+static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
+                           char *jvmpath, jint jvmpathsize, char * arch);
+static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
+static jboolean GetIcedTeaWebJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
+
+const char *
+GetArch()
+{
+    return LIBARCHNAME;
+}
+
+void
+CreateExecutionEnvironment(int *_argcp,
+                           char ***_argvp,
+                           char jrepath[],
+                           jint so_jrepath,
+                           char jvmpath[],
+                           jint so_jvmpath,
+                           char **original_argv) {
+  /*
+   * First, determine if we are running the desired data model.  If we
+   * are running the desired data model, all the error messages
+   * associated with calling GetJREPath, ReadKnownVMs, etc. should be
+   * output.  However, if we are not running the desired data model,
+   * some of the errors should be suppressed since it is more
+   * informative to issue an error message based on whether or not the
+   * os/processor combination has dual mode capabilities.
+   */
+
+    char *execname = NULL;
+    int original_argc = *_argcp;
+    jboolean jvmpathExists;
+
+    /* Compute the name of the executable */
+    execname = SetExecname(*_argvp);
+
+    /* Set the LD_LIBRARY_PATH environment variable, check data model
+       flags, and exec process, if needed */
+    {
+      char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
+      char * jvmtype    = NULL;
+      int argc          = *_argcp;
+      char **argv       = original_argv;
+
+      char *runpath     = NULL; /* existing effective LD_LIBRARY_PATH
+                                   setting */
+
+      int running       = CURRENT_DATA_MODEL;
+
+      int wanted        = running;      /* What data mode is being
+                                           asked for? Current model is
+                                           fine unless another model
+                                           is asked for */
+
+      char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
+      char* newpath     = NULL; /* path on new LD_LIBRARY_PATH */
+      char* lastslash   = NULL;
+
+      char** newenvp    = NULL; /* current environment */
+
+      char** newargv    = NULL;
+      int    newargc    = 0;
+#ifdef __sun
+      char*  dmpath     = NULL;  /* data model specific LD_LIBRARY_PATH,
+                                    Solaris only */
+#endif
+
+      /*
+       * Starting in 1.5, all unix platforms accept the -d32 and -d64
+       * options.  On platforms where only one data-model is supported
+       * (e.g. ia-64 Linux), using the flag for the other data model is
+       * an error and will terminate the program.
+       */
+
+      { /* open new scope to declare local variables */
+        int i;
+
+        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
+        newargv[newargc++] = argv[0];
+
+        /* scan for data model arguments and remove from argument list;
+           last occurrence determines desired data model */
+        for (i=1; i < argc; i++) {
+
+          if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) {
+            wanted = 64;
+            continue;
+          }
+          if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) {
+            wanted = 32;
+            continue;
+          }
+          newargv[newargc++] = argv[i];
+
+#ifdef JAVA_ARGS
+          if (argv[i][0] != '-')
+            continue;
+#else
+          if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) {
+            i++;
+            if (i >= argc) break;
+            newargv[newargc++] = argv[i];
+            continue;
+          }
+          if (argv[i][0] != '-') { i++; break; }
+#endif
+        }
+
+        /* copy rest of args [i .. argc) */
+        while (i < argc) {
+          newargv[newargc++] = argv[i++];
+        }
+        newargv[newargc] = NULL;
+
+        /*
+         * newargv has all proper arguments here
+         */
+
+        argc = newargc;
+        argv = newargv;
+      }
+
+      /* If the data model is not changing, it is an error if the
+         jvmpath does not exist */
+      if (wanted == running) {
+        /* Find out where the JRE is that we will be using. */
+        if (!GetIcedTeaWebJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
+          fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
+          exit(2);
+        }
+
+        /* Find the specified JVM type */
+        if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) {
+          fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n");
+          exit(1);
+        }
+
+        jvmpath[0] = '\0';
+        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
+
+        if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
+          fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath);
+          exit(4);
+        }
+      } else {  /* do the same speculatively or exit */
+#ifdef DUAL_MODE
+        if (running != wanted) {
+          /* Find out where the JRE is that we will be using. */
+          if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) {
+            goto EndDataModelSpeculate;
+          }
+
+          /*
+           * Read in jvm.cfg for target data model and process vm
+           * selection options.
+           */
+          if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) {
+            goto EndDataModelSpeculate;
+          }
+          jvmpath[0] = '\0';
+          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
+          /* exec child can do error checking on the existence of the path */
+          jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
+                                     ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME));
+
+        }
+      EndDataModelSpeculate: /* give up and let other code report error message */
+        ;
+#else
+        fprintf(stderr, "This Java instance does not support a %d-bit JVM.\nPlease install the desired version.\n", wanted);
+        exit(1);
+#endif
+      }
+
+      /*
+       * We will set the LD_LIBRARY_PATH as follows:
+       *
+       *     o          $JVMPATH (directory portion only)
+       *     o          $JRE/lib/$LIBARCHNAME
+       *     o          $JRE/../lib/$LIBARCHNAME
+       *
+       * followed by the user's previous effective LD_LIBRARY_PATH, if
+       * any.
+       */
+
+#ifdef __sun
+      /*
+       * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH
+       * variables:
+       *
+       * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if
+       * data-model specific variables are not set.
+       *
+       * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH
+       * for 64-bit binaries.
+       *
+       * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH
+       * for 32-bit binaries.
+       *
+       * The vm uses LD_LIBRARY_PATH to set the java.library.path system
+       * property.  To shield the vm from the complication of multiple
+       * LD_LIBRARY_PATH variables, if the appropriate data model
+       * specific variable is set, we will act as if LD_LIBRARY_PATH had
+       * the value of the data model specific variant and the data model
+       * specific variant will be unset.  Note that the variable for the
+       * *wanted* data model must be used (if it is set), not simply the
+       * current running data model.
+       */
+
+      switch(wanted) {
+      case 0:
+        if(running == 32) {
+          dmpath = getenv("LD_LIBRARY_PATH_32");
+          wanted = 32;
+        }
+        else {
+          dmpath = getenv("LD_LIBRARY_PATH_64");
+          wanted = 64;
+        }
+        break;
+
+      case 32:
+        dmpath = getenv("LD_LIBRARY_PATH_32");
+        break;
+
+      case 64:
+        dmpath = getenv("LD_LIBRARY_PATH_64");
+        break;
+
+      default:
+        fprintf(stderr, "Improper value at line %d.", __LINE__);
+        exit(1); /* unknown value in wanted */
+        break;
+      }
+
+      /*
+       * If dmpath is NULL, the relevant data model specific variable is
+       * not set and normal LD_LIBRARY_PATH should be used.
+       */
+      if( dmpath == NULL) {
+        runpath = getenv("LD_LIBRARY_PATH");
+      }
+      else {
+        runpath = dmpath;
+      }
+#else
+      /*
+       * If not on Solaris, assume only a single LD_LIBRARY_PATH
+       * variable.
+       */
+      runpath = getenv("LD_LIBRARY_PATH");
+#endif /* __sun */
+
+#ifdef __linux
+      /*
+       * On linux, if a binary is running as sgid or suid, glibc sets
+       * LD_LIBRARY_PATH to the empty string for security purposes.  (In
+       * contrast, on Solaris the LD_LIBRARY_PATH variable for a
+       * privileged binary does not lose its settings; but the dynamic
+       * linker does apply more scrutiny to the path.) The launcher uses
+       * the value of LD_LIBRARY_PATH to prevent an exec loop.
+       * Therefore, if we are running sgid or suid, this function's
+       * setting of LD_LIBRARY_PATH will be ineffective and we should
+       * return from the function now.  Getting the right libraries to
+       * be found must be handled through other mechanisms.
+       */
+      if((getgid() != getegid()) || (getuid() != geteuid()) ) {
+        return;
+      }
+#endif
+
+      /* runpath contains current effective LD_LIBRARY_PATH setting */
+
+      jvmpath = JLI_StringDup(jvmpath);
+      new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
+                              2*strlen(jrepath) + 2*strlen(arch) +
+                              strlen(jvmpath) + 52);
+      newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
+
+
+      /*
+       * Create desired LD_LIBRARY_PATH value for target data model.
+       */
+      {
+        /* remove the name of the .so from the JVM path */
+        lastslash = strrchr(jvmpath, '/');
+        if (lastslash)
+          *lastslash = '\0';
+
+
+        /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */
+
+        sprintf(new_runpath, "LD_LIBRARY_PATH="
+                "%s:"
+                "%s/lib/%s:"
+                "%s/../lib/%s",
+                jvmpath,
+#ifdef DUAL_MODE
+                jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME),
+                jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)
+#else
+                jrepath, arch,
+                jrepath, arch
+#endif
+                );
+
+
+        /*
+         * Check to make sure that the prefix of the current path is the
+         * desired environment variable setting.
+         */
+        if (runpath != NULL &&
+            strncmp(newpath, runpath, strlen(newpath))==0 &&
+            (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') &&
+            (running == wanted) /* data model does not have to be changed */
+#ifdef __sun
+            && (dmpath == NULL)    /* data model specific variables not set  */
+#endif
+            ) {
+
+          return;
+
+        }
+      }
+
+      /*
+       * Place the desired environment setting onto the prefix of
+       * LD_LIBRARY_PATH.  Note that this prevents any possible infinite
+       * loop of execv() because we test for the prefix, above.
+       */
+      if (runpath != 0 && (runpath[0] != '\0')) {
+        strcat(new_runpath, ":");
+        strcat(new_runpath, runpath);
+      }
+
+      if( putenv(new_runpath) != 0) {
+        exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set
+                    properly */
+      }
+
+      /*
+       * Unix systems document that they look at LD_LIBRARY_PATH only
+       * once at startup, so we have to re-exec the current executable
+       * to get the changed environment variable to have an effect.
+       */
+
+#ifdef __sun
+      /*
+       * If dmpath is not NULL, remove the data model specific string
+       * in the environment for the exec'ed child.
+       */
+
+      if( dmpath != NULL)
+        (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64");
+#endif
+
+      newenvp = environ;
+
+      {
+        char *newexec = execname;
+#ifdef DUAL_MODE
+        /*
+         * If the data model is being changed, the path to the
+         * executable must be updated accordingly; the executable name
+         * and directory the executable resides in are separate.  In the
+         * case of 32 => 64, the new bits are assumed to reside in, e.g.
+         * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32,
+         * the bits are assumed to be in "olddir/../execname".  For example,
+         *
+         * olddir/sparcv9/execname
+         * olddir/amd64/execname
+         *
+         * for Solaris SPARC and Linux amd64, respectively.
+         */
+
+        if (running != wanted) {
+          char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname);
+          char *olddir = oldexec;
+          char *oldbase = strrchr(oldexec, '/');
+
+
+          newexec = JLI_MemAlloc(strlen(execname) + 20);
+          *oldbase++ = 0;
+          sprintf(newexec, "%s/%s/%s", olddir,
+                  ((wanted==64) ? LIBARCH64NAME : ".."), oldbase);
+          argv[0] = newexec;
+        }
+#endif
+
+        (void)fflush(stdout);
+        (void)fflush(stderr);
+        execve(newexec, argv, newenvp);
+        perror("execve()");
+
+        fprintf(stderr, "Error trying to exec %s.\n", newexec);
+        fprintf(stderr, "Check if file exists and permissions are set correctly.\n");
+
+#ifdef DUAL_MODE
+        if (running != wanted) {
+          fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n",
+                  wanted, running);
+#  ifdef __sun
+
+#    ifdef __sparc
+          fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" );
+          fprintf(stderr,
+                  "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" );
+#    else
+          fprintf(stderr, "Either 64-bit processes are not supported by this platform\n");
+          fprintf(stderr, "or the 64-bit components have not been installed.\n");
+#    endif
+        }
+#  endif
+#endif
+
+      }
+
+      exit(1);
+    }
+
+}
+
+
+/*
+ * On Solaris VM choosing is done by the launcher (java.c).
+ */
+static jboolean
+GetJVMPath(const char *jrepath, const char *jvmtype,
+           char *jvmpath, jint jvmpathsize, char * arch)
+{
+    struct stat s;
+
+    if (strchr(jvmtype, '/')) {
+        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
+    } else {
+        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
+    }
+    if (_launcher_debug)
+      printf("Does `%s' exist ... ", jvmpath);
+
+    if (stat(jvmpath, &s) == 0) {
+        if (_launcher_debug)
+          printf("yes.\n");
+        return JNI_TRUE;
+    } else {
+        if (_launcher_debug)
+          printf("no.\n");
+        return JNI_FALSE;
+    }
+}
+
+/*
+ * Find path to the JRE based on the the compile flag ICEDTEA_WEB_JRE
+ */
+static jboolean
+GetIcedTeaWebJREPath(char* path, jint pathsize, char* arch, jboolean speculative)
+{
+    char libjava[MAXPATHLEN];
+    snprintf(libjava, MAXPATHLEN, ICEDTEA_WEB_JRE "/lib/%s/" JAVA_DLL, arch);
+
+    if (_launcher_debug) {
+      printf(ICEDTEA_WEB_JRE "/lib/%s/" JAVA_DLL "\n", arch);
+      printf("libjava is %s\n", libjava);
+    }
+
+    if (access(libjava, F_OK) == 0) {
+        strncpy(path, ICEDTEA_WEB_JRE, pathsize);
+        goto found;
+    }
+
+    return JNI_FALSE;
+
+ found:
+    if (_launcher_debug)
+      printf("JRE path is %s\n", path);
+    return JNI_TRUE;
+}
+
+/*
+ * Find path to JRE based on .exe's location or registry settings.
+ */
+static jboolean
+GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative)
+{
+    char libjava[MAXPATHLEN];
+
+    if (GetApplicationHome(path, pathsize)) {
+        /* Is JRE co-located with the application? */
+        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
+        if (access(libjava, F_OK) == 0) {
+            goto found;
+        }
+
+        /* Does the app ship a private JRE in <apphome>/jre directory? */
+        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
+        if (access(libjava, F_OK) == 0) {
+            strcat(path, "/jre");
+            goto found;
+        }
+    }
+
+    if (!speculative)
+      fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
+    return JNI_FALSE;
+
+ found:
+    if (_launcher_debug)
+      printf("JRE path is %s\n", path);
+    return JNI_TRUE;
+}
+
+jboolean
+LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
+{
+    Dl_info dlinfo;
+    void *libjvm;
+
+    if (_launcher_debug) {
+        printf("JVM path is %s\n", jvmpath);
+    }
+
+    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
+    if (libjvm == NULL) {
+#if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
+      FILE * fp;
+      Elf32_Ehdr elf_head;
+      int count;
+      int location;
+
+      fp = fopen(jvmpath, "r");
+      if(fp == NULL)
+        goto error;
+
+      /* read in elf header */
+      count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
+      fclose(fp);
+      if(count < 1)
+        goto error;
+
+      /*
+       * Check for running a server vm (compiled with -xarch=v8plus)
+       * on a stock v8 processor.  In this case, the machine type in
+       * the elf header would not be included the architecture list
+       * provided by the isalist command, which is turn is gotten from
+       * sysinfo.  This case cannot occur on 64-bit hardware and thus
+       * does not have to be checked for in binaries with an LP64 data
+       * model.
+       */
+      if(elf_head.e_machine == EM_SPARC32PLUS) {
+        char buf[257];  /* recommended buffer size from sysinfo man
+                           page */
+        long length;
+        char* location;
+
+        length = sysinfo(SI_ISALIST, buf, 257);
+        if(length > 0) {
+          location = strstr(buf, "sparcv8plus ");
+          if(location == NULL) {
+            fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n");
+            fprintf(stderr, "Use Client compiler on V8 processors.\n");
+            fprintf(stderr, "Could not create the Java virtual machine.\n");
+            return JNI_FALSE;
+          }
+        }
+      }
+#endif
+      fprintf(stderr, "dl failure on line %d", __LINE__);
+      goto error;
+    }
+
+    ifn->CreateJavaVM = (CreateJavaVM_t)
+      dlsym(libjvm, "JNI_CreateJavaVM");
+    if (ifn->CreateJavaVM == NULL)
+        goto error;
+
+    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
+        dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
+    if (ifn->GetDefaultJavaVMInitArgs == NULL)
+      goto error;
+
+    return JNI_TRUE;
+
+error:
+    fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
+    return JNI_FALSE;
+}
+
+/*
+ * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
+ * "/foo" into buf.
+ */
+jboolean
+GetApplicationHome(char *buf, jint bufsize)
+{
+#ifdef __linux__
+    char *execname = GetExecname();
+    if (execname) {
+        strncpy(buf, execname, bufsize-1);
+        buf[bufsize-1] = '\0';
+    } else {
+        return JNI_FALSE;
+    }
+#else
+    Dl_info dlinfo;
+
+    dladdr((void *)GetApplicationHome, &dlinfo);
+    if (realpath(dlinfo.dli_fname, buf) == NULL) {
+        fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname);
+        return JNI_FALSE;
+    }
+#endif
+
+    if (strrchr(buf, '/') == 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    *(strrchr(buf, '/')) = '\0';        /* executable file      */
+    if (strlen(buf) < 4 || strrchr(buf, '/') == 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    if (strcmp("/bin", buf + strlen(buf) - 4) != 0)
+        *(strrchr(buf, '/')) = '\0';    /* sparcv9 or amd64     */
+    if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    *(strrchr(buf, '/')) = '\0';        /* bin                  */
+
+    return JNI_TRUE;
+}
+
+
+/*
+ * Return true if the named program exists
+ */
+static int
+ProgramExists(char *name)
+{
+    struct stat sb;
+    if (stat(name, &sb) != 0) return 0;
+    if (S_ISDIR(sb.st_mode)) return 0;
+    return (sb.st_mode & S_IEXEC) != 0;
+}
+
+
+/*
+ * Find a command in a directory, returning the path.
+ */
+static char *
+Resolve(char *indir, char *cmd)
+{
+    char name[PATH_MAX + 2], *real;
+
+    if ((strlen(indir) + strlen(cmd) + 1)  > PATH_MAX) return 0;
+    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
+    if (!ProgramExists(name)) return 0;
+    real = JLI_MemAlloc(PATH_MAX + 2);
+    if (!realpath(name, real))
+        strcpy(real, name);
+    return real;
+}
+
+
+/*
+ * Find a path for the executable
+ */
+static char *
+FindExecName(char *program)
+{
+    char cwdbuf[PATH_MAX+2];
+    char *path;
+    char *tmp_path;
+    char *f;
+    char *result = NULL;
+
+    /* absolute path? */
+    if (*program == FILE_SEPARATOR ||
+        (FILE_SEPARATOR=='\\' && strrchr(program, ':')))
+        return Resolve("", program+1);
+
+    /* relative path? */
+    if (strrchr(program, FILE_SEPARATOR) != 0) {
+        char buf[PATH_MAX+2];
+        return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
+    }
+
+    /* from search path? */
+    path = getenv("PATH");
+    if (!path || !*path) path = ".";
+    tmp_path = JLI_MemAlloc(strlen(path) + 2);
+    strcpy(tmp_path, path);
+
+    for (f=tmp_path; *f && result==0; ) {
+        char *s = f;
+        while (*f && (*f != PATH_SEPARATOR)) ++f;
+        if (*f) *f++ = 0;
+        if (*s == FILE_SEPARATOR)
+            result = Resolve(s, program);
+        else {
+            /* relative path element */
+            char dir[2*PATH_MAX];
+            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
+                    FILE_SEPARATOR, s);
+            result = Resolve(dir, program);
+        }
+        if (result != 0) break;
+    }
+
+    JLI_MemFree(tmp_path);
+    return result;
+}
+
+
+/* Store the name of the executable once computed */
+static char *execname = NULL;
+
+/*
+ * Compute the name of the executable
+ *
+ * In order to re-exec securely we need the absolute path of the
+ * executable. On Solaris getexecname(3c) may not return an absolute
+ * path so we use dladdr to get the filename of the executable and
+ * then use realpath to derive an absolute path. From Solaris 9
+ * onwards the filename returned in DL_info structure from dladdr is
+ * an absolute pathname so technically realpath isn't required.
+ * On Linux we read the executable name from /proc/self/exe.
+ * As a fallback, and for platforms other than Solaris and Linux,
+ * we use FindExecName to compute the executable name.
+ */
+static char *
+SetExecname(char **argv)
+{
+    char* exec_path = NULL;
+
+    if (execname != NULL)       /* Already determined */
+        return (execname);
+
+#if defined(__sun)
+    {
+        Dl_info dlinfo;
+        if (dladdr((void*)&SetExecname, &dlinfo)) {
+            char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
+            if (resolved != NULL) {
+                exec_path = realpath(dlinfo.dli_fname, resolved);
+                if (exec_path == NULL) {
+                    JLI_MemFree(resolved);
+                }
+            }
+        }
+    }
+#elif defined(__linux__)
+    {
+        const char* self = "/proc/self/exe";
+        char buf[PATH_MAX+1];
+        int len = readlink(self, buf, PATH_MAX);
+        if (len >= 0) {
+            buf[len] = '\0';            /* readlink doesn't nul terminate */
+            exec_path = JLI_StringDup(buf);
+        }
+    }
+#else /* !__sun && !__linux */
+    {
+        /* Not implemented */
+    }
+#endif
+
+    if (exec_path == NULL) {
+        exec_path = FindExecName(argv[0]);
+    }
+    execname = exec_path;
+    return exec_path;
+}
+
+/*
+ * Return the name of the executable.  Used in java_md.c to find the JRE area.
+ */
+static char *
+GetExecname() {
+  return execname;
+}
+
+void ReportErrorMessage(char * message, jboolean always) {
+  if (always) {
+    fprintf(stderr, "%s\n", message);
+  }
+}
+
+void ReportErrorMessage2(char * format, char * string, jboolean always) {
+  if (always) {
+    fprintf(stderr, format, string);
+    fprintf(stderr, "\n");
+  }
+}
+
+void  ReportExceptionDescription(JNIEnv * env) {
+  (*env)->ExceptionDescribe(env);
+}
+
+/*
+ * Return JNI_TRUE for an option string that has no effect but should
+ * _not_ be passed on to the vm; return JNI_FALSE otherwise.  On
+ * Solaris SPARC, this screening needs to be done if:
+ * 1) LD_LIBRARY_PATH does _not_ need to be reset and
+ * 2) -d32 or -d64 is passed to a binary with a matching data model
+ *    (the exec in SetLibraryPath removes -d<n> options and points the
+ *    exec to the proper binary).  When this exec is not done, these options
+ *    would end up getting passed onto the vm.
+ */
+jboolean RemovableMachineDependentOption(char * option) {
+  /*
+   * Unconditionally remove both -d32 and -d64 options since only
+   * the last such options has an effect; e.g.
+   * java -d32 -d64 -d32 -version
+   * is equivalent to
+   * java -d32 -version
+   */
+
+  if( (strcmp(option, "-d32")  == 0 ) ||
+      (strcmp(option, "-d64")  == 0 ) )
+    return JNI_TRUE;
+  else
+    return JNI_FALSE;
+}
+
+/*
+ * The following methods (down to ServerClassMachine()) answer
+ * the question about whether a machine is a "server-class"
+ * machine.  A server-class machine is loosely defined as one
+ * with 2 or more processors and 2 gigabytes or more physical
+ * memory.  The definition of a processor is a physical package,
+ * not a hyperthreaded chip masquerading as a multi-processor.
+ * The definition of memory is also somewhat fuzzy, since x86
+ * machines seem not to report all the memory in their DIMMs, we
+ * think because of memory mapping of graphics cards, etc.
+ *
+ * This code is somewhat more confused with #ifdef's than we'd
+ * like because this file is used by both Solaris and Linux
+ * platforms, and so needs to be parameterized for SPARC and
+ * i586 hardware.  The other Linux platforms (amd64 and ia64)
+ * don't even ask this question, because they only come with
+ * server JVMs.  */
+
+# define KB (1024UL)
+# define MB (1024UL * KB)
+# define GB (1024UL * MB)
+
+/* Compute physical memory by asking the OS */
+uint64_t
+physical_memory(void) {
+  const uint64_t pages     = (uint64_t) sysconf(_SC_PHYS_PAGES);
+  const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE);
+  const uint64_t result    = pages * page_size;
+# define UINT64_FORMAT "%" PRIu64
+
+  if (_launcher_debug) {
+    printf("pages: " UINT64_FORMAT
+           "  page_size: " UINT64_FORMAT
+           "  physical memory: " UINT64_FORMAT " (%.3fGB)\n",
+           pages, page_size, result, result / (double) GB);
+  }
+  return result;
+}
+
+#if defined(__sparc)
+
+/* Methods for solaris-sparc and linux-sparc: these are easy. */
+
+/* Ask the OS how many processors there are. */
+unsigned long
+physical_processors(void) {
+  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+
+  if (_launcher_debug) {
+    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  }
+  return sys_processors;
+}
+
+/* The sparc version of the "server-class" predicate. */
+jboolean
+unix_sparc_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= server_memory) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
+  }
+  return result;
+}
+
+#endif /* __sparc */
+
+#if defined(__sun) && defined(i586)
+
+/*
+ * A utility method for asking the CPU about itself.
+ * There's a corresponding version of linux-i586
+ * because the compilers are different.
+ */
+void
+get_cpuid(uint32_t arg,
+          uint32_t* eaxp,
+          uint32_t* ebxp,
+          uint32_t* ecxp,
+          uint32_t* edxp) {
+#ifdef _LP64
+  asm(
+  /* rbx is a callee-saved register */
+      " movq    %rbx, %r11  \n"
+  /* rdx and rcx are 3rd and 4th argument registers */
+      " movq    %rdx, %r10  \n"
+      " movq    %rcx, %r9   \n"
+      " movl    %edi, %eax  \n"
+      " cpuid               \n"
+      " movl    %eax, (%rsi)\n"
+      " movl    %ebx, (%r10)\n"
+      " movl    %ecx, (%r9) \n"
+      " movl    %edx, (%r8) \n"
+  /* Restore rbx */
+      " movq    %r11, %rbx");
+#else
+  /* EBX is a callee-saved register */
+  asm(" pushl   %ebx");
+  /* Need ESI for storing through arguments */
+  asm(" pushl   %esi");
+  asm(" movl    8(%ebp), %eax   \n"
+      " cpuid                   \n"
+      " movl    12(%ebp), %esi  \n"
+      " movl    %eax, (%esi)    \n"
+      " movl    16(%ebp), %esi  \n"
+      " movl    %ebx, (%esi)    \n"
+      " movl    20(%ebp), %esi  \n"
+      " movl    %ecx, (%esi)    \n"
+      " movl    24(%ebp), %esi  \n"
+      " movl    %edx, (%esi)      ");
+  /* Restore ESI and EBX */
+  asm(" popl    %esi");
+  /* Restore EBX */
+  asm(" popl    %ebx");
+#endif
+}
+
+#endif /* __sun && i586 */
+
+#if defined(__linux__) && defined(i586)
+
+/*
+ * A utility method for asking the CPU about itself.
+ * There's a corresponding version of solaris-i586
+ * because the compilers are different.
+ */
+void
+get_cpuid(uint32_t arg,
+          uint32_t* eaxp,
+          uint32_t* ebxp,
+          uint32_t* ecxp,
+          uint32_t* edxp) {
+#ifdef _LP64
+  __asm__ volatile (/* Instructions */
+                    "   movl    %4, %%eax  \n"
+                    "   cpuid              \n"
+                    "   movl    %%eax, (%0)\n"
+                    "   movl    %%ebx, (%1)\n"
+                    "   movl    %%ecx, (%2)\n"
+                    "   movl    %%edx, (%3)\n"
+                    : /* Outputs */
+                    : /* Inputs */
+                    "r" (eaxp),
+                    "r" (ebxp),
+                    "r" (ecxp),
+                    "r" (edxp),
+                    "r" (arg)
+                    : /* Clobbers */
+                    "%rax", "%rbx", "%rcx", "%rdx", "memory"
+                    );
+#else
+  uint32_t value_of_eax = 0;
+  uint32_t value_of_ebx = 0;
+  uint32_t value_of_ecx = 0;
+  uint32_t value_of_edx = 0;
+  __asm__ volatile (/* Instructions */
+                        /* ebx is callee-save, so push it */
+                    "   pushl   %%ebx      \n"
+                    "   movl    %4, %%eax  \n"
+                    "   cpuid              \n"
+                    "   movl    %%eax, %0  \n"
+                    "   movl    %%ebx, %1  \n"
+                    "   movl    %%ecx, %2  \n"
+                    "   movl    %%edx, %3  \n"
+                        /* restore ebx */
+                    "   popl    %%ebx      \n"
+
+                    : /* Outputs */
+                    "=m" (value_of_eax),
+                    "=m" (value_of_ebx),
+                    "=m" (value_of_ecx),
+                    "=m" (value_of_edx)
+                    : /* Inputs */
+                    "m" (arg)
+                    : /* Clobbers */
+                    "%eax", "%ecx", "%edx"
+                    );
+  *eaxp = value_of_eax;
+  *ebxp = value_of_ebx;
+  *ecxp = value_of_ecx;
+  *edxp = value_of_edx;
+#endif
+}
+
+#endif /* __linux__ && i586 */
+
+#ifdef i586
+/*
+ * Routines shared by solaris-i586 and linux-i586.
+ */
+
+enum HyperThreadingSupport_enum {
+  hts_supported        =  1,
+  hts_too_soon_to_tell =  0,
+  hts_not_supported    = -1,
+  hts_not_pentium4     = -2,
+  hts_not_intel        = -3
+};
+typedef enum HyperThreadingSupport_enum HyperThreadingSupport;
+
+/* Determine if hyperthreading is supported */
+HyperThreadingSupport
+hyperthreading_support(void) {
+  HyperThreadingSupport result = hts_too_soon_to_tell;
+  /* Bits 11 through 8 is family processor id */
+# define FAMILY_ID_SHIFT 8
+# define FAMILY_ID_MASK 0xf
+  /* Bits 23 through 20 is extended family processor id */
+# define EXT_FAMILY_ID_SHIFT 20
+# define EXT_FAMILY_ID_MASK 0xf
+  /* Pentium 4 family processor id */
+# define PENTIUM4_FAMILY_ID 0xf
+  /* Bit 28 indicates Hyper-Threading Technology support */
+# define HT_BIT_SHIFT 28
+# define HT_BIT_MASK 1
+  uint32_t vendor_id[3] = { 0U, 0U, 0U };
+  uint32_t value_of_eax = 0U;
+  uint32_t value_of_edx = 0U;
+  uint32_t dummy        = 0U;
+
+  /* Yes, this is supposed to be [0], [2], [1] */
+  get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]);
+  if (_launcher_debug) {
+    printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n",
+           ((vendor_id[0] >>  0) & 0xff),
+           ((vendor_id[0] >>  8) & 0xff),
+           ((vendor_id[0] >> 16) & 0xff),
+           ((vendor_id[0] >> 24) & 0xff),
+           ((vendor_id[1] >>  0) & 0xff),
+           ((vendor_id[1] >>  8) & 0xff),
+           ((vendor_id[1] >> 16) & 0xff),
+           ((vendor_id[1] >> 24) & 0xff),
+           ((vendor_id[2] >>  0) & 0xff),
+           ((vendor_id[2] >>  8) & 0xff),
+           ((vendor_id[2] >> 16) & 0xff),
+           ((vendor_id[2] >> 24) & 0xff));
+  }
+  get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx);
+  if (_launcher_debug) {
+    printf("value_of_eax: 0x%x  value_of_edx: 0x%x\n",
+           value_of_eax, value_of_edx);
+  }
+  if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) ||
+      (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) {
+    if ((((vendor_id[0] >>  0) & 0xff) == 'G') &&
+        (((vendor_id[0] >>  8) & 0xff) == 'e') &&
+        (((vendor_id[0] >> 16) & 0xff) == 'n') &&
+        (((vendor_id[0] >> 24) & 0xff) == 'u') &&
+        (((vendor_id[1] >>  0) & 0xff) == 'i') &&
+        (((vendor_id[1] >>  8) & 0xff) == 'n') &&
+        (((vendor_id[1] >> 16) & 0xff) == 'e') &&
+        (((vendor_id[1] >> 24) & 0xff) == 'I') &&
+        (((vendor_id[2] >>  0) & 0xff) == 'n') &&
+        (((vendor_id[2] >>  8) & 0xff) == 't') &&
+        (((vendor_id[2] >> 16) & 0xff) == 'e') &&
+        (((vendor_id[2] >> 24) & 0xff) == 'l')) {
+      if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) {
+        if (_launcher_debug) {
+          printf("Hyperthreading supported\n");
+        }
+        result = hts_supported;
+      } else {
+        if (_launcher_debug) {
+          printf("Hyperthreading not supported\n");
+        }
+        result = hts_not_supported;
+      }
+    } else {
+      if (_launcher_debug) {
+        printf("Not GenuineIntel\n");
+      }
+      result = hts_not_intel;
+    }
+  } else {
+    if (_launcher_debug) {
+      printf("not Pentium 4 or extended\n");
+    }
+    result = hts_not_pentium4;
+  }
+  return result;
+}
+
+/* Determine how many logical processors there are per CPU */
+unsigned int
+logical_processors_per_package(void) {
+  /*
+   * After CPUID with EAX==1, register EBX bits 23 through 16
+   * indicate the number of logical processors per package
+   */
+# define NUM_LOGICAL_SHIFT 16
+# define NUM_LOGICAL_MASK 0xff
+  unsigned int result                        = 1U;
+  const HyperThreadingSupport hyperthreading = hyperthreading_support();
+
+  if (hyperthreading == hts_supported) {
+    uint32_t value_of_ebx = 0U;
+    uint32_t dummy        = 0U;
+
+    get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy);
+    result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK;
+    if (_launcher_debug) {
+      printf("logical processors per package: %u\n", result);
+    }
+  }
+  return result;
+}
+
+/* Compute the number of physical processors, not logical processors */
+unsigned long
+physical_processors(void) {
+  const long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+  unsigned long result      = sys_processors;
+
+  if (_launcher_debug) {
+    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  }
+  if (sys_processors > 1) {
+    unsigned int logical_processors = logical_processors_per_package();
+    if (logical_processors > 1) {
+      result = (unsigned long) sys_processors / logical_processors;
+    }
+  }
+  if (_launcher_debug) {
+    printf("physical processors: %lu\n", result);
+  }
+  return result;
+}
+
+#endif /* i586 */
+
+#if defined(__sun) && defined(i586)
+
+/* The definition of a server-class machine for solaris-i586/amd64 */
+jboolean
+solaris_i586_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  /*
+   * We seem not to get our full complement of memory.
+   *     We allow some part (1/8?) of the memory to be "missing",
+   *     based on the sizes of DIMMs, and maybe graphics cards.
+   */
+  const uint64_t      missing_memory    = 256UL * MB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= (server_memory - missing_memory)) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+  return result;
+}
+
+#endif /* __sun && i586 */
+
+#if defined(__linux__) && defined(i586)
+
+/* The definition of a server-class machine for linux-i586 */
+jboolean
+linux_i586_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  /*
+   * We seem not to get our full complement of memory.
+   *     We allow some part (1/8?) of the memory to be "missing",
+   *     based on the sizes of DIMMs, and maybe graphics cards.
+   */
+  const uint64_t      missing_memory    = 256UL * MB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= (server_memory - missing_memory)) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+  return result;
+}
+
+#endif /* __linux__ && i586 */
+
+/* Dispatch to the platform-specific definition of "server-class" */
+jboolean
+ServerClassMachine(void) {
+  jboolean result = JNI_FALSE;
+#if   defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_FALSE;
+#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_TRUE;
+#elif defined(__sun) && defined(__sparc)
+  result = unix_sparc_ServerClassMachine();
+#elif defined(__sun) && defined(i586)
+  result = solaris_i586_ServerClassMachine();
+#elif defined(__linux__) && defined(i586)
+  result = linux_i586_ServerClassMachine();
+#else
+  if (_launcher_debug) {
+    printf("ServerClassMachine: returns default value of %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+#endif
+  return result;
+}
+
+/*
+ *      Since using the file system as a registry is a bit risky, perform
+ *      additional sanity checks on the identified directory to validate
+ *      it as a valid jre/sdk.
+ *
+ *      Return 0 if the tests fail; otherwise return non-zero (true).
+ *
+ *      Note that checking for anything more than the existence of an
+ *      executable object at bin/java relative to the path being checked
+ *      will break the regression tests.
+ */
+static int
+CheckSanity(char *path, char *dir)
+{
+    char    buffer[PATH_MAX];
+
+    if (strlen(path) + strlen(dir) + 11 > PATH_MAX)
+        return (0);     /* Silently reject "impossibly" long paths */
+
+    (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java");
+    return ((access(buffer, X_OK) == 0) ? 1 : 0);
+}
+
+/*
+ *      Determine if there is an acceptable JRE in the directory dirname.
+ *      Upon locating the "best" one, return a fully qualified path to
+ *      it. "Best" is defined as the most advanced JRE meeting the
+ *      constraints contained in the manifest_info. If no JRE in this
+ *      directory meets the constraints, return NULL.
+ *
+ *      Note that we don't check for errors in reading the directory
+ *      (which would be done by checking errno).  This is because it
+ *      doesn't matter if we get an error reading the directory, or
+ *      we just don't find anything interesting in the directory.  We
+ *      just return NULL in either case.
+ *
+ *      The historical names of j2sdk and j2re were changed to jdk and
+ *      jre respecively as part of the 1.5 rebranding effort.  Since the
+ *      former names are legacy on Linux, they must be recognized for
+ *      all time.  Fortunately, this is a minor cost.
+ */
+static char
+*ProcessDir(manifest_info *info, char *dirname)
+{
+    DIR     *dirp;
+    struct dirent *dp;
+    char    *best = NULL;
+    int     offset;
+    int     best_offset = 0;
+    char    *ret_str = NULL;
+    char    buffer[PATH_MAX];
+
+    if ((dirp = opendir(dirname)) == NULL)
+        return (NULL);
+
+    do {
+        if ((dp = readdir(dirp)) != NULL) {
+            offset = 0;
+            if ((strncmp(dp->d_name, "jre", 3) == 0) ||
+                (strncmp(dp->d_name, "jdk", 3) == 0))
+                offset = 3;
+            else if (strncmp(dp->d_name, "j2re", 4) == 0)
+                offset = 4;
+            else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
+                offset = 5;
+            if (offset > 0) {
+                if ((JLI_AcceptableRelease(dp->d_name + offset,
+                    info->jre_version)) && CheckSanity(dirname, dp->d_name))
+                    if ((best == NULL) || (JLI_ExactVersionId(
+                      dp->d_name + offset, best + best_offset) > 0)) {
+                        if (best != NULL)
+                            JLI_MemFree(best);
+                        best = JLI_StringDup(dp->d_name);
+                        best_offset = offset;
+                    }
+            }
+        }
+    } while (dp != NULL);
+    (void) closedir(dirp);
+    if (best == NULL)
+        return (NULL);
+    else {
+        ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2);
+        ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
+        JLI_MemFree(best);
+        return (ret_str);
+    }
+}
+
+/*
+ *      This is the global entry point. It examines the host for the optimal
+ *      JRE to be used by scanning a set of directories.  The set of directories
+ *      is platform dependent and can be overridden by the environment
+ *      variable JAVA_VERSION_PATH.
+ *
+ *      This routine itself simply determines the set of appropriate
+ *      directories before passing control onto ProcessDir().
+ */
+char*
+LocateJRE(manifest_info* info)
+{
+    char        *path;
+    char        *home;
+    char        *target = NULL;
+    char        *dp;
+    char        *cp;
+
+    /*
+     * Start by getting JAVA_VERSION_PATH
+     */
+    if (info->jre_restrict_search)
+        path = JLI_StringDup(system_dir);
+    else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
+        path = JLI_StringDup(path);
+    else
+        if ((home = getenv("HOME")) != NULL) {
+            path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) +
+                strlen(user_dir) + 2);
+            path = strcat(strcat(strcat(strcpy(path, home),
+                user_dir), ":"), system_dir);
+        } else
+            path = JLI_StringDup(system_dir);
+
+    /*
+     * Step through each directory on the path. Terminate the scan with
+     * the first directory with an acceptable JRE.
+     */
+    cp = dp = path;
+    while (dp != NULL) {
+        cp = strchr(dp, (int)':');
+        if (cp != NULL)
+            *cp = (char)NULL;
+        if ((target = ProcessDir(info, dp)) != NULL)
+            break;
+        dp = cp;
+        if (dp != NULL)
+            dp++;
+    }
+    JLI_MemFree(path);
+    return (target);
+}
+
+/*
+ * Given a path to a jre to execute, this routine checks if this process
+ * is indeed that jre.  If not, it exec's that jre.
+ *
+ * We want to actually check the paths rather than just the version string
+ * built into the executable, so that given version specification (and
+ * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
+ * of the version of the arbitrary launcher we start with.
+ */
+void
+ExecJRE(char *jre, char **argv)
+{
+    char    wanted[PATH_MAX];
+    char    *execname;
+    char    *progname;
+
+    /*
+     * Resolve the real path to the directory containing the selected JRE.
+     */
+    if (realpath(jre, wanted) == NULL) {
+        fprintf(stderr, "Unable to resolve %s\n", jre);
+        exit(1);
+    }
+
+    /*
+     * Resolve the real path to the currently running launcher.
+     */
+    execname = SetExecname(argv);
+    if (execname == NULL) {
+        fprintf(stderr, "Unable to resolve current executable\n");
+        exit(1);
+    }
+
+    /*
+     * If the path to the selected JRE directory is a match to the initial
+     * portion of the path to the currently executing JRE, we have a winner!
+     * If so, just return.
+     */
+    if (strncmp(wanted, execname, strlen(wanted)) == 0)
+        return;                 /* I am the droid you were looking for */
+
+    /*
+     * If this isn't the selected version, exec the selected version.
+     */
+#ifdef JAVA_ARGS  /* javac, jar and friends. */
+    progname = "java";
+#else             /* java, oldjava, javaw and friends */
+#ifdef PROGNAME
+    progname = PROGNAME;
+#else
+    progname = *argv;
+    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
+        progname = s + 1;
+    }
+#endif /* PROGNAME */
+#endif /* JAVA_ARGS */
+
+    /*
+     * This should never happen (because of the selection code in SelectJRE),
+     * but check for "impossibly" long path names just because buffer overruns
+     * can be so deadly.
+     */
+    if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) {
+        fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n");
+        exit(1);
+    }
+
+    /*
+     * Construct the path and exec it.
+     */
+    (void)strcat(strcat(wanted, "/bin/"), progname);
+    argv[0] = progname;
+    if (_launcher_debug) {
+        int i;
+        printf("ReExec Command: %s (%s)\n", wanted, argv[0]);
+        printf("ReExec Args:");
+        for (i = 1; argv[i] != NULL; i++)
+            printf(" %s", argv[i]);
+        printf("\n");
+    }
+    (void)fflush(stdout);
+    (void)fflush(stderr);
+    execv(wanted, argv);
+    perror("execv()");
+    fprintf(stderr, "Exec of %s failed\n", wanted);
+    exit(1);
+}
+
+/*
+ * "Borrowed" from Solaris 10 where the unsetenv() function is being added
+ * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
+ * such, in the fullness of time this will appear in libc on all relevant
+ * Solaris/Linux platforms and maybe even the Windows platform.  At that
+ * time, this stub can be removed.
+ *
+ * This implementation removes the environment locking for multithreaded
+ * applications.  (We don't have access to these mutexes within libc and
+ * the launcher isn't multithreaded.)  Note that what remains is platform
+ * independent, because it only relies on attributes that a POSIX environment
+ * defines.
+ *
+ * Returns 0 on success, -1 on failure.
+ *
+ * Also removed was the setting of errno.  The only value of errno set
+ * was EINVAL ("Invalid Argument").
+ */
+
+/*
+ * s1(environ) is name=value
+ * s2(name) is name(not the form of name=value).
+ * if names match, return value of 1, else return 0
+ */
+static int
+match_noeq(const char *s1, const char *s2)
+{
+        while (*s1 == *s2++) {
+                if (*s1++ == '=')
+                        return (1);
+        }
+        if (*s1 == '=' && s2[-1] == '\0')
+                return (1);
+        return (0);
+}
+
+/*
+ * added for SUSv3 standard
+ *
+ * Delete entry from environ.
+ * Do not free() memory!  Other threads may be using it.
+ * Keep it around forever.
+ */
+static int
+borrowed_unsetenv(const char *name)
+{
+        long    idx;            /* index into environ */
+
+        if (name == NULL || *name == '\0' ||
+            strchr(name, '=') != NULL) {
+                return (-1);
+        }
+
+        for (idx = 0; environ[idx] != NULL; idx++) {
+                if (match_noeq(environ[idx], name))
+                        break;
+        }
+        if (environ[idx] == NULL) {
+                /* name not found but still a success */
+                return (0);
+        }
+        /* squeeze up one entry */
+        do {
+                environ[idx] = environ[idx+1];
+        } while (environ[++idx] != NULL);
+
+        return (0);
+}
+/* --- End of "borrowed" code --- */
+
+/*
+ * Wrapper for unsetenv() function.
+ */
+int
+UnsetEnv(char *name)
+{
+    return(borrowed_unsetenv(name));
+}
+
+/* --- Splash Screen shared library support --- */
+
+static const char* SPLASHSCREEN_SO = "libsplashscreen.so";
+
+static void* hSplashLib = NULL;
+
+void* SplashProcAddress(const char* name) {
+    if (!hSplashLib) {
+        hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL);
+    }
+    if (hSplashLib) {
+        void* sym = dlsym(hSplashLib, name);
+        return sym;
+    } else {
+        return NULL;
+    }
+}
+
+void SplashFreeLibrary() {
+    if (hSplashLib) {
+        dlclose(hSplashLib);
+        hSplashLib = NULL;
+    }
+}
+
+const char *
+jlong_format_specifier() {
+    return "%lld";
+}
+
+/*
+ * Block current thread and continue execution in a new thread
+ */
+int
+ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args, int ret) {
+    int rslt;
+#ifdef __linux__
+    pthread_t tid;
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    if (stack_size > 0) {
+      pthread_attr_setstacksize(&attr, stack_size);
+    }
+
+    if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
+      void * tmp;
+      pthread_join(tid, &tmp);
+      rslt = (int)tmp;
+    } else {
+     /*
+      * Continue execution in current thread if for some reason (e.g. out of
+      * memory/LWP)  a new thread can't be created. This will likely fail
+      * later in continuation as JNI_CreateJavaVM needs to create quite a
+      * few new threads, anyway, just give it a try..
+      */
+      rslt = continuation(args);
+    }
+
+    pthread_attr_destroy(&attr);
+#else
+    thread_t tid;
+    long flags = 0;
+    if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) {
+      void * tmp;
+      thr_join(tid, NULL, &tmp);
+      rslt = (int)tmp;
+    } else {
+      /* See above. Continue in current thread if thr_create() failed */
+      rslt = continuation(args);
+    }
+#endif
+    /* If the caller has deemed there is an error we
+     * simply return that, otherwise we return the value of
+     * the callee
+     */
+    return (ret != 0) ? ret : rslt;
+}
+
+/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
+#define MAX_PID_STR_SZ   20
+
+void SetJavaLauncherPlatformProps() {
+   /* Linux only */
+#ifdef __linux__
+    const char *substr = "-Dsun.java.launcher.pid=";
+    char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1);
+    sprintf(pid_prop_str, "%s%d", substr, getpid());
+    AddOption(pid_prop_str, NULL);
+#endif
+}
Index: /tags/icedtea-web/beta/launcher/java_md.h
===================================================================
--- /tags/icedtea-web/beta/launcher/java_md.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/java_md.h	(revision 403)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1998, 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef JAVA_MD_H
+#define JAVA_MD_H
+
+#include <limits.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include "manifest_info.h"
+#include "jli_util.h"
+
+#define PATH_SEPARATOR          ':'
+#define FILESEP                 "/"
+#define FILE_SEPARATOR          '/'
+#define IS_FILE_SEPARATOR(c) ((c) == '/')
+#ifndef MAXNAMELEN
+#define MAXNAMELEN              PATH_MAX
+#endif
+
+#ifdef JAVA_ARGS
+/*
+ * ApplicationHome is prepended to each of these entries; the resulting
+ * strings are concatenated (separated by PATH_SEPARATOR) and used as the
+ * value of -cp option to the launcher.
+ */
+#ifndef APP_CLASSPATH
+#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
+#endif
+#endif
+
+#ifdef HAVE_GETHRTIME
+/*
+ * Support for doing cheap, accurate interval timing.
+ */
+#include <sys/time.h>
+#define CounterGet()              (gethrtime()/1000)
+#define Counter2Micros(counts)    (counts)
+#else
+#define CounterGet()              (0)
+#define Counter2Micros(counts)    (1)
+#endif /* HAVE_GETHRTIME */
+
+/*
+ * Function prototypes.
+ */
+char *LocateJRE(manifest_info *info);
+void ExecJRE(char *jre, char **argv);
+int UnsetEnv(char *name);
+
+#endif
Index: /tags/icedtea-web/beta/launcher/javaws.in
===================================================================
--- /tags/icedtea-web/beta/launcher/javaws.in	(revision 403)
+++ /tags/icedtea-web/beta/launcher/javaws.in	(revision 403)
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+JAVA=@JAVA@
+LAUNCHER_BOOTCLASSPATH=@LAUNCHER_BOOTCLASSPATH@
+LAUNCHER_FLAGS=-Xms8m
+CLASSNAME=net.sourceforge.jnlp.runtime.Boot
+BINARY_LOCATION=@JAVAWS_BIN_LOCATION@
+PROGRAM_NAME=javaws
+CP=@JRE@/lib/rt.jar
+
+JAVA_ARGS=
+ARGS=
+
+while [ "$#" -gt "0" ]; do
+  case "$1" in
+    -J*)
+      JAVA_ARGS="${JAVA_ARGS} ${1##-J}"
+      ;;
+    *)
+      ARGS="${ARGS} $1"
+      ;;
+  esac
+  shift
+done
+
+${JAVA} ${LAUNCHER_BOOTCLASSPATH} ${LAUNCHER_FLAGS} \
+  ${JAVA_ARGS} \
+  -classpath ${CP} \
+  -Dicedtea-web.bin.name=${PROGRAM_NAME} \
+  -Dicedtea-web.bin.location=${BINARY_LOCATION} \
+  ${CLASSNAME} \
+  ${ARGS}
+
+exit $?
Index: /tags/icedtea-web/beta/launcher/jli_util.c
===================================================================
--- /tags/icedtea-web/beta/launcher/jli_util.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jli_util.c	(revision 403)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2005, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jli_util.h"
+
+/*
+ * Returns a pointer to a block of at least 'size' bytes of memory.
+ * Prints error message and exits if the memory could not be allocated.
+ */
+void *
+JLI_MemAlloc(size_t size)
+{
+    void *p = malloc(size);
+    if (p == 0) {
+        perror("malloc");
+        exit(1);
+    }
+    return p;
+}
+
+/*
+ * Equivalent to realloc(size).
+ * Prints error message and exits if the memory could not be reallocated.
+ */
+void *
+JLI_MemRealloc(void *ptr, size_t size)
+{
+    void *p = realloc(ptr, size);
+    if (p == 0) {
+        perror("realloc");
+        exit(1);
+    }
+    return p;
+}
+
+/*
+ * Wrapper over strdup(3C) which prints an error message and exits if memory
+ * could not be allocated.
+ */
+char *
+JLI_StringDup(const char *s1)
+{
+    char *s = strdup(s1);
+    if (s == NULL) {
+        perror("strdup");
+        exit(1);
+    }
+    return s;
+}
+
+/*
+ * Very equivalent to free(ptr).
+ * Here to maintain pairing with the above routines.
+ */
+void
+JLI_MemFree(void *ptr)
+{
+    free(ptr);
+}
Index: /tags/icedtea-web/beta/launcher/jli_util.h
===================================================================
--- /tags/icedtea-web/beta/launcher/jli_util.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jli_util.h	(revision 403)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _JLI_UTIL_H
+#define _JLI_UTIL_H
+
+#include <stdlib.h>
+
+void *JLI_MemAlloc(size_t size);
+void *JLI_MemRealloc(void *ptr, size_t size);
+char *JLI_StringDup(const char *s1);
+void  JLI_MemFree(void *ptr);
+
+#endif  /* _JLI_UTIL_H */
Index: /tags/icedtea-web/beta/launcher/jni.h
===================================================================
--- /tags/icedtea-web/beta/launcher/jni.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jni.h	(revision 403)
@@ -0,0 +1,1959 @@
+/*
+ * Copyright (c) 1996, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+   and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char   jboolean;
+typedef unsigned short  jchar;
+typedef short           jshort;
+typedef float           jfloat;
+typedef double          jdouble;
+
+typedef jint            jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+    jboolean z;
+    jbyte    b;
+    jchar    c;
+    jshort   s;
+    jint     i;
+    jlong    j;
+    jfloat   f;
+    jdouble  d;
+    jobject  l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+     JNIInvalidRefType    = 0,
+     JNILocalRefType      = 1,
+     JNIGlobalRefType     = 2,
+     JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK           0                 /* success */
+#define JNI_ERR          (-1)              /* unknown error */
+#define JNI_EDETACHED    (-2)              /* thread detached from the VM */
+#define JNI_EVERSION     (-3)              /* JNI version error */
+#define JNI_ENOMEM       (-4)              /* not enough memory */
+#define JNI_EEXIST       (-5)              /* VM already created */
+#define JNI_EINVAL       (-6)              /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+    char *name;
+    char *signature;
+    void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
+
+    void *reserved3;
+    jint (JNICALL *GetVersion)(JNIEnv *env);
+
+    jclass (JNICALL *DefineClass)
+      (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+       jsize len);
+    jclass (JNICALL *FindClass)
+      (JNIEnv *env, const char *name);
+
+    jmethodID (JNICALL *FromReflectedMethod)
+      (JNIEnv *env, jobject method);
+    jfieldID (JNICALL *FromReflectedField)
+      (JNIEnv *env, jobject field);
+
+    jobject (JNICALL *ToReflectedMethod)
+      (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+    jclass (JNICALL *GetSuperclass)
+      (JNIEnv *env, jclass sub);
+    jboolean (JNICALL *IsAssignableFrom)
+      (JNIEnv *env, jclass sub, jclass sup);
+
+    jobject (JNICALL *ToReflectedField)
+      (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+    jint (JNICALL *Throw)
+      (JNIEnv *env, jthrowable obj);
+    jint (JNICALL *ThrowNew)
+      (JNIEnv *env, jclass clazz, const char *msg);
+    jthrowable (JNICALL *ExceptionOccurred)
+      (JNIEnv *env);
+    void (JNICALL *ExceptionDescribe)
+      (JNIEnv *env);
+    void (JNICALL *ExceptionClear)
+      (JNIEnv *env);
+    void (JNICALL *FatalError)
+      (JNIEnv *env, const char *msg);
+
+    jint (JNICALL *PushLocalFrame)
+      (JNIEnv *env, jint capacity);
+    jobject (JNICALL *PopLocalFrame)
+      (JNIEnv *env, jobject result);
+
+    jobject (JNICALL *NewGlobalRef)
+      (JNIEnv *env, jobject lobj);
+    void (JNICALL *DeleteGlobalRef)
+      (JNIEnv *env, jobject gref);
+    void (JNICALL *DeleteLocalRef)
+      (JNIEnv *env, jobject obj);
+    jboolean (JNICALL *IsSameObject)
+      (JNIEnv *env, jobject obj1, jobject obj2);
+    jobject (JNICALL *NewLocalRef)
+      (JNIEnv *env, jobject ref);
+    jint (JNICALL *EnsureLocalCapacity)
+      (JNIEnv *env, jint capacity);
+
+    jobject (JNICALL *AllocObject)
+      (JNIEnv *env, jclass clazz);
+    jobject (JNICALL *NewObject)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *NewObjectV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jobject (JNICALL *NewObjectA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jclass (JNICALL *GetObjectClass)
+      (JNIEnv *env, jobject obj);
+    jboolean (JNICALL *IsInstanceOf)
+      (JNIEnv *env, jobject obj, jclass clazz);
+
+    jmethodID (JNICALL *GetMethodID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *CallObjectMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jobject (JNICALL *CallObjectMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jobject (JNICALL *CallObjectMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jboolean (JNICALL *CallBooleanMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jboolean (JNICALL *CallBooleanMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jboolean (JNICALL *CallBooleanMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jbyte (JNICALL *CallByteMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jbyte (JNICALL *CallByteMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jbyte (JNICALL *CallByteMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jchar (JNICALL *CallCharMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jchar (JNICALL *CallCharMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jchar (JNICALL *CallCharMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jshort (JNICALL *CallShortMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jshort (JNICALL *CallShortMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jshort (JNICALL *CallShortMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jint (JNICALL *CallIntMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jint (JNICALL *CallIntMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jint (JNICALL *CallIntMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jlong (JNICALL *CallLongMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jlong (JNICALL *CallLongMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jlong (JNICALL *CallLongMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jfloat (JNICALL *CallFloatMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jfloat (JNICALL *CallFloatMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jfloat (JNICALL *CallFloatMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    jdouble (JNICALL *CallDoubleMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    jdouble (JNICALL *CallDoubleMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    jdouble (JNICALL *CallDoubleMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+    void (JNICALL *CallVoidMethod)
+      (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+    void (JNICALL *CallVoidMethodV)
+      (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+    void (JNICALL *CallVoidMethodA)
+      (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+    jobject (JNICALL *CallNonvirtualObjectMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *CallNonvirtualObjectMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jobject (JNICALL *CallNonvirtualObjectMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jboolean (JNICALL *CallNonvirtualBooleanMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jbyte (JNICALL *CallNonvirtualByteMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jbyte (JNICALL *CallNonvirtualByteMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jbyte (JNICALL *CallNonvirtualByteMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jchar (JNICALL *CallNonvirtualCharMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jchar (JNICALL *CallNonvirtualCharMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jchar (JNICALL *CallNonvirtualCharMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jshort (JNICALL *CallNonvirtualShortMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jshort (JNICALL *CallNonvirtualShortMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jshort (JNICALL *CallNonvirtualShortMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jint (JNICALL *CallNonvirtualIntMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jint (JNICALL *CallNonvirtualIntMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jint (JNICALL *CallNonvirtualIntMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jlong (JNICALL *CallNonvirtualLongMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jlong (JNICALL *CallNonvirtualLongMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jlong (JNICALL *CallNonvirtualLongMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jfloat (JNICALL *CallNonvirtualFloatMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jfloat (JNICALL *CallNonvirtualFloatMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jfloat (JNICALL *CallNonvirtualFloatMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    jdouble (JNICALL *CallNonvirtualDoubleMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue *args);
+
+    void (JNICALL *CallNonvirtualVoidMethod)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+    void (JNICALL *CallNonvirtualVoidMethodV)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       va_list args);
+    void (JNICALL *CallNonvirtualVoidMethodA)
+      (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+       const jvalue * args);
+
+    jfieldID (JNICALL *GetFieldID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *GetObjectField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jboolean (JNICALL *GetBooleanField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jbyte (JNICALL *GetByteField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jchar (JNICALL *GetCharField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jshort (JNICALL *GetShortField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jint (JNICALL *GetIntField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jlong (JNICALL *GetLongField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jfloat (JNICALL *GetFloatField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+    jdouble (JNICALL *GetDoubleField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+    void (JNICALL *SetObjectField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+    void (JNICALL *SetBooleanField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+    void (JNICALL *SetByteField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+    void (JNICALL *SetCharField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+    void (JNICALL *SetShortField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+    void (JNICALL *SetIntField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+    void (JNICALL *SetLongField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+    void (JNICALL *SetFloatField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+    void (JNICALL *SetDoubleField)
+      (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+    jmethodID (JNICALL *GetStaticMethodID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+    jobject (JNICALL *CallStaticObjectMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jobject (JNICALL *CallStaticObjectMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jobject (JNICALL *CallStaticObjectMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jboolean (JNICALL *CallStaticBooleanMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jboolean (JNICALL *CallStaticBooleanMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jboolean (JNICALL *CallStaticBooleanMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jbyte (JNICALL *CallStaticByteMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jbyte (JNICALL *CallStaticByteMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jbyte (JNICALL *CallStaticByteMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jchar (JNICALL *CallStaticCharMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jchar (JNICALL *CallStaticCharMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jchar (JNICALL *CallStaticCharMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jshort (JNICALL *CallStaticShortMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jshort (JNICALL *CallStaticShortMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jshort (JNICALL *CallStaticShortMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jint (JNICALL *CallStaticIntMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jint (JNICALL *CallStaticIntMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jint (JNICALL *CallStaticIntMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jlong (JNICALL *CallStaticLongMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jlong (JNICALL *CallStaticLongMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jlong (JNICALL *CallStaticLongMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jfloat (JNICALL *CallStaticFloatMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jfloat (JNICALL *CallStaticFloatMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jfloat (JNICALL *CallStaticFloatMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    jdouble (JNICALL *CallStaticDoubleMethod)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+    jdouble (JNICALL *CallStaticDoubleMethodV)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+    jdouble (JNICALL *CallStaticDoubleMethodA)
+      (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+    void (JNICALL *CallStaticVoidMethod)
+      (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+    void (JNICALL *CallStaticVoidMethodV)
+      (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+    void (JNICALL *CallStaticVoidMethodA)
+      (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+    jfieldID (JNICALL *GetStaticFieldID)
+      (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+    jobject (JNICALL *GetStaticObjectField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jboolean (JNICALL *GetStaticBooleanField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jbyte (JNICALL *GetStaticByteField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jchar (JNICALL *GetStaticCharField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jshort (JNICALL *GetStaticShortField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jint (JNICALL *GetStaticIntField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jlong (JNICALL *GetStaticLongField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jfloat (JNICALL *GetStaticFloatField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+    jdouble (JNICALL *GetStaticDoubleField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+    void (JNICALL *SetStaticObjectField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+    void (JNICALL *SetStaticBooleanField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+    void (JNICALL *SetStaticByteField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+    void (JNICALL *SetStaticCharField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+    void (JNICALL *SetStaticShortField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+    void (JNICALL *SetStaticIntField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+    void (JNICALL *SetStaticLongField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+    void (JNICALL *SetStaticFloatField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+    void (JNICALL *SetStaticDoubleField)
+      (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+    jstring (JNICALL *NewString)
+      (JNIEnv *env, const jchar *unicode, jsize len);
+    jsize (JNICALL *GetStringLength)
+      (JNIEnv *env, jstring str);
+    const jchar *(JNICALL *GetStringChars)
+      (JNIEnv *env, jstring str, jboolean *isCopy);
+    void (JNICALL *ReleaseStringChars)
+      (JNIEnv *env, jstring str, const jchar *chars);
+
+    jstring (JNICALL *NewStringUTF)
+      (JNIEnv *env, const char *utf);
+    jsize (JNICALL *GetStringUTFLength)
+      (JNIEnv *env, jstring str);
+    const char* (JNICALL *GetStringUTFChars)
+      (JNIEnv *env, jstring str, jboolean *isCopy);
+    void (JNICALL *ReleaseStringUTFChars)
+      (JNIEnv *env, jstring str, const char* chars);
+
+
+    jsize (JNICALL *GetArrayLength)
+      (JNIEnv *env, jarray array);
+
+    jobjectArray (JNICALL *NewObjectArray)
+      (JNIEnv *env, jsize len, jclass clazz, jobject init);
+    jobject (JNICALL *GetObjectArrayElement)
+      (JNIEnv *env, jobjectArray array, jsize index);
+    void (JNICALL *SetObjectArrayElement)
+      (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+    jbooleanArray (JNICALL *NewBooleanArray)
+      (JNIEnv *env, jsize len);
+    jbyteArray (JNICALL *NewByteArray)
+      (JNIEnv *env, jsize len);
+    jcharArray (JNICALL *NewCharArray)
+      (JNIEnv *env, jsize len);
+    jshortArray (JNICALL *NewShortArray)
+      (JNIEnv *env, jsize len);
+    jintArray (JNICALL *NewIntArray)
+      (JNIEnv *env, jsize len);
+    jlongArray (JNICALL *NewLongArray)
+      (JNIEnv *env, jsize len);
+    jfloatArray (JNICALL *NewFloatArray)
+      (JNIEnv *env, jsize len);
+    jdoubleArray (JNICALL *NewDoubleArray)
+      (JNIEnv *env, jsize len);
+
+    jboolean * (JNICALL *GetBooleanArrayElements)
+      (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+    jbyte * (JNICALL *GetByteArrayElements)
+      (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+    jchar * (JNICALL *GetCharArrayElements)
+      (JNIEnv *env, jcharArray array, jboolean *isCopy);
+    jshort * (JNICALL *GetShortArrayElements)
+      (JNIEnv *env, jshortArray array, jboolean *isCopy);
+    jint * (JNICALL *GetIntArrayElements)
+      (JNIEnv *env, jintArray array, jboolean *isCopy);
+    jlong * (JNICALL *GetLongArrayElements)
+      (JNIEnv *env, jlongArray array, jboolean *isCopy);
+    jfloat * (JNICALL *GetFloatArrayElements)
+      (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+    jdouble * (JNICALL *GetDoubleArrayElements)
+      (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+    void (JNICALL *ReleaseBooleanArrayElements)
+      (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+    void (JNICALL *ReleaseByteArrayElements)
+      (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+    void (JNICALL *ReleaseCharArrayElements)
+      (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+    void (JNICALL *ReleaseShortArrayElements)
+      (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+    void (JNICALL *ReleaseIntArrayElements)
+      (JNIEnv *env, jintArray array, jint *elems, jint mode);
+    void (JNICALL *ReleaseLongArrayElements)
+      (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+    void (JNICALL *ReleaseFloatArrayElements)
+      (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+    void (JNICALL *ReleaseDoubleArrayElements)
+      (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+    void (JNICALL *GetBooleanArrayRegion)
+      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+    void (JNICALL *GetByteArrayRegion)
+      (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+    void (JNICALL *GetCharArrayRegion)
+      (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+    void (JNICALL *GetShortArrayRegion)
+      (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+    void (JNICALL *GetIntArrayRegion)
+      (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+    void (JNICALL *GetLongArrayRegion)
+      (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+    void (JNICALL *GetFloatArrayRegion)
+      (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+    void (JNICALL *GetDoubleArrayRegion)
+      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+    void (JNICALL *SetBooleanArrayRegion)
+      (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+    void (JNICALL *SetByteArrayRegion)
+      (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+    void (JNICALL *SetCharArrayRegion)
+      (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+    void (JNICALL *SetShortArrayRegion)
+      (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+    void (JNICALL *SetIntArrayRegion)
+      (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+    void (JNICALL *SetLongArrayRegion)
+      (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+    void (JNICALL *SetFloatArrayRegion)
+      (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+    void (JNICALL *SetDoubleArrayRegion)
+      (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+    jint (JNICALL *RegisterNatives)
+      (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+       jint nMethods);
+    jint (JNICALL *UnregisterNatives)
+      (JNIEnv *env, jclass clazz);
+
+    jint (JNICALL *MonitorEnter)
+      (JNIEnv *env, jobject obj);
+    jint (JNICALL *MonitorExit)
+      (JNIEnv *env, jobject obj);
+
+    jint (JNICALL *GetJavaVM)
+      (JNIEnv *env, JavaVM **vm);
+
+    void (JNICALL *GetStringRegion)
+      (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+    void (JNICALL *GetStringUTFRegion)
+      (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+    void * (JNICALL *GetPrimitiveArrayCritical)
+      (JNIEnv *env, jarray array, jboolean *isCopy);
+    void (JNICALL *ReleasePrimitiveArrayCritical)
+      (JNIEnv *env, jarray array, void *carray, jint mode);
+
+    const jchar * (JNICALL *GetStringCritical)
+      (JNIEnv *env, jstring string, jboolean *isCopy);
+    void (JNICALL *ReleaseStringCritical)
+      (JNIEnv *env, jstring string, const jchar *cstring);
+
+    jweak (JNICALL *NewWeakGlobalRef)
+       (JNIEnv *env, jobject obj);
+    void (JNICALL *DeleteWeakGlobalRef)
+       (JNIEnv *env, jweak ref);
+
+    jboolean (JNICALL *ExceptionCheck)
+       (JNIEnv *env);
+
+    jobject (JNICALL *NewDirectByteBuffer)
+       (JNIEnv* env, void* address, jlong capacity);
+    void* (JNICALL *GetDirectBufferAddress)
+       (JNIEnv* env, jobject buf);
+    jlong (JNICALL *GetDirectBufferCapacity)
+       (JNIEnv* env, jobject buf);
+
+    /* New JNI 1.6 Features */
+
+    jobjectRefType (JNICALL *GetObjectRefType)
+        (JNIEnv* env, jobject obj);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ *    env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ *    (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+    const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+    jint GetVersion() {
+        return functions->GetVersion(this);
+    }
+    jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+                       jsize len) {
+        return functions->DefineClass(this, name, loader, buf, len);
+    }
+    jclass FindClass(const char *name) {
+        return functions->FindClass(this, name);
+    }
+    jmethodID FromReflectedMethod(jobject method) {
+        return functions->FromReflectedMethod(this,method);
+    }
+    jfieldID FromReflectedField(jobject field) {
+        return functions->FromReflectedField(this,field);
+    }
+
+    jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+        return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+    }
+
+    jclass GetSuperclass(jclass sub) {
+        return functions->GetSuperclass(this, sub);
+    }
+    jboolean IsAssignableFrom(jclass sub, jclass sup) {
+        return functions->IsAssignableFrom(this, sub, sup);
+    }
+
+    jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+        return functions->ToReflectedField(this,cls,fieldID,isStatic);
+    }
+
+    jint Throw(jthrowable obj) {
+        return functions->Throw(this, obj);
+    }
+    jint ThrowNew(jclass clazz, const char *msg) {
+        return functions->ThrowNew(this, clazz, msg);
+    }
+    jthrowable ExceptionOccurred() {
+        return functions->ExceptionOccurred(this);
+    }
+    void ExceptionDescribe() {
+        functions->ExceptionDescribe(this);
+    }
+    void ExceptionClear() {
+        functions->ExceptionClear(this);
+    }
+    void FatalError(const char *msg) {
+        functions->FatalError(this, msg);
+    }
+
+    jint PushLocalFrame(jint capacity) {
+        return functions->PushLocalFrame(this,capacity);
+    }
+    jobject PopLocalFrame(jobject result) {
+        return functions->PopLocalFrame(this,result);
+    }
+
+    jobject NewGlobalRef(jobject lobj) {
+        return functions->NewGlobalRef(this,lobj);
+    }
+    void DeleteGlobalRef(jobject gref) {
+        functions->DeleteGlobalRef(this,gref);
+    }
+    void DeleteLocalRef(jobject obj) {
+        functions->DeleteLocalRef(this, obj);
+    }
+
+    jboolean IsSameObject(jobject obj1, jobject obj2) {
+        return functions->IsSameObject(this,obj1,obj2);
+    }
+
+    jobject NewLocalRef(jobject ref) {
+        return functions->NewLocalRef(this,ref);
+    }
+    jint EnsureLocalCapacity(jint capacity) {
+        return functions->EnsureLocalCapacity(this,capacity);
+    }
+
+    jobject AllocObject(jclass clazz) {
+        return functions->AllocObject(this,clazz);
+    }
+    jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+        va_list args;
+        jobject result;
+        va_start(args, methodID);
+        result = functions->NewObjectV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jobject NewObjectV(jclass clazz, jmethodID methodID,
+                       va_list args) {
+        return functions->NewObjectV(this,clazz,methodID,args);
+    }
+    jobject NewObjectA(jclass clazz, jmethodID methodID,
+                       const jvalue *args) {
+        return functions->NewObjectA(this,clazz,methodID,args);
+    }
+
+    jclass GetObjectClass(jobject obj) {
+        return functions->GetObjectClass(this,obj);
+    }
+    jboolean IsInstanceOf(jobject obj, jclass clazz) {
+        return functions->IsInstanceOf(this,obj,clazz);
+    }
+
+    jmethodID GetMethodID(jclass clazz, const char *name,
+                          const char *sig) {
+        return functions->GetMethodID(this,clazz,name,sig);
+    }
+
+    jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jobject result;
+        va_start(args,methodID);
+        result = functions->CallObjectMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+                        va_list args) {
+        return functions->CallObjectMethodV(this,obj,methodID,args);
+    }
+    jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+                        const jvalue * args) {
+        return functions->CallObjectMethodA(this,obj,methodID,args);
+    }
+
+    jboolean CallBooleanMethod(jobject obj,
+                               jmethodID methodID, ...) {
+        va_list args;
+        jboolean result;
+        va_start(args,methodID);
+        result = functions->CallBooleanMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+                                va_list args) {
+        return functions->CallBooleanMethodV(this,obj,methodID,args);
+    }
+    jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+                                const jvalue * args) {
+        return functions->CallBooleanMethodA(this,obj,methodID, args);
+    }
+
+    jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jbyte result;
+        va_start(args,methodID);
+        result = functions->CallByteMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+                          va_list args) {
+        return functions->CallByteMethodV(this,obj,methodID,args);
+    }
+    jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+                          const jvalue * args) {
+        return functions->CallByteMethodA(this,obj,methodID,args);
+    }
+
+    jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jchar result;
+        va_start(args,methodID);
+        result = functions->CallCharMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jchar CallCharMethodV(jobject obj, jmethodID methodID,
+                          va_list args) {
+        return functions->CallCharMethodV(this,obj,methodID,args);
+    }
+    jchar CallCharMethodA(jobject obj, jmethodID methodID,
+                          const jvalue * args) {
+        return functions->CallCharMethodA(this,obj,methodID,args);
+    }
+
+    jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jshort result;
+        va_start(args,methodID);
+        result = functions->CallShortMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jshort CallShortMethodV(jobject obj, jmethodID methodID,
+                            va_list args) {
+        return functions->CallShortMethodV(this,obj,methodID,args);
+    }
+    jshort CallShortMethodA(jobject obj, jmethodID methodID,
+                            const jvalue * args) {
+        return functions->CallShortMethodA(this,obj,methodID,args);
+    }
+
+    jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jint result;
+        va_start(args,methodID);
+        result = functions->CallIntMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jint CallIntMethodV(jobject obj, jmethodID methodID,
+                        va_list args) {
+        return functions->CallIntMethodV(this,obj,methodID,args);
+    }
+    jint CallIntMethodA(jobject obj, jmethodID methodID,
+                        const jvalue * args) {
+        return functions->CallIntMethodA(this,obj,methodID,args);
+    }
+
+    jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jlong result;
+        va_start(args,methodID);
+        result = functions->CallLongMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jlong CallLongMethodV(jobject obj, jmethodID methodID,
+                          va_list args) {
+        return functions->CallLongMethodV(this,obj,methodID,args);
+    }
+    jlong CallLongMethodA(jobject obj, jmethodID methodID,
+                          const jvalue * args) {
+        return functions->CallLongMethodA(this,obj,methodID,args);
+    }
+
+    jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jfloat result;
+        va_start(args,methodID);
+        result = functions->CallFloatMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+                            va_list args) {
+        return functions->CallFloatMethodV(this,obj,methodID,args);
+    }
+    jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+                            const jvalue * args) {
+        return functions->CallFloatMethodA(this,obj,methodID,args);
+    }
+
+    jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        jdouble result;
+        va_start(args,methodID);
+        result = functions->CallDoubleMethodV(this,obj,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+                        va_list args) {
+        return functions->CallDoubleMethodV(this,obj,methodID,args);
+    }
+    jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+                        const jvalue * args) {
+        return functions->CallDoubleMethodA(this,obj,methodID,args);
+    }
+
+    void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+        va_list args;
+        va_start(args,methodID);
+        functions->CallVoidMethodV(this,obj,methodID,args);
+        va_end(args);
+    }
+    void CallVoidMethodV(jobject obj, jmethodID methodID,
+                         va_list args) {
+        functions->CallVoidMethodV(this,obj,methodID,args);
+    }
+    void CallVoidMethodA(jobject obj, jmethodID methodID,
+                         const jvalue * args) {
+        functions->CallVoidMethodA(this,obj,methodID,args);
+    }
+
+    jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+                                       jmethodID methodID, ...) {
+        va_list args;
+        jobject result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+                                                        methodID,args);
+        va_end(args);
+        return result;
+    }
+    jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+                                        jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+                                                      methodID,args);
+    }
+    jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+                                        jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+                                                      methodID,args);
+    }
+
+    jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+                                         jmethodID methodID, ...) {
+        va_list args;
+        jboolean result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+                                                         methodID,args);
+        va_end(args);
+        return result;
+    }
+    jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+                                          jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+                                                       methodID,args);
+    }
+    jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+                                          jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+                                                       methodID, args);
+    }
+
+    jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+                                   jmethodID methodID, ...) {
+        va_list args;
+        jbyte result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+                                                      methodID,args);
+        va_end(args);
+        return result;
+    }
+    jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+                                    jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+                                                    methodID,args);
+    }
+    jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+                                    jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+                                                    methodID,args);
+    }
+
+    jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+                                   jmethodID methodID, ...) {
+        va_list args;
+        jchar result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+                                                      methodID,args);
+        va_end(args);
+        return result;
+    }
+    jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+                                    jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+                                                    methodID,args);
+    }
+    jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+                                    jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+                                                    methodID,args);
+    }
+
+    jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+                                     jmethodID methodID, ...) {
+        va_list args;
+        jshort result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+                                                       methodID,args);
+        va_end(args);
+        return result;
+    }
+    jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+                                      jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+                                                     methodID,args);
+    }
+    jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+                                      jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+                                                     methodID,args);
+    }
+
+    jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+                                 jmethodID methodID, ...) {
+        va_list args;
+        jint result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+                                                     methodID,args);
+        va_end(args);
+        return result;
+    }
+    jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+                                  jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+                                                   methodID,args);
+    }
+    jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+                                  jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+                                                   methodID,args);
+    }
+
+    jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+                                   jmethodID methodID, ...) {
+        va_list args;
+        jlong result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+                                                      methodID,args);
+        va_end(args);
+        return result;
+    }
+    jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+                                    jmethodID methodID, va_list args) {
+        return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+                                                    methodID,args);
+    }
+    jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+                                    jmethodID methodID, const jvalue * args) {
+        return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+                                                    methodID,args);
+    }
+
+    jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+                                     jmethodID methodID, ...) {
+        va_list args;
+        jfloat result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+                                                       methodID,args);
+        va_end(args);
+        return result;
+    }
+    jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+                                      jmethodID methodID,
+                                      va_list args) {
+        return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+                                                     methodID,args);
+    }
+    jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+                                      jmethodID methodID,
+                                      const jvalue * args) {
+        return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+                                                     methodID,args);
+    }
+
+    jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+                                       jmethodID methodID, ...) {
+        va_list args;
+        jdouble result;
+        va_start(args,methodID);
+        result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+                                                        methodID,args);
+        va_end(args);
+        return result;
+    }
+    jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+                                        jmethodID methodID,
+                                        va_list args) {
+        return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+                                                      methodID,args);
+    }
+    jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+                                        jmethodID methodID,
+                                        const jvalue * args) {
+        return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+                                                      methodID,args);
+    }
+
+    void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+                                  jmethodID methodID, ...) {
+        va_list args;
+        va_start(args,methodID);
+        functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+        va_end(args);
+    }
+    void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+                                   jmethodID methodID,
+                                   va_list args) {
+        functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+    }
+    void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+                                   jmethodID methodID,
+                                   const jvalue * args) {
+        functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+    }
+
+    jfieldID GetFieldID(jclass clazz, const char *name,
+                        const char *sig) {
+        return functions->GetFieldID(this,clazz,name,sig);
+    }
+
+    jobject GetObjectField(jobject obj, jfieldID fieldID) {
+        return functions->GetObjectField(this,obj,fieldID);
+    }
+    jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+        return functions->GetBooleanField(this,obj,fieldID);
+    }
+    jbyte GetByteField(jobject obj, jfieldID fieldID) {
+        return functions->GetByteField(this,obj,fieldID);
+    }
+    jchar GetCharField(jobject obj, jfieldID fieldID) {
+        return functions->GetCharField(this,obj,fieldID);
+    }
+    jshort GetShortField(jobject obj, jfieldID fieldID) {
+        return functions->GetShortField(this,obj,fieldID);
+    }
+    jint GetIntField(jobject obj, jfieldID fieldID) {
+        return functions->GetIntField(this,obj,fieldID);
+    }
+    jlong GetLongField(jobject obj, jfieldID fieldID) {
+        return functions->GetLongField(this,obj,fieldID);
+    }
+    jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+        return functions->GetFloatField(this,obj,fieldID);
+    }
+    jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+        return functions->GetDoubleField(this,obj,fieldID);
+    }
+
+    void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+        functions->SetObjectField(this,obj,fieldID,val);
+    }
+    void SetBooleanField(jobject obj, jfieldID fieldID,
+                         jboolean val) {
+        functions->SetBooleanField(this,obj,fieldID,val);
+    }
+    void SetByteField(jobject obj, jfieldID fieldID,
+                      jbyte val) {
+        functions->SetByteField(this,obj,fieldID,val);
+    }
+    void SetCharField(jobject obj, jfieldID fieldID,
+                      jchar val) {
+        functions->SetCharField(this,obj,fieldID,val);
+    }
+    void SetShortField(jobject obj, jfieldID fieldID,
+                       jshort val) {
+        functions->SetShortField(this,obj,fieldID,val);
+    }
+    void SetIntField(jobject obj, jfieldID fieldID,
+                     jint val) {
+        functions->SetIntField(this,obj,fieldID,val);
+    }
+    void SetLongField(jobject obj, jfieldID fieldID,
+                      jlong val) {
+        functions->SetLongField(this,obj,fieldID,val);
+    }
+    void SetFloatField(jobject obj, jfieldID fieldID,
+                       jfloat val) {
+        functions->SetFloatField(this,obj,fieldID,val);
+    }
+    void SetDoubleField(jobject obj, jfieldID fieldID,
+                        jdouble val) {
+        functions->SetDoubleField(this,obj,fieldID,val);
+    }
+
+    jmethodID GetStaticMethodID(jclass clazz, const char *name,
+                                const char *sig) {
+        return functions->GetStaticMethodID(this,clazz,name,sig);
+    }
+
+    jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+                             ...) {
+        va_list args;
+        jobject result;
+        va_start(args,methodID);
+        result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+                              va_list args) {
+        return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+    }
+    jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+                              const jvalue *args) {
+        return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+    }
+
+    jboolean CallStaticBooleanMethod(jclass clazz,
+                                     jmethodID methodID, ...) {
+        va_list args;
+        jboolean result;
+        va_start(args,methodID);
+        result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jboolean CallStaticBooleanMethodV(jclass clazz,
+                                      jmethodID methodID, va_list args) {
+        return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+    }
+    jboolean CallStaticBooleanMethodA(jclass clazz,
+                                      jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+    }
+
+    jbyte CallStaticByteMethod(jclass clazz,
+                               jmethodID methodID, ...) {
+        va_list args;
+        jbyte result;
+        va_start(args,methodID);
+        result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jbyte CallStaticByteMethodV(jclass clazz,
+                                jmethodID methodID, va_list args) {
+        return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+    }
+    jbyte CallStaticByteMethodA(jclass clazz,
+                                jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+    }
+
+    jchar CallStaticCharMethod(jclass clazz,
+                               jmethodID methodID, ...) {
+        va_list args;
+        jchar result;
+        va_start(args,methodID);
+        result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jchar CallStaticCharMethodV(jclass clazz,
+                                jmethodID methodID, va_list args) {
+        return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+    }
+    jchar CallStaticCharMethodA(jclass clazz,
+                                jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+    }
+
+    jshort CallStaticShortMethod(jclass clazz,
+                                 jmethodID methodID, ...) {
+        va_list args;
+        jshort result;
+        va_start(args,methodID);
+        result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jshort CallStaticShortMethodV(jclass clazz,
+                                  jmethodID methodID, va_list args) {
+        return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+    }
+    jshort CallStaticShortMethodA(jclass clazz,
+                                  jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+    }
+
+    jint CallStaticIntMethod(jclass clazz,
+                             jmethodID methodID, ...) {
+        va_list args;
+        jint result;
+        va_start(args,methodID);
+        result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jint CallStaticIntMethodV(jclass clazz,
+                              jmethodID methodID, va_list args) {
+        return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+    }
+    jint CallStaticIntMethodA(jclass clazz,
+                              jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+    }
+
+    jlong CallStaticLongMethod(jclass clazz,
+                               jmethodID methodID, ...) {
+        va_list args;
+        jlong result;
+        va_start(args,methodID);
+        result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jlong CallStaticLongMethodV(jclass clazz,
+                                jmethodID methodID, va_list args) {
+        return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+    }
+    jlong CallStaticLongMethodA(jclass clazz,
+                                jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+    }
+
+    jfloat CallStaticFloatMethod(jclass clazz,
+                                 jmethodID methodID, ...) {
+        va_list args;
+        jfloat result;
+        va_start(args,methodID);
+        result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jfloat CallStaticFloatMethodV(jclass clazz,
+                                  jmethodID methodID, va_list args) {
+        return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+    }
+    jfloat CallStaticFloatMethodA(jclass clazz,
+                                  jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+    }
+
+    jdouble CallStaticDoubleMethod(jclass clazz,
+                                   jmethodID methodID, ...) {
+        va_list args;
+        jdouble result;
+        va_start(args,methodID);
+        result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+        va_end(args);
+        return result;
+    }
+    jdouble CallStaticDoubleMethodV(jclass clazz,
+                                    jmethodID methodID, va_list args) {
+        return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+    }
+    jdouble CallStaticDoubleMethodA(jclass clazz,
+                                    jmethodID methodID, const jvalue *args) {
+        return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+    }
+
+    void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+        va_list args;
+        va_start(args,methodID);
+        functions->CallStaticVoidMethodV(this,cls,methodID,args);
+        va_end(args);
+    }
+    void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+                               va_list args) {
+        functions->CallStaticVoidMethodV(this,cls,methodID,args);
+    }
+    void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+                               const jvalue * args) {
+        functions->CallStaticVoidMethodA(this,cls,methodID,args);
+    }
+
+    jfieldID GetStaticFieldID(jclass clazz, const char *name,
+                              const char *sig) {
+        return functions->GetStaticFieldID(this,clazz,name,sig);
+    }
+    jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticObjectField(this,clazz,fieldID);
+    }
+    jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticBooleanField(this,clazz,fieldID);
+    }
+    jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticByteField(this,clazz,fieldID);
+    }
+    jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticCharField(this,clazz,fieldID);
+    }
+    jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticShortField(this,clazz,fieldID);
+    }
+    jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticIntField(this,clazz,fieldID);
+    }
+    jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticLongField(this,clazz,fieldID);
+    }
+    jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticFloatField(this,clazz,fieldID);
+    }
+    jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+        return functions->GetStaticDoubleField(this,clazz,fieldID);
+    }
+
+    void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+                        jobject value) {
+      functions->SetStaticObjectField(this,clazz,fieldID,value);
+    }
+    void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+                        jboolean value) {
+      functions->SetStaticBooleanField(this,clazz,fieldID,value);
+    }
+    void SetStaticByteField(jclass clazz, jfieldID fieldID,
+                        jbyte value) {
+      functions->SetStaticByteField(this,clazz,fieldID,value);
+    }
+    void SetStaticCharField(jclass clazz, jfieldID fieldID,
+                        jchar value) {
+      functions->SetStaticCharField(this,clazz,fieldID,value);
+    }
+    void SetStaticShortField(jclass clazz, jfieldID fieldID,
+                        jshort value) {
+      functions->SetStaticShortField(this,clazz,fieldID,value);
+    }
+    void SetStaticIntField(jclass clazz, jfieldID fieldID,
+                        jint value) {
+      functions->SetStaticIntField(this,clazz,fieldID,value);
+    }
+    void SetStaticLongField(jclass clazz, jfieldID fieldID,
+                        jlong value) {
+      functions->SetStaticLongField(this,clazz,fieldID,value);
+    }
+    void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+                        jfloat value) {
+      functions->SetStaticFloatField(this,clazz,fieldID,value);
+    }
+    void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+                        jdouble value) {
+      functions->SetStaticDoubleField(this,clazz,fieldID,value);
+    }
+
+    jstring NewString(const jchar *unicode, jsize len) {
+        return functions->NewString(this,unicode,len);
+    }
+    jsize GetStringLength(jstring str) {
+        return functions->GetStringLength(this,str);
+    }
+    const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+        return functions->GetStringChars(this,str,isCopy);
+    }
+    void ReleaseStringChars(jstring str, const jchar *chars) {
+        functions->ReleaseStringChars(this,str,chars);
+    }
+
+    jstring NewStringUTF(const char *utf) {
+        return functions->NewStringUTF(this,utf);
+    }
+    jsize GetStringUTFLength(jstring str) {
+        return functions->GetStringUTFLength(this,str);
+    }
+    const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+        return functions->GetStringUTFChars(this,str,isCopy);
+    }
+    void ReleaseStringUTFChars(jstring str, const char* chars) {
+        functions->ReleaseStringUTFChars(this,str,chars);
+    }
+
+    jsize GetArrayLength(jarray array) {
+        return functions->GetArrayLength(this,array);
+    }
+
+    jobjectArray NewObjectArray(jsize len, jclass clazz,
+                                jobject init) {
+        return functions->NewObjectArray(this,len,clazz,init);
+    }
+    jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+        return functions->GetObjectArrayElement(this,array,index);
+    }
+    void SetObjectArrayElement(jobjectArray array, jsize index,
+                               jobject val) {
+        functions->SetObjectArrayElement(this,array,index,val);
+    }
+
+    jbooleanArray NewBooleanArray(jsize len) {
+        return functions->NewBooleanArray(this,len);
+    }
+    jbyteArray NewByteArray(jsize len) {
+        return functions->NewByteArray(this,len);
+    }
+    jcharArray NewCharArray(jsize len) {
+        return functions->NewCharArray(this,len);
+    }
+    jshortArray NewShortArray(jsize len) {
+        return functions->NewShortArray(this,len);
+    }
+    jintArray NewIntArray(jsize len) {
+        return functions->NewIntArray(this,len);
+    }
+    jlongArray NewLongArray(jsize len) {
+        return functions->NewLongArray(this,len);
+    }
+    jfloatArray NewFloatArray(jsize len) {
+        return functions->NewFloatArray(this,len);
+    }
+    jdoubleArray NewDoubleArray(jsize len) {
+        return functions->NewDoubleArray(this,len);
+    }
+
+    jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+        return functions->GetBooleanArrayElements(this,array,isCopy);
+    }
+    jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+        return functions->GetByteArrayElements(this,array,isCopy);
+    }
+    jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+        return functions->GetCharArrayElements(this,array,isCopy);
+    }
+    jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+        return functions->GetShortArrayElements(this,array,isCopy);
+    }
+    jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+        return functions->GetIntArrayElements(this,array,isCopy);
+    }
+    jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+        return functions->GetLongArrayElements(this,array,isCopy);
+    }
+    jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+        return functions->GetFloatArrayElements(this,array,isCopy);
+    }
+    jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+        return functions->GetDoubleArrayElements(this,array,isCopy);
+    }
+
+    void ReleaseBooleanArrayElements(jbooleanArray array,
+                                     jboolean *elems,
+                                     jint mode) {
+        functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+    }
+    void ReleaseByteArrayElements(jbyteArray array,
+                                  jbyte *elems,
+                                  jint mode) {
+        functions->ReleaseByteArrayElements(this,array,elems,mode);
+    }
+    void ReleaseCharArrayElements(jcharArray array,
+                                  jchar *elems,
+                                  jint mode) {
+        functions->ReleaseCharArrayElements(this,array,elems,mode);
+    }
+    void ReleaseShortArrayElements(jshortArray array,
+                                   jshort *elems,
+                                   jint mode) {
+        functions->ReleaseShortArrayElements(this,array,elems,mode);
+    }
+    void ReleaseIntArrayElements(jintArray array,
+                                 jint *elems,
+                                 jint mode) {
+        functions->ReleaseIntArrayElements(this,array,elems,mode);
+    }
+    void ReleaseLongArrayElements(jlongArray array,
+                                  jlong *elems,
+                                  jint mode) {
+        functions->ReleaseLongArrayElements(this,array,elems,mode);
+    }
+    void ReleaseFloatArrayElements(jfloatArray array,
+                                   jfloat *elems,
+                                   jint mode) {
+        functions->ReleaseFloatArrayElements(this,array,elems,mode);
+    }
+    void ReleaseDoubleArrayElements(jdoubleArray array,
+                                    jdouble *elems,
+                                    jint mode) {
+        functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+    }
+
+    void GetBooleanArrayRegion(jbooleanArray array,
+                               jsize start, jsize len, jboolean *buf) {
+        functions->GetBooleanArrayRegion(this,array,start,len,buf);
+    }
+    void GetByteArrayRegion(jbyteArray array,
+                            jsize start, jsize len, jbyte *buf) {
+        functions->GetByteArrayRegion(this,array,start,len,buf);
+    }
+    void GetCharArrayRegion(jcharArray array,
+                            jsize start, jsize len, jchar *buf) {
+        functions->GetCharArrayRegion(this,array,start,len,buf);
+    }
+    void GetShortArrayRegion(jshortArray array,
+                             jsize start, jsize len, jshort *buf) {
+        functions->GetShortArrayRegion(this,array,start,len,buf);
+    }
+    void GetIntArrayRegion(jintArray array,
+                           jsize start, jsize len, jint *buf) {
+        functions->GetIntArrayRegion(this,array,start,len,buf);
+    }
+    void GetLongArrayRegion(jlongArray array,
+                            jsize start, jsize len, jlong *buf) {
+        functions->GetLongArrayRegion(this,array,start,len,buf);
+    }
+    void GetFloatArrayRegion(jfloatArray array,
+                             jsize start, jsize len, jfloat *buf) {
+        functions->GetFloatArrayRegion(this,array,start,len,buf);
+    }
+    void GetDoubleArrayRegion(jdoubleArray array,
+                              jsize start, jsize len, jdouble *buf) {
+        functions->GetDoubleArrayRegion(this,array,start,len,buf);
+    }
+
+    void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+                               const jboolean *buf) {
+        functions->SetBooleanArrayRegion(this,array,start,len,buf);
+    }
+    void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+                            const jbyte *buf) {
+        functions->SetByteArrayRegion(this,array,start,len,buf);
+    }
+    void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+                            const jchar *buf) {
+        functions->SetCharArrayRegion(this,array,start,len,buf);
+    }
+    void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+                             const jshort *buf) {
+        functions->SetShortArrayRegion(this,array,start,len,buf);
+    }
+    void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+                           const jint *buf) {
+        functions->SetIntArrayRegion(this,array,start,len,buf);
+    }
+    void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+                            const jlong *buf) {
+        functions->SetLongArrayRegion(this,array,start,len,buf);
+    }
+    void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+                             const jfloat *buf) {
+        functions->SetFloatArrayRegion(this,array,start,len,buf);
+    }
+    void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+                              const jdouble *buf) {
+        functions->SetDoubleArrayRegion(this,array,start,len,buf);
+    }
+
+    jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+                         jint nMethods) {
+        return functions->RegisterNatives(this,clazz,methods,nMethods);
+    }
+    jint UnregisterNatives(jclass clazz) {
+        return functions->UnregisterNatives(this,clazz);
+    }
+
+    jint MonitorEnter(jobject obj) {
+        return functions->MonitorEnter(this,obj);
+    }
+    jint MonitorExit(jobject obj) {
+        return functions->MonitorExit(this,obj);
+    }
+
+    jint GetJavaVM(JavaVM **vm) {
+        return functions->GetJavaVM(this,vm);
+    }
+
+    void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+        functions->GetStringRegion(this,str,start,len,buf);
+    }
+    void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+        functions->GetStringUTFRegion(this,str,start,len,buf);
+    }
+
+    void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+        return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+    }
+    void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+        functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+    }
+
+    const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+        return functions->GetStringCritical(this,string,isCopy);
+    }
+    void ReleaseStringCritical(jstring string, const jchar *cstring) {
+        functions->ReleaseStringCritical(this,string,cstring);
+    }
+
+    jweak NewWeakGlobalRef(jobject obj) {
+        return functions->NewWeakGlobalRef(this,obj);
+    }
+    void DeleteWeakGlobalRef(jweak ref) {
+        functions->DeleteWeakGlobalRef(this,ref);
+    }
+
+    jboolean ExceptionCheck() {
+        return functions->ExceptionCheck(this);
+    }
+
+    jobject NewDirectByteBuffer(void* address, jlong capacity) {
+        return functions->NewDirectByteBuffer(this, address, capacity);
+    }
+    void* GetDirectBufferAddress(jobject buf) {
+        return functions->GetDirectBufferAddress(this, buf);
+    }
+    jlong GetDirectBufferCapacity(jobject buf) {
+        return functions->GetDirectBufferCapacity(this, buf);
+    }
+    jobjectRefType GetObjectRefType(jobject obj) {
+        return functions->GetObjectRefType(this, obj);
+    }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+    char *optionString;
+    void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+    jint version;
+
+    jint nOptions;
+    JavaVMOption *options;
+    jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+    jint version;
+
+    char *name;
+    jobject group;
+} JavaVMAttachArgs;
+
+/* These will be VM-specific. */
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+    void *reserved0;
+    void *reserved1;
+    void *reserved2;
+
+    jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+    jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+    jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+    jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+    jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+    const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+    jint DestroyJavaVM() {
+        return functions->DestroyJavaVM(this);
+    }
+    jint AttachCurrentThread(void **penv, void *args) {
+        return functions->AttachCurrentThread(this, penv, args);
+    }
+    jint DetachCurrentThread() {
+        return functions->DetachCurrentThread(this);
+    }
+
+    jint GetEnv(void **penv, jint version) {
+        return functions->GetEnv(this, penv, version);
+    }
+    jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+        return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+    }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
Index: /tags/icedtea-web/beta/launcher/jni_md.h
===================================================================
--- /tags/icedtea-web/beta/launcher/jni_md.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jni_md.h	(revision 403)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1996, 2000, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT
+#define JNIIMPORT
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64 /* 64-bit Solaris */
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
Index: /tags/icedtea-web/beta/launcher/jvm.h
===================================================================
--- /tags/icedtea-web/beta/launcher/jvm.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jvm.h	(revision 403)
@@ -0,0 +1,1501 @@
+/*
+ * Copyright (c) 1997, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _JAVASOFT_JVM_H_
+#define _JAVASOFT_JVM_H_
+
+#include <sys/stat.h>
+
+#include "jni.h"
+#include "jvm_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains additional functions exported from the VM.
+ * These functions are complementary to the standard JNI support.
+ * There are three parts to this file:
+ *
+ * First, this file contains the VM-related functions needed by native
+ * libraries in the standard Java API. For example, the java.lang.Object
+ * class needs VM-level functions that wait for and notify monitors.
+ *
+ * Second, this file contains the functions and constant definitions
+ * needed by the byte code verifier and class file format checker.
+ * These functions allow the verifier and format checker to be written
+ * in a VM-independent way.
+ *
+ * Third, this file contains various I/O and nerwork operations needed
+ * by the standard Java I/O and network APIs.
+ */
+
+/*
+ * Bump the version number when either of the following happens:
+ *
+ * 1. There is a change in JVM_* functions.
+ *
+ * 2. There is a change in the contract between VM and Java classes.
+ *    For example, if the VM relies on a new private field in Thread
+ *    class.
+ */
+
+#define JVM_INTERFACE_VERSION 4
+
+JNIEXPORT jint JNICALL
+JVM_GetInterfaceVersion(void);
+
+/*************************************************************************
+ PART 1: Functions for Native Libraries
+ ************************************************************************/
+/*
+ * java.lang.Object
+ */
+JNIEXPORT jint JNICALL
+JVM_IHashCode(JNIEnv *env, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms);
+
+JNIEXPORT void JNICALL
+JVM_MonitorNotify(JNIEnv *env, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_MonitorNotifyAll(JNIEnv *env, jobject obj);
+
+JNIEXPORT jobject JNICALL
+JVM_Clone(JNIEnv *env, jobject obj);
+
+/*
+ * java.lang.String
+ */
+JNIEXPORT jstring JNICALL
+JVM_InternString(JNIEnv *env, jstring str);
+
+/*
+ * java.lang.System
+ */
+JNIEXPORT jlong JNICALL
+JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
+
+JNIEXPORT jlong JNICALL
+JVM_NanoTime(JNIEnv *env, jclass ignored);
+
+JNIEXPORT void JNICALL
+JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
+              jobject dst, jint dst_pos, jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_InitProperties(JNIEnv *env, jobject p);
+
+/*
+ * java.io.File
+ */
+JNIEXPORT void JNICALL
+JVM_OnExit(void (*func)(void));
+
+/*
+ * java.lang.Runtime
+ */
+JNIEXPORT void JNICALL
+JVM_Exit(jint code);
+
+JNIEXPORT void JNICALL
+JVM_Halt(jint code);
+
+JNIEXPORT void JNICALL
+JVM_GC(void);
+
+/* Returns the number of real-time milliseconds that have elapsed since the
+ * least-recently-inspected heap object was last inspected by the garbage
+ * collector.
+ *
+ * For simple stop-the-world collectors this value is just the time
+ * since the most recent collection.  For generational collectors it is the
+ * time since the oldest generation was most recently collected.  Other
+ * collectors are free to return a pessimistic estimate of the elapsed time, or
+ * simply the time since the last full collection was performed.
+ *
+ * Note that in the presence of reference objects, a given object that is no
+ * longer strongly reachable may have to be inspected multiple times before it
+ * can be reclaimed.
+ */
+JNIEXPORT jlong JNICALL
+JVM_MaxObjectInspectionAge(void);
+
+JNIEXPORT void JNICALL
+JVM_TraceInstructions(jboolean on);
+
+JNIEXPORT void JNICALL
+JVM_TraceMethodCalls(jboolean on);
+
+JNIEXPORT jlong JNICALL
+JVM_TotalMemory(void);
+
+JNIEXPORT jlong JNICALL
+JVM_FreeMemory(void);
+
+JNIEXPORT jlong JNICALL
+JVM_MaxMemory(void);
+
+JNIEXPORT jint JNICALL
+JVM_ActiveProcessorCount(void);
+
+JNIEXPORT void * JNICALL
+JVM_LoadLibrary(const char *name);
+
+JNIEXPORT void JNICALL
+JVM_UnloadLibrary(void * handle);
+
+JNIEXPORT void * JNICALL
+JVM_FindLibraryEntry(void *handle, const char *name);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsSupportedJNIVersion(jint version);
+
+/*
+ * java.lang.Float and java.lang.Double
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsNaN(jdouble d);
+
+/*
+ * java.lang.Throwable
+ */
+JNIEXPORT void JNICALL
+JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
+
+JNIEXPORT void JNICALL
+JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable);
+
+JNIEXPORT jint JNICALL
+JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable);
+
+JNIEXPORT jobject JNICALL
+JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index);
+
+/*
+ * java.lang.Compiler
+ */
+JNIEXPORT void JNICALL
+JVM_InitializeCompiler (JNIEnv *env, jclass compCls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsSilentCompiler(JNIEnv *env, jclass compCls);
+
+JNIEXPORT jboolean JNICALL
+JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname);
+
+JNIEXPORT jobject JNICALL
+JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg);
+
+JNIEXPORT void JNICALL
+JVM_EnableCompiler(JNIEnv *env, jclass compCls);
+
+JNIEXPORT void JNICALL
+JVM_DisableCompiler(JNIEnv *env, jclass compCls);
+
+/*
+ * java.lang.Thread
+ */
+JNIEXPORT void JNICALL
+JVM_StartThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsThreadAlive(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_SuspendThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_ResumeThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
+
+JNIEXPORT void JNICALL
+JVM_Yield(JNIEnv *env, jclass threadClass);
+
+JNIEXPORT void JNICALL
+JVM_Sleep(JNIEnv *env, jclass threadClass, jlong millis);
+
+JNIEXPORT jobject JNICALL
+JVM_CurrentThread(JNIEnv *env, jclass threadClass);
+
+JNIEXPORT jint JNICALL
+JVM_CountStackFrames(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_Interrupt(JNIEnv *env, jobject thread);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsInterrupted(JNIEnv *env, jobject thread, jboolean clearInterrupted);
+
+JNIEXPORT jboolean JNICALL
+JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_DumpAllStacks(JNIEnv *env, jclass unused);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetAllThreads(JNIEnv *env, jclass dummy);
+
+/* getStackTrace() and getAllStackTraces() method */
+JNIEXPORT jobjectArray JNICALL
+JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
+
+/*
+ * java.lang.SecurityManager
+ */
+JNIEXPORT jclass JNICALL
+JVM_CurrentLoadedClass(JNIEnv *env);
+
+JNIEXPORT jobject JNICALL
+JVM_CurrentClassLoader(JNIEnv *env);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassContext(JNIEnv *env);
+
+JNIEXPORT jint JNICALL
+JVM_ClassDepth(JNIEnv *env, jstring name);
+
+JNIEXPORT jint JNICALL
+JVM_ClassLoaderDepth(JNIEnv *env);
+
+/*
+ * java.lang.Package
+ */
+JNIEXPORT jstring JNICALL
+JVM_GetSystemPackage(JNIEnv *env, jstring name);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetSystemPackages(JNIEnv *env);
+
+/*
+ * java.io.ObjectInputStream
+ */
+JNIEXPORT jobject JNICALL
+JVM_AllocateNewObject(JNIEnv *env, jobject obj, jclass currClass,
+                      jclass initClass);
+
+JNIEXPORT jobject JNICALL
+JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass,
+                     jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_LatestUserDefinedLoader(JNIEnv *env);
+
+/*
+ * This function has been deprecated and should not be considered
+ * part of the specified JVM interface.
+ */
+JNIEXPORT jclass JNICALL
+JVM_LoadClass0(JNIEnv *env, jobject obj, jclass currClass,
+               jstring currClassName);
+
+/*
+ * java.lang.reflect.Array
+ */
+JNIEXPORT jint JNICALL
+JVM_GetArrayLength(JNIEnv *env, jobject arr);
+
+JNIEXPORT jobject JNICALL
+JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index);
+
+JNIEXPORT jvalue JNICALL
+JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode);
+
+JNIEXPORT void JNICALL
+JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val);
+
+JNIEXPORT void JNICALL
+JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
+                             unsigned char vCode);
+
+JNIEXPORT jobject JNICALL
+JVM_NewArray(JNIEnv *env, jclass eltClass, jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
+
+/*
+ * java.lang.Class and java.lang.ClassLoader
+ */
+/*
+ * Returns the class in which the code invoking the native method
+ * belongs.
+ *
+ * Note that in JDK 1.1, native methods did not create a frame.
+ * In 1.2, they do. Therefore native methods like Class.forName
+ * can no longer look at the current frame for the caller class.
+ */
+JNIEXPORT jclass JNICALL
+JVM_GetCallerClass(JNIEnv *env, int n);
+
+/*
+ * Find primitive classes
+ * utf: class name
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
+
+/*
+ * Link the class
+ */
+JNIEXPORT void JNICALL
+JVM_ResolveClass(JNIEnv *env, jclass cls);
+
+/*
+ * Find a class from a given class loader. Throw ClassNotFoundException
+ * or NoClassDefFoundError depending on the value of the last
+ * argument.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
+                             jobject loader, jboolean throwError);
+
+/*
+ * Find a class from a given class.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
+                             jclass from);
+
+/* Find a loaded class cached by the VM */
+JNIEXPORT jclass JNICALL
+JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name);
+
+/* Define a class */
+JNIEXPORT jclass JNICALL
+JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+                jsize len, jobject pd);
+
+/* Define a class with a source (added in JDK1.5) */
+JNIEXPORT jclass JNICALL
+JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
+                          const jbyte *buf, jsize len, jobject pd,
+                          const char *source);
+
+/*
+ * Reflection support functions
+ */
+
+JNIEXPORT jstring JNICALL
+JVM_GetClassName(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassInterfaces(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobject JNICALL
+JVM_GetClassLoader(JNIEnv *env, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsInterface(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassSigners(JNIEnv *env, jclass cls);
+
+JNIEXPORT void JNICALL
+JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers);
+
+JNIEXPORT jobject JNICALL
+JVM_GetProtectionDomain(JNIEnv *env, jclass cls);
+
+JNIEXPORT void JNICALL
+JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsArrayClass(JNIEnv *env, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
+
+JNIEXPORT jclass JNICALL
+JVM_GetComponentType(JNIEnv *env, jclass cls);
+
+JNIEXPORT jint JNICALL
+JVM_GetClassModifiers(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass);
+
+JNIEXPORT jclass JNICALL
+JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass);
+
+/* Generics support (JDK 1.5) */
+JNIEXPORT jstring JNICALL
+JVM_GetClassSignature(JNIEnv *env, jclass cls);
+
+/* Annotations support (JDK 1.5) */
+JNIEXPORT jbyteArray JNICALL
+JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
+
+/*
+ * New (JDK 1.4) reflection implementation
+ */
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+/* Differs from JVM_GetClassModifiers in treatment of inner classes.
+   This returns the access flags for the class as specified in the
+   class file rather than searching the InnerClasses attribute (if
+   present) to find the source-level access flags. Only the values of
+   the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
+   valid. */
+JNIEXPORT jint JNICALL
+JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
+
+/* The following two reflection routines are still needed due to startup time issues */
+/*
+ * java.lang.reflect.Method
+ */
+JNIEXPORT jobject JNICALL
+JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
+
+/*
+ * java.lang.reflect.Constructor
+ */
+JNIEXPORT jobject JNICALL
+JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
+
+/*
+ * Constant pool access; currently used to implement reflective access to annotations (JDK 1.5)
+ */
+
+JNIEXPORT jobject JNICALL
+JVM_GetClassConstantPool(JNIEnv *env, jclass cls);
+
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
+(JNIEnv *env, jobject unused, jobject jcpool);
+
+JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+/*
+ * java.security.*
+ */
+
+JNIEXPORT jobject JNICALL
+JVM_DoPrivileged(JNIEnv *env, jclass cls,
+                 jobject action, jobject context, jboolean wrapException);
+
+JNIEXPORT jobject JNICALL
+JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobject JNICALL
+JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls);
+
+/*
+ * Signal support, used to implement the shutdown sequence.  Every VM must
+ * support JVM_SIGINT and JVM_SIGTERM, raising the former for user interrupts
+ * (^C) and the latter for external termination (kill, system shutdown, etc.).
+ * Other platform-dependent signal values may also be supported.
+ */
+
+JNIEXPORT void * JNICALL
+JVM_RegisterSignal(jint sig, void *handler);
+
+JNIEXPORT jboolean JNICALL
+JVM_RaiseSignal(jint sig);
+
+JNIEXPORT jint JNICALL
+JVM_FindSignal(const char *name);
+
+/*
+ * Retrieve the assertion directives for the specified class.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls);
+
+/*
+ * Retrieve the assertion directives from the VM.
+ */
+JNIEXPORT jobject JNICALL
+JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
+
+/*
+ * java.util.concurrent.AtomicLong
+ */
+JNIEXPORT jboolean JNICALL
+JVM_SupportsCX8(void);
+
+/*************************************************************************
+ PART 2: Support for the Verifier and Class File Format Checker
+ ************************************************************************/
+/*
+ * Return the class name in UTF format. The result is valid
+ * until JVM_ReleaseUTf is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetClassNameUTF(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the constant pool types in the buffer provided by "types."
+ */
+JNIEXPORT void JNICALL
+JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types);
+
+/*
+ * Returns the number of Constant Pool entries.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the number of *declared* fields or methods.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetClassFieldsCount(JNIEnv *env, jclass cb);
+
+JNIEXPORT jint JNICALL
+JVM_GetClassMethodsCount(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the CP indexes of exceptions raised by a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
+                                unsigned short *exceptions);
+/*
+ * Returns the number of exceptions raised by a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index);
+
+/*
+ * Returns the byte code sequence of a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
+                        unsigned char *code);
+
+/*
+ * Returns the length of the byte code sequence of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index);
+
+/*
+ * A structure used to a capture exception table entry in a Java method.
+ */
+typedef struct {
+    jint start_pc;
+    jint end_pc;
+    jint handler_pc;
+    jint catchType;
+} JVM_ExceptionTableEntryType;
+
+/*
+ * Returns the exception table entry at entry_index of a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
+                                   jint entry_index,
+                                   JVM_ExceptionTableEntryType *entry);
+
+/*
+ * Returns the length of the exception table of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the modifiers of a given field.
+ * The field is identified by field_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the modifiers of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the number of local variables of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the number of arguments (including this pointer) of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the maximum amount of stack (in words) used by a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Is a given method a constructor.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the name of a given method in UTF format.
+ * The result remains valid until JVM_ReleaseUTF is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of a given method in UTF format.
+ * The result remains valid until JVM_ReleaseUTF is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the name of the field refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the name of the method refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of the method refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of the field refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The constant pool entry must refer to a CONSTANT_Fieldref.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The constant pool entry must refer to CONSTANT_Methodref or
+ * CONSTANT_InterfaceMethodref.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the modifiers of a field in calledClass. The field is
+ * referred to in class cb at constant pool entry index.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ *
+ * Returns -1 if the field does not exist in calledClass.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
+
+/*
+ * Returns the modifiers of a method in calledClass. The method is
+ * referred to in class cb at constant pool entry index.
+ *
+ * Returns -1 if the method does not exist in calledClass.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
+
+/*
+ * Releases the UTF string obtained from the VM.
+ */
+JNIEXPORT void JNICALL
+JVM_ReleaseUTF(const char *utf);
+
+/*
+ * Compare if two classes are in the same package.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
+
+/* Constants in class files */
+
+#define JVM_ACC_PUBLIC        0x0001  /* visible to everyone */
+#define JVM_ACC_PRIVATE       0x0002  /* visible only to the defining class */
+#define JVM_ACC_PROTECTED     0x0004  /* visible to subclasses */
+#define JVM_ACC_STATIC        0x0008  /* instance variable is static */
+#define JVM_ACC_FINAL         0x0010  /* no further subclassing, overriding */
+#define JVM_ACC_SYNCHRONIZED  0x0020  /* wrap method call in monitor lock */
+#define JVM_ACC_SUPER         0x0020  /* funky handling of invokespecial */
+#define JVM_ACC_VOLATILE      0x0040  /* can not cache in registers */
+#define JVM_ACC_BRIDGE        0x0040  /* bridge method generated by compiler */
+#define JVM_ACC_TRANSIENT     0x0080  /* not persistant */
+#define JVM_ACC_VARARGS       0x0080  /* method declared with variable number of args */
+#define JVM_ACC_NATIVE        0x0100  /* implemented in C */
+#define JVM_ACC_INTERFACE     0x0200  /* class is an interface */
+#define JVM_ACC_ABSTRACT      0x0400  /* no definition provided */
+#define JVM_ACC_STRICT        0x0800  /* strict floating point */
+#define JVM_ACC_SYNTHETIC     0x1000  /* compiler-generated class, method or field */
+
+#define JVM_ACC_ANNOTATION    0x2000  /* annotation type */
+#define JVM_ACC_ENUM          0x4000  /* field is declared as element of enum */
+
+#define JVM_ACC_PUBLIC_BIT        0
+#define JVM_ACC_PRIVATE_BIT       1
+#define JVM_ACC_PROTECTED_BIT     2
+#define JVM_ACC_STATIC_BIT        3
+#define JVM_ACC_FINAL_BIT         4
+#define JVM_ACC_SYNCHRONIZED_BIT  5
+#define JVM_ACC_SUPER_BIT         5
+#define JVM_ACC_VOLATILE_BIT      6
+#define JVM_ACC_BRIDGE_BIT        6
+#define JVM_ACC_TRANSIENT_BIT     7
+#define JVM_ACC_VARARGS_BIT       7
+#define JVM_ACC_NATIVE_BIT        8
+#define JVM_ACC_INTERFACE_BIT     9
+#define JVM_ACC_ABSTRACT_BIT      10
+#define JVM_ACC_STRICT_BIT        11
+#define JVM_ACC_SYNTHETIC_BIT     12
+#define JVM_ACC_ANNOTATION_BIT    13
+#define JVM_ACC_ENUM_BIT          14
+
+enum {
+    JVM_CONSTANT_Utf8 = 1,
+    JVM_CONSTANT_Unicode,               /* unused */
+    JVM_CONSTANT_Integer,
+    JVM_CONSTANT_Float,
+    JVM_CONSTANT_Long,
+    JVM_CONSTANT_Double,
+    JVM_CONSTANT_Class,
+    JVM_CONSTANT_String,
+    JVM_CONSTANT_Fieldref,
+    JVM_CONSTANT_Methodref,
+    JVM_CONSTANT_InterfaceMethodref,
+    JVM_CONSTANT_NameAndType
+};
+
+/* Used in the newarray instruction. */
+
+#define JVM_T_BOOLEAN 4
+#define JVM_T_CHAR    5
+#define JVM_T_FLOAT   6
+#define JVM_T_DOUBLE  7
+#define JVM_T_BYTE    8
+#define JVM_T_SHORT   9
+#define JVM_T_INT    10
+#define JVM_T_LONG   11
+
+/* JVM method signatures */
+
+#define JVM_SIGNATURE_ARRAY             '['
+#define JVM_SIGNATURE_BYTE              'B'
+#define JVM_SIGNATURE_CHAR              'C'
+#define JVM_SIGNATURE_CLASS             'L'
+#define JVM_SIGNATURE_ENDCLASS          ';'
+#define JVM_SIGNATURE_ENUM              'E'
+#define JVM_SIGNATURE_FLOAT             'F'
+#define JVM_SIGNATURE_DOUBLE            'D'
+#define JVM_SIGNATURE_FUNC              '('
+#define JVM_SIGNATURE_ENDFUNC           ')'
+#define JVM_SIGNATURE_INT               'I'
+#define JVM_SIGNATURE_LONG              'J'
+#define JVM_SIGNATURE_SHORT             'S'
+#define JVM_SIGNATURE_VOID              'V'
+#define JVM_SIGNATURE_BOOLEAN           'Z'
+
+/*
+ * A function defined by the byte-code verifier and called by the VM.
+ * This is not a function implemented in the VM.
+ *
+ * Returns JNI_FALSE if verification fails. A detailed error message
+ * will be places in msg_buf, whose length is specified by buf_len.
+ */
+typedef jboolean (*verifier_fn_t)(JNIEnv *env,
+                                  jclass cb,
+                                  char * msg_buf,
+                                  jint buf_len);
+
+
+/*
+ * Support for a VM-independent class format checker.
+ */
+typedef struct {
+    unsigned long code;    /* byte code */
+    unsigned long excs;    /* exceptions */
+    unsigned long etab;    /* catch table */
+    unsigned long lnum;    /* line number */
+    unsigned long lvar;    /* local vars */
+} method_size_info;
+
+typedef struct {
+    unsigned int constants;    /* constant pool */
+    unsigned int fields;
+    unsigned int methods;
+    unsigned int interfaces;
+    unsigned int fields2;      /* number of static 2-word fields */
+    unsigned int innerclasses; /* # of records in InnerClasses attr */
+
+    method_size_info clinit;   /* memory used in clinit */
+    method_size_info main;     /* used everywhere else */
+} class_size_info;
+
+/*
+ * Functions defined in libjava.so to perform string conversions.
+ *
+ */
+
+typedef jstring (*to_java_string_fn_t)(JNIEnv *env, char *str);
+
+typedef char *(*to_c_string_fn_t)(JNIEnv *env, jstring s, jboolean *b);
+
+/* This is the function defined in libjava.so that performs class
+ * format checks. This functions fills in size information about
+ * the class file and returns:
+ *
+ *   0: good
+ *  -1: out of memory
+ *  -2: bad format
+ *  -3: unsupported version
+ *  -4: bad class name
+ */
+
+typedef jint (*check_format_fn_t)(char *class_name,
+                                  unsigned char *data,
+                                  unsigned int data_size,
+                                  class_size_info *class_size,
+                                  char *message_buffer,
+                                  jint buffer_length,
+                                  jboolean measure_only,
+                                  jboolean check_relaxed);
+
+#define JVM_RECOGNIZED_CLASS_MODIFIERS (JVM_ACC_PUBLIC | \
+                                        JVM_ACC_FINAL | \
+                                        JVM_ACC_SUPER | \
+                                        JVM_ACC_INTERFACE | \
+                                        JVM_ACC_ABSTRACT | \
+                                        JVM_ACC_ANNOTATION | \
+                                        JVM_ACC_ENUM | \
+                                        JVM_ACC_SYNTHETIC)
+
+#define JVM_RECOGNIZED_FIELD_MODIFIERS (JVM_ACC_PUBLIC | \
+                                        JVM_ACC_PRIVATE | \
+                                        JVM_ACC_PROTECTED | \
+                                        JVM_ACC_STATIC | \
+                                        JVM_ACC_FINAL | \
+                                        JVM_ACC_VOLATILE | \
+                                        JVM_ACC_TRANSIENT | \
+                                        JVM_ACC_ENUM | \
+                                        JVM_ACC_SYNTHETIC)
+
+#define JVM_RECOGNIZED_METHOD_MODIFIERS (JVM_ACC_PUBLIC | \
+                                         JVM_ACC_PRIVATE | \
+                                         JVM_ACC_PROTECTED | \
+                                         JVM_ACC_STATIC | \
+                                         JVM_ACC_FINAL | \
+                                         JVM_ACC_SYNCHRONIZED | \
+                                         JVM_ACC_BRIDGE | \
+                                         JVM_ACC_VARARGS | \
+                                         JVM_ACC_NATIVE | \
+                                         JVM_ACC_ABSTRACT | \
+                                         JVM_ACC_STRICT | \
+                                         JVM_ACC_SYNTHETIC)
+
+/*
+ * This is the function defined in libjava.so to perform path
+ * canonicalization. VM call this function before opening jar files
+ * to load system classes.
+ *
+ */
+
+typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
+
+/*************************************************************************
+ PART 3: I/O and Network Support
+ ************************************************************************/
+
+/* Note that the JVM IO functions are expected to return JVM_IO_ERR
+ * when there is any kind of error. The caller can then use the
+ * platform specific support (e.g., errno) to get the detailed
+ * error info.  The JVM_GetLastErrorString procedure may also be used
+ * to obtain a descriptive error string.
+ */
+#define JVM_IO_ERR  (-1)
+
+/* For interruptible IO. Returning JVM_IO_INTR indicates that an IO
+ * operation has been disrupted by Thread.interrupt. There are a
+ * number of technical difficulties related to interruptible IO that
+ * need to be solved. For example, most existing programs do not handle
+ * InterruptedIOExceptions specially, they simply treat those as any
+ * IOExceptions, which typically indicate fatal errors.
+ *
+ * There are also two modes of operation for interruptible IO. In the
+ * resumption mode, an interrupted IO operation is guaranteed not to
+ * have any side-effects, and can be restarted. In the termination mode,
+ * an interrupted IO operation corrupts the underlying IO stream, so
+ * that the only reasonable operation on an interrupted stream is to
+ * close that stream. The resumption mode seems to be impossible to
+ * implement on Win32 and Solaris. Implementing the termination mode is
+ * easier, but it's not clear that's the right semantics.
+ *
+ * Interruptible IO is not supported on Win32.It can be enabled/disabled
+ * using a compile-time flag on Solaris. Third-party JVM ports do not
+ * need to implement interruptible IO.
+ */
+#define JVM_IO_INTR (-2)
+
+/* Write a string into the given buffer, in the platform's local encoding,
+ * that describes the most recent system-level error to occur in this thread.
+ * Return the length of the string or zero if no error occurred.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetLastErrorString(char *buf, int len);
+
+/*
+ * Convert a pathname into native format.  This function does syntactic
+ * cleanup, such as removing redundant separator characters.  It modifies
+ * the given pathname string in place.
+ */
+JNIEXPORT char * JNICALL
+JVM_NativePath(char *);
+
+/*
+ * JVM I/O error codes
+ */
+#define JVM_EEXIST       -100
+
+/*
+ * Open a file descriptor. This function returns a negative error code
+ * on error, and a non-negative integer that is the file descriptor on
+ * success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Open(const char *fname, jint flags, jint mode);
+
+/*
+ * Close a file descriptor. This function returns -1 on error, and 0
+ * on success.
+ *
+ * fd        the file descriptor to close.
+ */
+JNIEXPORT jint JNICALL
+JVM_Close(jint fd);
+
+/*
+ * Read data from a file decriptor into a char array.
+ *
+ * fd        the file descriptor to read from.
+ * buf       the buffer where to put the read data.
+ * nbytes    the number of bytes to read.
+ *
+ * This function returns -1 on error, and 0 on success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Read(jint fd, char *buf, jint nbytes);
+
+/*
+ * Write data from a char array to a file decriptor.
+ *
+ * fd        the file descriptor to read from.
+ * buf       the buffer from which to fetch the data.
+ * nbytes    the number of bytes to write.
+ *
+ * This function returns -1 on error, and 0 on success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Write(jint fd, char *buf, jint nbytes);
+
+/*
+ * Returns the number of bytes available for reading from a given file
+ * descriptor
+ */
+JNIEXPORT jint JNICALL
+JVM_Available(jint fd, jlong *pbytes);
+
+/*
+ * Move the file descriptor pointer from whence by offset.
+ *
+ * fd        the file descriptor to move.
+ * offset    the number of bytes to move it by.
+ * whence    the start from where to move it.
+ *
+ * This function returns the resulting pointer location.
+ */
+JNIEXPORT jlong JNICALL
+JVM_Lseek(jint fd, jlong offset, jint whence);
+
+/*
+ * Set the length of the file associated with the given descriptor to the given
+ * length.  If the new length is longer than the current length then the file
+ * is extended; the contents of the extended portion are not defined.  The
+ * value of the file pointer is undefined after this procedure returns.
+ */
+JNIEXPORT jint JNICALL
+JVM_SetLength(jint fd, jlong length);
+
+/*
+ * Synchronize the file descriptor's in memory state with that of the
+ * physical device.  Return of -1 is an error, 0 is OK.
+ */
+JNIEXPORT jint JNICALL
+JVM_Sync(jint fd);
+
+/*
+ * Networking library support
+ */
+
+JNIEXPORT jint JNICALL
+JVM_InitializeSocketLibrary(void);
+
+struct sockaddr;
+
+JNIEXPORT jint JNICALL
+JVM_Socket(jint domain, jint type, jint protocol);
+
+JNIEXPORT jint JNICALL
+JVM_SocketClose(jint fd);
+
+JNIEXPORT jint JNICALL
+JVM_SocketShutdown(jint fd, jint howto);
+
+JNIEXPORT jint JNICALL
+JVM_Recv(jint fd, char *buf, jint nBytes, jint flags);
+
+JNIEXPORT jint JNICALL
+JVM_Send(jint fd, char *buf, jint nBytes, jint flags);
+
+JNIEXPORT jint JNICALL
+JVM_Timeout(int fd, long timeout);
+
+JNIEXPORT jint JNICALL
+JVM_Listen(jint fd, jint count);
+
+JNIEXPORT jint JNICALL
+JVM_Connect(jint fd, struct sockaddr *him, jint len);
+
+JNIEXPORT jint JNICALL
+JVM_Bind(jint fd, struct sockaddr *him, jint len);
+
+JNIEXPORT jint JNICALL
+JVM_Accept(jint fd, struct sockaddr *him, jint *len);
+
+JNIEXPORT jint JNICALL
+JVM_RecvFrom(jint fd, char *buf, int nBytes,
+                  int flags, struct sockaddr *from, int *fromlen);
+
+JNIEXPORT jint JNICALL
+JVM_SendTo(jint fd, char *buf, int len,
+                int flags, struct sockaddr *to, int tolen);
+
+JNIEXPORT jint JNICALL
+JVM_SocketAvailable(jint fd, jint *result);
+
+
+JNIEXPORT jint JNICALL
+JVM_GetSockName(jint fd, struct sockaddr *him, int *len);
+
+JNIEXPORT jint JNICALL
+JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen);
+
+JNIEXPORT jint JNICALL
+JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen);
+
+/*
+ * These routines are only reentrant on Windows
+ */
+
+#ifdef WIN32
+
+JNIEXPORT struct protoent * JNICALL
+JVM_GetProtoByName(char* name);
+
+JNIEXPORT struct hostent* JNICALL
+JVM_GetHostByAddr(const char* name, int len, int type);
+
+JNIEXPORT struct hostent* JNICALL
+JVM_GetHostByName(char* name);
+
+#endif /* _WINDOWS */
+
+JNIEXPORT int JNICALL
+JVM_GetHostName(char* name, int namelen);
+
+/*
+ * The standard printing functions supported by the Java VM. (Should they
+ * be renamed to JVM_* in the future?
+ */
+
+/*
+ * BE CAREFUL! The following functions do not implement the
+ * full feature set of standard C printf formats.
+ */
+int
+jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
+
+int
+jio_snprintf(char *str, size_t count, const char *fmt, ...);
+
+int
+jio_fprintf(FILE *, const char *fmt, ...);
+
+int
+jio_vfprintf(FILE *, const char *fmt, va_list args);
+
+
+JNIEXPORT void * JNICALL
+JVM_RawMonitorCreate(void);
+
+JNIEXPORT void JNICALL
+JVM_RawMonitorDestroy(void *mon);
+
+JNIEXPORT jint JNICALL
+JVM_RawMonitorEnter(void *mon);
+
+JNIEXPORT void JNICALL
+JVM_RawMonitorExit(void *mon);
+
+/*
+ * java.lang.management support
+ */
+JNIEXPORT void* JNICALL
+JVM_GetManagement(jint version);
+
+/*
+ * com.sun.tools.attach.VirtualMachine support
+ *
+ * Initialize the agent properties with the properties maintained in the VM.
+ */
+JNIEXPORT jobject JNICALL
+JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
+
+/* Generics reflection support.
+ *
+ * Returns information about the given class's EnclosingMethod
+ * attribute, if present, or null if the class had no enclosing
+ * method.
+ *
+ * If non-null, the returned array contains three elements. Element 0
+ * is the java.lang.Class of which the enclosing method is a member,
+ * and elements 1 and 2 are the java.lang.Strings for the enclosing
+ * method's name and descriptor, respectively.
+ */
+JNIEXPORT jobjectArray JNICALL
+JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
+
+/*
+ * Java thread state support
+ */
+enum {
+    JAVA_THREAD_STATE_NEW           = 0,
+    JAVA_THREAD_STATE_RUNNABLE      = 1,
+    JAVA_THREAD_STATE_BLOCKED       = 2,
+    JAVA_THREAD_STATE_WAITING       = 3,
+    JAVA_THREAD_STATE_TIMED_WAITING = 4,
+    JAVA_THREAD_STATE_TERMINATED    = 5,
+    JAVA_THREAD_STATE_COUNT         = 6
+};
+
+/*
+ * Returns an array of the threadStatus values representing the
+ * given Java thread state.  Returns NULL if the VM version is
+ * incompatible with the JDK or doesn't support the given
+ * Java thread state.
+ */
+JNIEXPORT jintArray JNICALL
+JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState);
+
+/*
+ * Returns an array of the substate names representing the
+ * given Java thread state.  Returns NULL if the VM version is
+ * incompatible with the JDK or the VM doesn't support
+ * the given Java thread state.
+ * values must be the jintArray returned from JVM_GetThreadStateValues
+ * and javaThreadState.
+ */
+JNIEXPORT jobjectArray JNICALL
+JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values);
+
+/* =========================================================================
+ * The following defines a private JVM interface that the JDK can query
+ * for the JVM version and capabilities.  sun.misc.Version defines
+ * the methods for getting the VM version and its capabilities.
+ *
+ * When a new bit is added, the following should be updated to provide
+ * access to the new capability:
+ *    HS:   JVM_GetVersionInfo and Abstract_VM_Version class
+ *    SDK:  Version class
+ *
+ * Similary, a private JDK interface JDK_GetVersionInfo0 is defined for
+ * JVM to query for the JDK version and capabilities.
+ *
+ * When a new bit is added, the following should be updated to provide
+ * access to the new capability:
+ *    HS:   JDK_Version class
+ *    SDK:  JDK_GetVersionInfo0
+ *
+ * ==========================================================================
+ */
+typedef struct {
+    /* Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx */
+    unsigned int jvm_version;   /* Consists of major, minor, micro (n.n.n) */
+                                /* and build number (xx) */
+    unsigned int update_version : 8;         /* Update release version (uu) */
+    unsigned int special_update_version : 8; /* Special update release version (c)*/
+    unsigned int reserved1 : 16;
+    unsigned int reserved2;
+
+    /* The following bits represents JVM supports that JDK has dependency on.
+     * JDK can use these bits to determine which JVM version
+     * and support it has to maintain runtime compatibility.
+     *
+     * When a new bit is added in a minor or update release, make sure
+     * the new bit is also added in the main/baseline.
+     */
+    unsigned int is_attach_supported : 1;
+    unsigned int is_kernel_jvm : 1;
+    unsigned int : 30;
+    unsigned int : 32;
+    unsigned int : 32;
+} jvm_version_info;
+
+#define JVM_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
+#define JVM_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
+#define JVM_VERSION_MICRO(version) ((version & 0x0000FF00) >> 8)
+
+/* Build number is available only for RE builds.
+ * It will be zero for internal builds.
+ */
+#define JVM_VERSION_BUILD(version) ((version & 0x000000FF))
+
+JNIEXPORT void JNICALL
+JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size);
+
+typedef struct {
+    // Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx
+    unsigned int jdk_version;   /* Consists of major, minor, micro (n.n.n) */
+                                /* and build number (xx) */
+    unsigned int update_version : 8;         /* Update release version (uu) */
+    unsigned int special_update_version : 8; /* Special update release version (c)*/
+    unsigned int reserved1 : 16;
+    unsigned int reserved2;
+
+    /* The following bits represents new JDK supports that VM has dependency on.
+     * VM implementation can use these bits to determine which JDK version
+     * and support it has to maintain runtime compatibility.
+     *
+     * When a new bit is added in a minor or update release, make sure
+     * the new bit is also added in the main/baseline.
+     */
+    unsigned int thread_park_blocker : 1;
+    unsigned int : 31;
+    unsigned int : 32;
+    unsigned int : 32;
+} jdk_version_info;
+
+#define JDK_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
+#define JDK_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
+#define JDK_VERSION_MICRO(version) ((version & 0x0000FF00) >> 8)
+
+/* Build number is available only for RE build (i.e. JDK_BUILD_NUMBER is set to bNN)
+ * It will be zero for internal builds.
+ */
+#define JDK_VERSION_BUILD(version) ((version & 0x000000FF))
+
+/*
+ * This is the function JDK_GetVersionInfo0 defined in libjava.so
+ * that is dynamically looked up by JVM.
+ */
+typedef void (*jdk_version_info_fn_t)(jdk_version_info* info, size_t info_size);
+
+/*
+ * This structure is used by the launcher to get the default thread
+ * stack size from the VM using JNI_GetDefaultJavaVMInitArgs() with a
+ * version of 1.1.  As it is not supported otherwise, it has been removed
+ * from jni.h
+ */
+typedef struct JDK1_1InitArgs {
+    jint version;
+
+    char **properties;
+    jint checkSource;
+    jint nativeStackSize;
+    jint javaStackSize;
+    jint minHeapSize;
+    jint maxHeapSize;
+    jint verifyMode;
+    char *classpath;
+
+    jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
+    void (JNICALL *exit)(jint code);
+    void (JNICALL *abort)(void);
+
+    jint enableClassGC;
+    jint enableVerboseGC;
+    jint disableAsyncGC;
+    jint verbose;
+    jboolean debugging;
+    jint debugPort;
+} JDK1_1InitArgs;
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JVM_H_ */
Index: /tags/icedtea-web/beta/launcher/jvm_md.h
===================================================================
--- /tags/icedtea-web/beta/launcher/jvm_md.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/jvm_md.h	(revision 403)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997, 1999, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _JAVASOFT_JVM_MD_H_
+#define _JAVASOFT_JVM_MD_H_
+
+/*
+ * This file is currently collecting system-specific dregs for the
+ * JNI conversion, which should be sorted out later.
+ */
+
+#include <dirent.h>             /* For DIR */
+#include <sys/param.h>          /* For MAXPATHLEN */
+#include <unistd.h>             /* For F_OK, R_OK, W_OK */
+
+#define JNI_ONLOAD_SYMBOLS   {"JNI_OnLoad"}
+#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
+
+#define JNI_LIB_PREFIX "lib"
+#define JNI_LIB_SUFFIX ".so"
+
+#define JVM_MAXPATHLEN MAXPATHLEN
+
+#define JVM_R_OK    R_OK
+#define JVM_W_OK    W_OK
+#define JVM_X_OK    X_OK
+#define JVM_F_OK    F_OK
+
+/*
+ * File I/O
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/signal.h>
+
+/* O Flags */
+
+#define JVM_O_RDONLY     O_RDONLY
+#define JVM_O_WRONLY     O_WRONLY
+#define JVM_O_RDWR       O_RDWR
+#define JVM_O_O_APPEND   O_APPEND
+#define JVM_O_EXCL       O_EXCL
+#define JVM_O_CREAT      O_CREAT
+#define JVM_O_DELETE     0x10000
+
+/* Signals */
+
+#define JVM_SIGINT     SIGINT
+#define JVM_SIGTERM    SIGTERM
+
+
+#endif /* !_JAVASOFT_JVM_MD_H_ */
Index: /tags/icedtea-web/beta/launcher/manifest_info.h
===================================================================
--- /tags/icedtea-web/beta/launcher/manifest_info.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/manifest_info.h	(revision 403)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003, 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _MANIFEST_INFO_H
+#define _MANIFEST_INFO_H
+
+#include <sys/types.h>
+
+/*
+ * Zip file header signatures
+ */
+#define SIGSIZ 4                    /* size of all header signatures */
+#define LOCSIG 0x04034b50L          /* "PK\003\004" */
+#define EXTSIG 0x08074b50L          /* "PK\007\008" */
+#define CENSIG 0x02014b50L          /* "PK\001\002" */
+#define ENDSIG 0x06054b50L          /* "PK\005\006" */
+
+/*
+ * Header sizes including signatures
+ */
+#define LOCHDR 30
+#define EXTHDR 16
+#define CENHDR 46
+#define ENDHDR 22
+
+/*
+ * Header field access macros
+ */
+#define CH(b, n) (((unsigned char *)(b))[n])
+#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
+#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16))
+#define GETSIG(b) LG(b, 0)
+
+/*
+ * Macros for getting local file (LOC) header fields
+ */
+#define LOCVER(b) SH(b, 4)          /* version needed to extract */
+#define LOCFLG(b) SH(b, 6)          /* general purpose bit flags */
+#define LOCHOW(b) SH(b, 8)          /* compression method */
+#define LOCTIM(b) LG(b, 10)         /* modification time */
+#define LOCCRC(b) LG(b, 14)         /* crc of uncompressed data */
+#define LOCSIZ(b) LG(b, 18)         /* compressed data size */
+#define LOCLEN(b) LG(b, 22)         /* uncompressed data size */
+#define LOCNAM(b) SH(b, 26)         /* filename length */
+#define LOCEXT(b) SH(b, 28)         /* extra field length */
+
+/*
+ * Macros for getting extra local (EXT) header fields
+ */
+#define EXTCRC(b) LG(b, 4)          /* crc of uncompressed data */
+#define EXTSIZ(b) LG(b, 8)          /* compressed size */
+#define EXTLEN(b) LG(b, 12)         /* uncompressed size */
+
+/*
+ * Macros for getting central directory header (CEN) fields
+ */
+#define CENVEM(b) SH(b, 4)          /* version made by */
+#define CENVER(b) SH(b, 6)          /* version needed to extract */
+#define CENFLG(b) SH(b, 8)          /* general purpose bit flags */
+#define CENHOW(b) SH(b, 10)         /* compression method */
+#define CENTIM(b) LG(b, 12)         /* modification time */
+#define CENCRC(b) LG(b, 16)         /* crc of uncompressed data */
+#define CENSIZ(b) LG(b, 20)         /* compressed size */
+#define CENLEN(b) LG(b, 24)         /* uncompressed size */
+#define CENNAM(b) SH(b, 28)         /* length of filename */
+#define CENEXT(b) SH(b, 30)         /* length of extra field */
+#define CENCOM(b) SH(b, 32)         /* file comment length */
+#define CENDSK(b) SH(b, 34)         /* disk number start */
+#define CENATT(b) SH(b, 36)         /* internal file attributes */
+#define CENATX(b) LG(b, 38)         /* external file attributes */
+#define CENOFF(b) LG(b, 42)         /* offset of local header */
+
+/*
+ * Macros for getting end of central directory header (END) fields
+ */
+#define ENDSUB(b) SH(b, 8)          /* number of entries on this disk */
+#define ENDTOT(b) SH(b, 10)         /* total number of entries */
+#define ENDSIZ(b) LG(b, 12)         /* central directory size */
+#define ENDOFF(b) LG(b, 16)         /* central directory offset */
+#define ENDCOM(b) SH(b, 20)         /* size of zip file comment */
+
+/*
+ * A comment of maximum length of 64kb can follow the END record. This
+ * is the furthest the END record can be from the end of the file.
+ */
+#define END_MAXLEN      (0xFFFF + ENDHDR)
+
+/*
+ * Supported compression methods.
+ */
+#define STORED      0
+#define DEFLATED    8
+
+/*
+ * Information from the CEN entry to inflate a file.
+ */
+typedef struct zentry { /* Zip file entry */
+    size_t      isize;  /* size of inflated data */
+    size_t      csize;  /* size of compressed data (zero if uncompressed) */
+    off_t       offset; /* position of compressed data */
+    int         how;    /* compression method (if any) */
+} zentry;
+
+/*
+ * Information returned from the Manifest file by the ParseManifest() routine.
+ * Certainly (much) more could be returned, but this is the information
+ * currently of interest to the C based Java utilities (particularly the
+ * Java launcher).
+ */
+typedef struct manifest_info {  /* Interesting fields from the Manifest */
+    char        *manifest_version;      /* Manifest-Version string */
+    char        *main_class;            /* Main-Class entry */
+    char        *jre_version;           /* Appropriate J2SE release spec */
+    char        jre_restrict_search;    /* Restricted JRE search */
+    char        *splashscreen_image_file_name; /* splashscreen image file */
+} manifest_info;
+
+/*
+ * Attribute closure to provide to manifest_iterate.
+ */
+typedef void (*attribute_closure)(const char *name, const char *value,
+        void *user_data);
+
+/*
+ * Function prototypes.
+ */
+int     JLI_ParseManifest(char *jarfile, manifest_info *info);
+void    *JLI_JarUnpackFile(const char *jarfile, const char *filename,
+                int *size);
+void    JLI_FreeManifest(void);
+int     JLI_ManifestIterate(const char *jarfile, attribute_closure ac,
+                void *user_data);
+
+#endif  /* _MANIFEST_INFO_H */
Index: /tags/icedtea-web/beta/launcher/parse_manifest.c
===================================================================
--- /tags/icedtea-web/beta/launcher/parse_manifest.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/parse_manifest.c	(revision 403)
@@ -0,0 +1,610 @@
+/*
+ * Copyright (c) 2003, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * If Windows is POSIX compliant, why isn't the prototype for lseek where
+ * POSIX says it should be?
+ */
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#else   /* Unix */
+#include <unistd.h>
+#endif  /* Unix */
+
+#include <zlib.h>
+#include "manifest_info.h"
+
+/*
+ * On Windows, str[n]casecmp() are known as str[n]icmp().
+ */
+#ifdef _WIN32
+#define strcasecmp(p1, p2)      stricmp((p1), (p2))
+#define strncasecmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
+#endif
+
+static char     *manifest;
+
+static const char       *manifest_name = "META-INF/MANIFEST.MF";
+
+/*
+ * Inflate the manifest file (or any file for that matter).
+ *
+ *   fd:        File descriptor of the jar file.
+ *   entry:     Contains the information necessary to perform the inflation
+ *              (the compressed and uncompressed sizes and the offset in
+ *              the file where the compressed data is located).
+ *   size_out:  Returns the size of the inflated file.
+ *
+ * Upon success, it returns a pointer to a NUL-terminated malloc'd buffer
+ * containing the inflated manifest file.  When the caller is done with it,
+ * this buffer should be released by a call to free().  Upon failure,
+ * returns NULL.
+ */
+static char *
+inflate_file(int fd, zentry *entry, int *size_out)
+{
+    char        *in;
+    char        *out;
+    z_stream    zs;
+
+    if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+        return (NULL);
+    if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
+        return (NULL);
+    if ((in = malloc(entry->csize + 1)) == NULL)
+        return (NULL);
+    if ((size_t)(read(fd, in, (unsigned int)entry->csize)) != entry->csize) {
+        free(in);
+        return (NULL);
+    }
+    if (entry->how == STORED) {
+        *(char *)((size_t)in + entry->csize) = '\0';
+        if (size_out) {
+            *size_out = entry->csize;
+        }
+        return (in);
+    } else if (entry->how == DEFLATED) {
+        zs.zalloc = (alloc_func)Z_NULL;
+        zs.zfree = (free_func)Z_NULL;
+        zs.opaque = (voidpf)Z_NULL;
+        zs.next_in = (Byte*)in;
+        zs.avail_in = (uInt)entry->csize;
+        if (inflateInit2(&zs, -MAX_WBITS) < 0) {
+            free(in);
+            return (NULL);
+        }
+        if ((out = malloc(entry->isize + 1)) == NULL) {
+            free(in);
+            return (NULL);
+        }
+        zs.next_out = (Byte*)out;
+        zs.avail_out = (uInt)entry->isize;
+        if (inflate(&zs, Z_PARTIAL_FLUSH) < 0) {
+            free(in);
+            free(out);
+            return (NULL);
+        }
+        *(char *)((size_t)out + entry->isize) = '\0';
+        free(in);
+        if (inflateEnd(&zs) < 0) {
+            free(out);
+            return (NULL);
+        }
+        if (size_out) {
+            *size_out = entry->isize;
+        }
+        return (out);
+    } else
+        return (NULL);
+}
+
+/*
+ * A very little used routine to handle the case that zip file has
+ * a comment at the end. Believe it or not, the only way to find the
+ * END record is to walk backwards, byte by bloody byte looking for
+ * the END record signature.
+ *
+ *      fd:     File descriptor of the jar file.
+ *      eb:     Pointer to a buffer to receive a copy of the END header.
+ *
+ * Returns the offset of the END record in the file on success,
+ * -1 on failure.
+ */
+static off_t
+find_end(int fd, Byte *eb)
+{
+    off_t   len;
+    off_t   pos;
+    off_t   flen;
+    int     bytes;
+    Byte    *cp;
+    Byte    *endpos;
+    Byte    *buffer;
+
+    /*
+     * 99.44% (or more) of the time, there will be no comment at the
+     * end of the zip file.  Try reading just enough to read the END
+     * record from the end of the file.
+     */
+    if ((pos = lseek(fd, -ENDHDR, SEEK_END)) < (off_t)0)
+        return (-1);
+    if ((bytes = read(fd, eb, ENDHDR)) < 0)
+        return (-1);
+    if (GETSIG(eb) == ENDSIG)
+        return (pos);
+
+    /*
+     * Shucky-Darn,... There is a comment at the end of the zip file.
+     *
+     * Allocate and fill a buffer with enough of the zip file
+     * to meet the specification for a maximal comment length.
+     */
+    if ((flen = lseek(fd, 0, SEEK_END)) < (off_t)0)
+        return (-1);
+    len = (flen < END_MAXLEN) ? flen : END_MAXLEN;
+    if (lseek(fd, -len, SEEK_END) < (off_t)0)
+        return (-1);
+    if ((buffer = malloc(END_MAXLEN)) == NULL)
+        return (-1);
+    if ((bytes = read(fd, buffer, len)) < 0) {
+        free(buffer);
+        return (-1);
+    }
+
+    /*
+     * Search backwards from the end of file stopping when the END header
+     * signature is found. (The first condition of the "if" is just a
+     * fast fail, because the GETSIG macro isn't always cheap.  The
+     * final condition protects against false positives.)
+     */
+    endpos = &buffer[bytes];
+    for (cp = &buffer[bytes - ENDHDR]; cp >= &buffer[0]; cp--)
+        if ((*cp == (ENDSIG & 0xFF)) && (GETSIG(cp) == ENDSIG) &&
+          (cp + ENDHDR + ENDCOM(cp) == endpos)) {
+            (void) memcpy(eb, cp, ENDHDR);
+            free(buffer);
+            return (flen - (endpos - cp));
+        }
+    free(buffer);
+    return (-1);
+}
+
+/*
+ * Locate the manifest file with the zip/jar file.
+ *
+ *      fd:     File descriptor of the jar file.
+ *      entry:  To be populated with the information necessary to perform
+ *              the inflation (the compressed and uncompressed sizes and
+ *              the offset in the file where the compressed data is located).
+ *
+ * Returns zero upon success. Returns a negative value upon failure.
+ *
+ * The buffer for reading the Central Directory if the zip/jar file needs
+ * to be large enough to accommodate the largest possible single record
+ * and the signature of the next record which is:
+ *
+ *      3*2**16 + CENHDR + SIGSIZ
+ *
+ * Each of the three variable sized fields (name, comment and extension)
+ * has a maximum possible size of 64k.
+ *
+ * Typically, only a small bit of this buffer is used with bytes shuffled
+ * down to the beginning of the buffer.  It is one thing to allocate such
+ * a large buffer and another thing to actually start faulting it in.
+ *
+ * In most cases, all that needs to be read are the first two entries in
+ * a typical jar file (META-INF and META-INF/MANIFEST.MF). Keep this factoid
+ * in mind when optimizing this code.
+ */
+#define BUFSIZE (3 * 65536 + CENHDR + SIGSIZ)
+#define MINREAD 1024
+
+static int
+find_file(int fd, zentry *entry, const char *file_name)
+{
+    int     bytes;
+    int     res;
+    int     entry_size;
+    int     read_size;
+    int     base_offset;
+    Byte    *p;
+    Byte    *bp;
+    Byte    buffer[BUFSIZE];
+    Byte    locbuf[LOCHDR];
+
+    p = buffer;
+    bp = buffer;
+
+    /*
+     * Read the END Header, which is the starting point for ZIP files.
+     * (Clearly designed to make writing a zip file easier than reading
+     * one. Now isn't that precious...)
+     */
+    if ((base_offset = find_end(fd, bp)) == -1)
+        return (-1);
+
+    /*
+     * There is a historical, but undocumented, ability to allow for
+     * additional "stuff" to be prepended to the zip/jar file. It seems
+     * that this has been used to prepend an actual java launcher
+     * executable to the jar on Windows.  Although this is just another
+     * form of statically linking a small piece of the JVM to the
+     * application, we choose to continue to support it.  Note that no
+     * guarantees have been made (or should be made) to the customer that
+     * this will continue to work.
+     *
+     * Therefore, calculate the base offset of the zip file (within the
+     * expanded file) by assuming that the central directory is followed
+     * immediately by the end record.
+     */
+    base_offset = base_offset - ENDSIZ(p) - ENDOFF(p);
+
+    /*
+     * The END Header indicates the start of the Central Directory
+     * Headers. Remember that the desired Central Directory Header (CEN)
+     * will almost always be the second one and the first one is a small
+     * directory entry ("META-INF/"). Keep the code optimized for
+     * that case.
+     *
+     * Begin by seeking to the beginning of the Central Directory and
+     * reading in the first buffer full of bits.
+     */
+    if (lseek(fd, base_offset + ENDOFF(p), SEEK_SET) < (off_t)0)
+        return (-1);
+    if ((bytes = read(fd, bp, MINREAD)) < 0)
+        return (-1);
+
+    /*
+     * Loop through the Central Directory Headers. Note that a valid zip/jar
+     * must have an ENDHDR (with ENDSIG) after the Central Directory.
+     */
+    while (GETSIG(p) == CENSIG) {
+
+        /*
+         * If a complete header isn't in the buffer, shift the contents
+         * of the buffer down and refill the buffer.  Note that the check
+         * for "bytes < CENHDR" must be made before the test for the entire
+         * size of the header, because if bytes is less than CENHDR, the
+         * actual size of the header can't be determined. The addition of
+         * SIGSIZ guarantees that the next signature is also in the buffer
+         * for proper loop termination.
+         */
+        if (bytes < CENHDR) {
+            p = memmove(bp, p, bytes);
+            if ((res = read(fd, bp + bytes, MINREAD)) <= 0)
+                return (-1);
+            bytes += res;
+        }
+        entry_size = CENHDR + CENNAM(p) + CENEXT(p) + CENCOM(p);
+        if (bytes < entry_size + SIGSIZ) {
+            if (p != bp)
+                p = memmove(bp, p, bytes);
+            read_size = entry_size - bytes + SIGSIZ;
+            read_size = (read_size < MINREAD) ? MINREAD : read_size;
+            if ((res = read(fd, bp + bytes,  read_size)) <= 0)
+                return (-1);
+            bytes += res;
+        }
+
+        /*
+         * Check if the name is the droid we are looking for; the jar file
+         * manifest.  If so, build the entry record from the data found in
+         * the header located and return success.
+         */
+        if (CENNAM(p) == strlen(file_name) &&
+          memcmp((p + CENHDR), file_name, strlen(file_name)) == 0) {
+            if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0)
+                return (-1);
+            if (read(fd, locbuf, LOCHDR) < 0)
+                return (-1);
+            if (GETSIG(locbuf) != LOCSIG)
+                return (-1);
+            entry->isize = CENLEN(p);
+            entry->csize = CENSIZ(p);
+            entry->offset = base_offset + CENOFF(p) + LOCHDR +
+                LOCNAM(locbuf) + LOCEXT(locbuf);
+            entry->how = CENHOW(p);
+            return (0);
+        }
+
+        /*
+         * Point to the next entry and decrement the count of valid remaining
+         * bytes.
+         */
+        bytes -= entry_size;
+        p += entry_size;
+    }
+
+    return (-1);        /* Fell off the end the loop without a Manifest */
+}
+
+/*
+ * Parse a Manifest file header entry into a distinct "name" and "value".
+ * Continuation lines are joined into a single "value". The documented
+ * syntax for a header entry is:
+ *
+ *      header: name ":" value
+ *
+ *      name: alphanum *headerchar
+ *
+ *      value: SPACE *otherchar newline *continuation
+ *
+ *      continuation: SPACE *otherchar newline
+ *
+ *      newline: CR LF | LF | CR (not followed by LF)
+ *
+ *      alphanum: {"A"-"Z"} | {"a"-"z"} | {"0"-"9"}
+ *
+ *      headerchar: alphanum | "-" | "_"
+ *
+ *      otherchar: any UTF-8 character except NUL, CR and LF
+ *
+ * Note that a manifest file may be composed of multiple sections,
+ * each of which may contain multiple headers.
+ *
+ *      section: *header +newline
+ *
+ *      nonempty-section: +header +newline
+ *
+ * (Note that the point of "nonempty-section" is unclear, because it isn't
+ * referenced elsewhere in the full specification for the Manifest file.)
+ *
+ * Arguments:
+ *      lp      pointer to a character pointer which points to the start
+ *              of a valid header.
+ *      name    pointer to a character pointer which will be set to point
+ *              to the name portion of the header (nul terminated).
+ *      value   pointer to a character pointer which will be set to point
+ *              to the value portion of the header (nul terminated).
+ *
+ * Returns:
+ *    1 Successful parsing of an NV pair.  lp is updated to point to the
+ *      next character after the terminating newline in the string
+ *      representing the Manifest file. name and value are updated to
+ *      point to the strings parsed.
+ *    0 A valid end of section indicator was encountered.  lp, name, and
+ *      value are not modified.
+ *   -1 lp does not point to a valid header. Upon return, the values of
+ *      lp, name, and value are undefined.
+ */
+static int
+parse_nv_pair(char **lp, char **name, char **value)
+{
+    char    *nl;
+    char    *cp;
+
+    /*
+     * End of the section - return 0. The end of section condition is
+     * indicated by either encountering a blank line or the end of the
+     * Manifest "string" (EOF).
+     */
+    if (**lp == '\0' || **lp == '\n' || **lp == '\r')
+        return (0);
+
+    /*
+     * Getting to here, indicates that *lp points to an "otherchar".
+     * Turn the "header" into a string on its own.
+     */
+    nl = strpbrk(*lp, "\n\r");
+    if (nl == NULL) {
+        nl = strchr(*lp, (int)'\0');
+    } else {
+        cp = nl;                        /* For merging continuation lines */
+        if (*nl == '\r' && *(nl+1) == '\n')
+            *nl++ = '\0';
+        *nl++ = '\0';
+
+        /*
+         * Process any "continuation" line(s), by making them part of the
+         * "header" line. Yes, I know that we are "undoing" the NULs we
+         * just placed here, but continuation lines are the fairly rare
+         * case, so we shouldn't unnecessarily complicate the code above.
+         *
+         * Note that an entire continuation line is processed each iteration
+         * through the outer while loop.
+         */
+        while (*nl == ' ') {
+            nl++;                       /* First character to be moved */
+            while (*nl != '\n' && *nl != '\r' && *nl != '\0')
+                *cp++ = *nl++;          /* Shift string */
+            if (*nl == '\0')
+                return (-1);            /* Error: newline required */
+            *cp = '\0';
+            if (*nl == '\r' && *(nl+1) == '\n')
+                *nl++ = '\0';
+            *nl++ = '\0';
+        }
+    }
+
+    /*
+     * Separate the name from the value;
+     */
+    cp = strchr(*lp, (int)':');
+    if (cp == NULL)
+        return (-1);
+    *cp++ = '\0';               /* The colon terminates the name */
+    if (*cp != ' ')
+        return (-1);
+    *cp++ = '\0';               /* Eat the required space */
+    *name = *lp;
+    *value = cp;
+    *lp = nl;
+    return (1);
+}
+
+/*
+ * Read the manifest from the specified jar file and fill in the manifest_info
+ * structure with the information found within.
+ *
+ * Error returns are as follows:
+ *    0 Success
+ *   -1 Unable to open jarfile
+ *   -2 Error accessing the manifest from within the jarfile (most likely
+ *      a manifest is not present, or this isn't a valid zip/jar file).
+ */
+int
+JLI_ParseManifest(char *jarfile, manifest_info *info)
+{
+    int     fd;
+    zentry  entry;
+    char    *lp;
+    char    *name;
+    char    *value;
+    int     rc;
+    char    *splashscreen_name = NULL;
+
+    if ((fd = open(jarfile, O_RDONLY
+#ifdef O_BINARY
+        | O_BINARY /* use binary mode on windows */
+#endif
+        )) == -1)
+        return (-1);
+
+    info->manifest_version = NULL;
+    info->main_class = NULL;
+    info->jre_version = NULL;
+    info->jre_restrict_search = 0;
+    info->splashscreen_image_file_name = NULL;
+    if (rc = find_file(fd, &entry, manifest_name) != 0) {
+        close(fd);
+        return (-2);
+    }
+    manifest = inflate_file(fd, &entry, NULL);
+    if (manifest == NULL) {
+        close(fd);
+        return (-2);
+    }
+    lp = manifest;
+    while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
+        if (strcasecmp(name, "Manifest-Version") == 0)
+            info->manifest_version = value;
+        else if (strcasecmp(name, "Main-Class") == 0)
+            info->main_class = value;
+        else if (strcasecmp(name, "JRE-Version") == 0)
+            info->jre_version = value;
+        else if (strcasecmp(name, "JRE-Restrict-Search") == 0) {
+            if (strcasecmp(value, "true") == 0)
+                info->jre_restrict_search = 1;
+        } else if (strcasecmp(name, "Splashscreen-Image") == 0) {
+            info->splashscreen_image_file_name = value;
+        }
+    }
+    close(fd);
+    if (rc == 0)
+        return (0);
+    else
+        return (-2);
+}
+
+/*
+ * Opens the jar file and unpacks the specified file from its contents.
+ * Returns NULL on failure.
+ */
+void *
+JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) {
+    int     fd;
+    zentry  entry;
+    void    *data = NULL;
+
+    fd = open(jarfile, O_RDONLY
+#ifdef O_BINARY
+        | O_BINARY /* use binary mode on windows */
+#endif
+        );
+    if (fd != -1 && find_file(fd, &entry, filename) == 0) {
+        data = inflate_file(fd, &entry, size);
+    }
+    close(fd);
+    return (data);
+}
+
+/*
+ * Specialized "free" function.
+ */
+void
+JLI_FreeManifest()
+{
+    if (manifest)
+        free(manifest);
+}
+
+/*
+ * Iterate over the manifest of the specified jar file and invoke the provided
+ * closure function for each attribute encountered.
+ *
+ * Error returns are as follows:
+ *    0 Success
+ *   -1 Unable to open jarfile
+ *   -2 Error accessing the manifest from within the jarfile (most likely
+ *      this means a manifest is not present, or it isn't a valid zip/jar file).
+ */
+int
+JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
+{
+    int     fd;
+    zentry  entry;
+    char    *mp;        /* manifest pointer */
+    char    *lp;        /* pointer into manifest, updated during iteration */
+    char    *name;
+    char    *value;
+    int     rc;
+
+    if ((fd = open(jarfile, O_RDONLY
+#ifdef O_BINARY
+        | O_BINARY /* use binary mode on windows */
+#endif
+        )) == -1)
+        return (-1);
+
+    if (rc = find_file(fd, &entry, manifest_name) != 0) {
+        close(fd);
+        return (-2);
+    }
+
+    mp = inflate_file(fd, &entry, NULL);
+    if (mp == NULL) {
+        close(fd);
+        return (-2);
+    }
+
+    lp = mp;
+    while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
+        (*ac)(name, value, user_data);
+    }
+    free(mp);
+    close(fd);
+    if (rc == 0)
+        return (0);
+    else
+        return (-2);
+}
Index: /tags/icedtea-web/beta/launcher/splashscreen.h
===================================================================
--- /tags/icedtea-web/beta/launcher/splashscreen.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/splashscreen.h	(revision 403)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+
+int     DoSplashLoadMemory(void* pdata, int size); /* requires preloading the file */
+int     DoSplashLoadFile(const char* filename);
+void    DoSplashInit(void);
+void    DoSplashClose(void);
+void    DoSplashSetFileJarName(const char* fileName, const char* jarName);
Index: /tags/icedtea-web/beta/launcher/splashscreen_stubs.c
===================================================================
--- /tags/icedtea-web/beta/launcher/splashscreen_stubs.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/splashscreen_stubs.c	(revision 403)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include "splashscreen.h"
+
+extern void* SplashProcAddress(const char* name); /* in java_md.c */
+
+/*
+ * Prototypes of pointers to functions in splashscreen shared lib
+ */
+typedef int (*SplashLoadMemory_t)(void* pdata, int size);
+typedef int (*SplashLoadFile_t)(const char* filename);
+typedef void (*SplashInit_t)(void);
+typedef void (*SplashClose_t)(void);
+typedef void (*SplashSetFileJarName_t)(const char* fileName,
+                                       const char* jarName);
+
+/*
+ * This macro invokes a function from the shared lib.
+ * it locates a function with SplashProcAddress on demand.
+ * if SplashProcAddress fails, def value is returned.
+ *
+ * it is further wrapped with INVOKEV (works with functions which return
+ * void and INVOKE (for all other functions). INVOKEV looks a bit ugly,
+ * that's due being unable to return a value of type void in C. INVOKEV
+ * works around this by using semicolon instead of return operator.
+ */
+#define _INVOKE(name,def,ret) \
+    static void* proc = NULL; \
+    if (!proc) { proc = SplashProcAddress(#name); } \
+    if (!proc) { return def; } \
+    ret ((name##_t)proc)
+
+#define INVOKE(name,def) _INVOKE(name,def,return)
+#define INVOKEV(name) _INVOKE(name, ,;)
+
+int     DoSplashLoadMemory(void* pdata, int size) {
+    INVOKE(SplashLoadMemory,0)(pdata, size);
+}
+
+int     DoSplashLoadFile(const char* filename) {
+    INVOKE(SplashLoadFile,0)(filename);
+}
+
+void    DoSplashInit(void) {
+    INVOKEV(SplashInit)();
+}
+
+void    DoSplashClose(void) {
+    INVOKEV(SplashClose)();
+}
+
+void    DoSplashSetFileJarName(const char* fileName, const char* jarName) {
+    INVOKEV(SplashSetFileJarName)(fileName, jarName);
+}
Index: /tags/icedtea-web/beta/launcher/version_comp.c
===================================================================
--- /tags/icedtea-web/beta/launcher/version_comp.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/version_comp.c	(revision 403)
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2003, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "jni.h"
+#include "jli_util.h"
+#include "version_comp.h"
+
+/*
+ *      A collection of useful strings. One should think of these as #define
+ *      entries, but actual strings can be more efficient (with many compilers).
+ */
+static const char *separators   = ".-_";
+static const char *zero_string  = "0";
+
+/*
+ *      Validate a string as parsable as a "Java int". If so parsable,
+ *      return true (non-zero) and store the numeric value at the address
+ *      passed in as "value"; otherwise return false (zero).
+ *
+ *      Note that the maximum allowable value is 2147483647 as defined by
+ *      the "Java Language Specification" which precludes the use of native
+ *      conversion routines which may have other limits.
+ *
+ *      Also note that we don't have to worry about the alternate maximum
+ *      allowable value of 2147483648 because it is only allowed after
+ *      the unary negation operator and this grammar doesn't have one
+ *      of those.
+ *
+ *      Finally, note that a value which exceeds the maximum jint value will
+ *      return false (zero). This results in the otherwise purely numeric
+ *      string being compared as a string of characters (as per the spec.)
+ */
+static int
+isjavaint(const char *s, jint *value)
+{
+    jlong sum = 0;
+    jint digit;
+    while (*s != '\0')
+        if (isdigit(*s)) {
+            digit = (jint)((int)(*s++) - (int)('0'));
+            sum = (sum * 10) + digit;
+            if (sum > 2147483647)
+                return (0);     /* Overflows jint (but not jlong) */
+        } else
+            return (0);
+    *value = (jint)sum;
+    return (1);
+}
+
+/*
+ *      Modeled after strcmp(), compare two strings (as in the grammar defined
+ *      in Appendix A of JSR 56).  If both strings can be interpreted as
+ *      Java ints, do a numeric comparison, else it is strcmp().
+ */
+static int
+comp_string(const char *s1, const char *s2)
+{
+    jint v1, v2;
+    if (isjavaint(s1, &v1) && isjavaint(s2, &v2))
+        return ((int)(v1 - v2));
+    else
+        return (strcmp(s1, s2));
+}
+
+/*
+ *      Modeled after strcmp(), compare two version-ids for a Prefix
+ *      Match as defined in JSR 56.
+ */
+int
+JLI_PrefixVersionId(char *id1, char *id2)
+{
+    char        *s1 = JLI_StringDup(id1);
+    char        *s2 = JLI_StringDup(id2);
+    char        *m1 = s1;
+    char        *m2 = s2;
+    char        *end1 = NULL;
+    char        *end2 = NULL;
+    int res = 0;
+
+    do {
+
+        if ((s1 != NULL) && ((end1 = strpbrk(s1, ".-_")) != NULL))
+            *end1 = '\0';
+        if ((s2 != NULL) && ((end2 = strpbrk(s2, ".-_")) != NULL))
+            *end2 = '\0';
+
+        res = comp_string(s1, s2);
+
+        if (end1 != NULL)
+            s1 = end1 + 1;
+        else
+            s1 = NULL;
+        if (end2 != NULL)
+            s2 = end2 + 1;
+        else
+            s2 = NULL;
+
+    } while (res == 0 && ((s1 != NULL) && (s2 != NULL)));
+
+    JLI_MemFree(m1);
+    JLI_MemFree(m2);
+    return (res);
+}
+
+/*
+ *      Modeled after strcmp(), compare two version-ids for an Exact
+ *      Match as defined in JSR 56.
+ */
+int
+JLI_ExactVersionId(char *id1, char *id2)
+{
+    char        *s1 = JLI_StringDup(id1);
+    char        *s2 = JLI_StringDup(id2);
+    char        *m1 = s1;
+    char        *m2 = s2;
+    char        *end1 = NULL;
+    char        *end2 = NULL;
+    int res = 0;
+
+    do {
+
+        if ((s1 != NULL) && ((end1 = strpbrk(s1, separators)) != NULL))
+            *end1 = '\0';
+        if ((s2 != NULL) && ((end2 = strpbrk(s2, separators)) != NULL))
+            *end2 = '\0';
+
+        if ((s1 != NULL) && (s2 == NULL))
+            res = comp_string(s1, zero_string);
+        else if ((s1 == NULL) && (s2 != NULL))
+            res = comp_string(zero_string, s2);
+        else
+            res = comp_string(s1, s2);
+
+        if (end1 != NULL)
+            s1 = end1 + 1;
+        else
+            s1 = NULL;
+        if (end2 != NULL)
+            s2 = end2 + 1;
+        else
+            s2 = NULL;
+
+    } while (res == 0 && ((s1 != NULL) || (s2 != NULL)));
+
+    JLI_MemFree(m1);
+    JLI_MemFree(m2);
+    return (res);
+}
+
+/*
+ *      Return true if this simple-element (as defined in JSR 56) forms
+ *      an acceptable match.
+ *
+ *      JSR 56 is modified by the Java Web Start <rel> Developer Guide
+ *      where it is stated "... Java Web Start will not consider an installed
+ *      non-FCS (i.e., milestone) JRE as a match. ... a JRE from Sun
+ *      Microsystems, Inc., is by convention a non-FCS (milestone) JRE
+ *      if there is a dash (-) in the version string."
+ *
+ *      An undocumented caveat to the above is that an exact match with a
+ *      hyphen is accepted as a development extension.
+ *
+ *      These modifications are addressed by the specific comparisons
+ *      for releases with hyphens.
+ */
+static int
+acceptable_simple_element(char *release, char *simple_element)
+{
+    char        *modifier;
+    modifier = simple_element + strlen(simple_element) - 1;
+    if (*modifier == '*') {
+        *modifier = '\0';
+        if (strchr(release, '-'))
+            return ((strcmp(release, simple_element) == 0)?1:0);
+        return ((JLI_PrefixVersionId(release, simple_element) == 0)?1:0);
+    } else if (*modifier == '+') {
+        *modifier = '\0';
+        if (strchr(release, '-'))
+            return ((strcmp(release, simple_element) == 0)?1:0);
+        return ((JLI_ExactVersionId(release, simple_element) >= 0)?1:0);
+    } else {
+        return ((JLI_ExactVersionId(release, simple_element) == 0)?1:0);
+    }
+}
+
+/*
+ *      Return true if this element (as defined in JSR 56) forms
+ *      an acceptable match. An element is the intersection (and)
+ *      of multiple simple-elements.
+ */
+static int
+acceptable_element(char *release, char *element)
+{
+    char        *end;
+    do {
+        if ((end = strchr(element, '&')) != NULL)
+            *end = '\0';
+        if (!acceptable_simple_element(release, element))
+            return (0);
+        if (end != NULL)
+            element = end + 1;
+    } while (end != NULL);
+    return (1);
+}
+
+/*
+ *      Checks if release is acceptable by the specification version-string.
+ *      Return true if this version-string (as defined in JSR 56) forms
+ *      an acceptable match. A version-string is the union (or) of multiple
+ *      elements.
+ */
+int
+JLI_AcceptableRelease(char *release, char *version_string)
+{
+    char        *vs;
+    char        *m1;
+    char        *end;
+    m1 = vs = JLI_StringDup(version_string);
+    do {
+        if ((end = strchr(vs, ' ')) != NULL)
+            *end = '\0';
+        if (acceptable_element(release, vs)) {
+            JLI_MemFree(m1);
+            return (1);
+        }
+        if (end != NULL)
+            vs = end + 1;
+    } while (end != NULL);
+    JLI_MemFree(m1);
+    return (0);
+}
+
+/*
+ *      Return true if this is a valid simple-element (as defined in JSR 56).
+ *
+ *      The official grammar for a simple-element is:
+ *
+ *              simple-element  ::= version-id | version-id modifier
+ *              modifier        ::= '+' | '*'
+ *              version-id      ::= string ( separator  string )*
+ *              string          ::= char ( char )*
+ *              char            ::= Any ASCII character except a space, an
+ *                                  ampersand, a separator or a modifier
+ *              separator       ::= '.' | '-' | '_'
+ *
+ *      However, for efficiency, it is time to abandon the top down parser
+ *      implementation.  After deleting the potential trailing modifier, we
+ *      are left with a version-id.
+ *
+ *      Note that a valid version-id has three simple properties:
+ *
+ *      1) Doesn't contain a space, an ampersand or a modifier.
+ *
+ *      2) Doesn't begin or end with a separator.
+ *
+ *      3) Doesn't contain two adjacent separators.
+ *
+ *      Any other line noise constitutes a valid version-id.
+ */
+static int
+valid_simple_element(char *simple_element)
+{
+    char        *last;
+    size_t      len;
+
+    if ((simple_element == NULL) || ((len = strlen(simple_element)) == 0))
+        return (0);
+    last = simple_element + len - 1;
+    if (*last == '*' || *last == '+') {
+        if (--len == 0)
+            return (0);
+        *last-- = '\0';
+    }
+    if (strpbrk(simple_element, " &+*") != NULL)        /* Property #1 */
+        return (0);
+    if ((strchr(".-_", *simple_element) != NULL) ||     /* Property #2 */
+      (strchr(".-_", *last) != NULL))
+        return (0);
+    for (; simple_element != last; simple_element++)    /* Property #3 */
+        if ((strchr(".-_", *simple_element) != NULL) &&
+          (strchr(".-_", *(simple_element + 1)) != NULL))
+            return (0);
+    return (1);
+}
+
+/*
+ *      Return true if this is a valid element (as defined in JSR 56).
+ *      An element is the intersection (and) of multiple simple-elements.
+ */
+static int
+valid_element(char *element)
+{
+    char        *end;
+    if ((element == NULL) || (strlen(element) == 0))
+        return (0);
+    do {
+        if ((end = strchr(element, '&')) != NULL)
+            *end = '\0';
+        if (!valid_simple_element(element))
+            return (0);
+        if (end != NULL)
+            element = end + 1;
+    } while (end != NULL);
+    return (1);
+}
+
+/*
+ *      Validates a version string by the extended JSR 56 grammar.
+ */
+int
+JLI_ValidVersionString(char *version_string)
+{
+    char        *vs;
+    char        *m1;
+    char        *end;
+    if ((version_string == NULL) || (strlen(version_string) == 0))
+        return (0);
+    m1 = vs = JLI_StringDup(version_string);
+    do {
+        if ((end = strchr(vs, ' ')) != NULL)
+            *end = '\0';
+        if (!valid_element(vs)) {
+            JLI_MemFree(m1);
+            return (0);
+        }
+        if (end != NULL)
+            vs = end + 1;
+    } while (end != NULL);
+    JLI_MemFree(m1);
+    return (1);
+}
Index: /tags/icedtea-web/beta/launcher/version_comp.h
===================================================================
--- /tags/icedtea-web/beta/launcher/version_comp.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/version_comp.h	(revision 403)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2003, 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef _VERSION_COMP_H
+#define _VERSION_COMP_H
+
+/*
+ * Function prototypes.
+ */
+int JLI_ExactVersionId(char *id1, char *id2);
+int JLI_PrefixVersionId(char *id1, char *id2);
+int JLI_AcceptableRelease(char *release, char *version_string);
+int JLI_ValidVersionString(char *version_string);
+
+#endif /* _VERSION_COMP_H */
Index: /tags/icedtea-web/beta/launcher/wildcard.c
===================================================================
--- /tags/icedtea-web/beta/launcher/wildcard.c	(revision 403)
+++ /tags/icedtea-web/beta/launcher/wildcard.c	(revision 403)
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2005, 2006, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/*
+ * Class-Path Wildcards
+ *
+ * The syntax for wildcards is a single asterisk. The class path
+ * foo/"*", e.g., loads all jar files in the directory named foo.
+ * (This requires careful quotation when used in shell scripts.)
+ *
+ * Only files whose names end in .jar or .JAR are matched.
+ * Files whose names end in .zip, or which have a particular
+ * magic number, regardless of filename extension, are not
+ * matched.
+ *
+ * Files are considered regardless of whether or not they are
+ * "hidden" in the UNIX sense, i.e., have names beginning with '.'.
+ *
+ * A wildcard only matches jar files, not class files in the same
+ * directory.  If you want to load both class files and jar files from
+ * a single directory foo then you can say foo:foo/"*", or foo/"*":foo
+ * if you want the jar files to take precedence.
+ *
+ * Subdirectories are not searched recursively, i.e., foo/"*" only
+ * looks for jar files in foo, not in foo/bar, foo/baz, etc.
+ *
+ * Expansion of wildcards is done early, prior to the invocation of a
+ * program's main method, rather than late, during the class-loading
+ * process itself.  Each element of the input class path containing a
+ * wildcard is replaced by the (possibly empty) sequence of elements
+ * generated by enumerating the jar files in the named directory.  If
+ * the directory foo contains a.jar, b.jar, and c.jar,
+ * e.g., then the class path foo/"*" is expanded into
+ * foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value
+ * of the system property java.class.path.
+ *
+ * The order in which the jar files in a directory are enumerated in
+ * the expanded class path is not specified and may vary from platform
+ * to platform and even from moment to moment on the same machine.  A
+ * well-constructed application should not depend upon any particular
+ * order.  If a specific order is required then the jar files can be
+ * enumerated explicitly in the class path.
+ *
+ * The CLASSPATH environment variable is not treated any differently
+ * from the -classpath (equiv. -cp) command-line option,
+ * i.e. wildcards are honored in all these cases.
+ *
+ * Class-path wildcards are not honored in the Class-Path jar-manifest
+ * header.
+ *
+ * Class-path wildcards are honored not only by the Java launcher but
+ * also by most other command-line tools that accept class paths, and
+ * in particular by javac and javadoc.
+ *
+ * Class-path wildcards are not honored in any other kind of path, and
+ * especially not in the bootstrap class path, which is a mere
+ * artifact of our implementation and not something that developers
+ * should use.
+ *
+ * Classpath wildcards are only expanded in the Java launcher code,
+ * supporting the use of wildcards on the command line and in the
+ * CLASSPATH environment variable.  We do not support the use of
+ * wildcards by applications that embed the JVM.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "java.h"       /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
+#include "jli_util.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else /* Unix */
+#include <unistd.h>
+#include <dirent.h>
+#endif /* Unix */
+
+static int
+exists(const char* filename)
+{
+#ifdef _WIN32
+    return _access(filename, 0) == 0;
+#else
+    return access(filename, F_OK) == 0;
+#endif
+}
+
+#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
+
+/*
+ * Wildcard directory iteration.
+ * WildcardIterator_for(wildcard) returns an iterator.
+ * Each call to that iterator's next() method returns the basename
+ * of an entry in the wildcard's directory.  The basename's memory
+ * belongs to the iterator.  The caller is responsible for prepending
+ * the directory name and file separator, if necessary.
+ * When done with the iterator, call the close method to clean up.
+ */
+typedef struct WildcardIterator_* WildcardIterator;
+
+#ifdef _WIN32
+struct WildcardIterator_
+{
+    HANDLE handle;
+    char *firstFile; /* Stupid FindFirstFile...FindNextFile */
+};
+
+static WildcardIterator
+WildcardIterator_for(const char *wildcard)
+{
+    WIN32_FIND_DATA find_data;
+    WildcardIterator it = NEW_(WildcardIterator);
+    HANDLE handle = FindFirstFile(wildcard, &find_data);
+    if (handle == INVALID_HANDLE_VALUE)
+        return NULL;
+    it->handle = handle;
+    it->firstFile = find_data.cFileName;
+    return it;
+}
+
+static char *
+WildcardIterator_next(WildcardIterator it)
+{
+    WIN32_FIND_DATA find_data;
+    if (it->firstFile != NULL) {
+        char *firstFile = it->firstFile;
+        it->firstFile = NULL;
+        return firstFile;
+    }
+    return FindNextFile(it->handle, &find_data)
+        ? find_data.cFileName : NULL;
+}
+
+static void
+WildcardIterator_close(WildcardIterator it)
+{
+    if (it) {
+        FindClose(it->handle);
+        JLI_MemFree(it->firstFile);
+        JLI_MemFree(it);
+    }
+}
+
+#else /* Unix */
+struct WildcardIterator_
+{
+    DIR *dir;
+};
+
+static WildcardIterator
+WildcardIterator_for(const char *wildcard)
+{
+    DIR *dir;
+    int wildlen = strlen(wildcard);
+    if (wildlen < 2) {
+        dir = opendir(".");
+    } else {
+        char *dirname = JLI_StringDup(wildcard);
+        dirname[wildlen - 1] = '\0';
+        dir = opendir(dirname);
+        JLI_MemFree(dirname);
+    }
+    if (dir == NULL)
+        return NULL;
+    else {
+        WildcardIterator it = NEW_(WildcardIterator);
+        it->dir = dir;
+        return it;
+    }
+}
+
+static char *
+WildcardIterator_next(WildcardIterator it)
+{
+    struct dirent* dirp = readdir(it->dir);
+    return dirp ? dirp->d_name : NULL;
+}
+
+static void
+WildcardIterator_close(WildcardIterator it)
+{
+    if (it) {
+        closedir(it->dir);
+        JLI_MemFree(it);
+    }
+}
+#endif /* Unix */
+
+static int
+equal(const char *s1, const char *s2)
+{
+    return strcmp(s1, s2) == 0;
+}
+
+/*
+ * FileList ADT - a dynamic list of C filenames
+ */
+struct FileList_
+{
+    char **files;
+    int size;
+    int capacity;
+};
+typedef struct FileList_ *FileList;
+
+static FileList
+FileList_new(int capacity)
+{
+    FileList fl = NEW_(FileList);
+    fl->capacity = capacity;
+    fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0]));
+    fl->size = 0;
+    return fl;
+}
+
+#ifdef DEBUG_WILDCARD
+static void
+FileList_print(FileList fl)
+{
+    int i;
+    putchar('[');
+    for (i = 0; i < fl->size; i++) {
+        if (i > 0) printf(", ");
+        printf("\"%s\"",fl->files[i]);
+    }
+    putchar(']');
+}
+#endif
+
+static void
+FileList_free(FileList fl)
+{
+    if (fl) {
+        if (fl->files) {
+            int i;
+            for (i = 0; i < fl->size; i++)
+                JLI_MemFree(fl->files[i]);
+            JLI_MemFree(fl->files);
+        }
+        JLI_MemFree(fl);
+    }
+}
+
+static void
+FileList_ensureCapacity(FileList fl, int capacity)
+{
+    if (fl->capacity < capacity) {
+        while (fl->capacity < capacity)
+            fl->capacity *= 2;
+        fl->files = JLI_MemRealloc(fl->files,
+                               fl->capacity * sizeof(fl->files[0]));
+    }
+}
+
+static void
+FileList_add(FileList fl, char *file)
+{
+    FileList_ensureCapacity(fl, fl->size+1);
+    fl->files[fl->size++] = file;
+}
+
+static void
+FileList_addSubstring(FileList fl, const char *beg, int len)
+{
+    char *filename = (char *) JLI_MemAlloc(len+1);
+    memcpy(filename, beg, len);
+    filename[len] = '\0';
+    FileList_ensureCapacity(fl, fl->size+1);
+    fl->files[fl->size++] = filename;
+}
+
+static char *
+FileList_join(FileList fl, char sep)
+{
+    int i;
+    int size;
+    char *path;
+    char *p;
+    for (i = 0, size = 1; i < fl->size; i++)
+        size += strlen(fl->files[i]) + 1;
+
+    path = JLI_MemAlloc(size);
+
+    for (i = 0, p = path; i < fl->size; i++) {
+        int len = strlen(fl->files[i]);
+        if (i > 0) *p++ = sep;
+        memcpy(p, fl->files[i], len);
+        p += len;
+    }
+    *p = '\0';
+
+    return path;
+}
+
+static FileList
+FileList_split(const char *path, char sep)
+{
+    const char *p, *q;
+    int len = strlen(path);
+    int count;
+    FileList fl;
+    for (count = 1, p = path; p < path + len; p++)
+        count += (*p == sep);
+    fl = FileList_new(count);
+    for (p = path;;) {
+        for (q = p; q <= path + len; q++) {
+            if (*q == sep || *q == '\0') {
+                FileList_addSubstring(fl, p, q - p);
+                if (*q == '\0')
+                    return fl;
+                p = q + 1;
+            }
+        }
+    }
+}
+
+static int
+isJarFileName(const char *filename)
+{
+    int len = strlen(filename);
+    return (len >= 4) &&
+        (filename[len - 4] == '.') &&
+        (equal(filename + len - 3, "jar") ||
+         equal(filename + len - 3, "JAR")) &&
+        /* Paranoia: Maybe filename is "DIR:foo.jar" */
+        (strchr(filename, PATH_SEPARATOR) == NULL);
+}
+
+static char *
+wildcardConcat(const char *wildcard, const char *basename)
+{
+    int wildlen = strlen(wildcard);
+    int baselen = strlen(basename);
+    char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
+    /* Replace the trailing '*' with basename */
+    memcpy(filename, wildcard, wildlen-1);
+    memcpy(filename+wildlen-1, basename, baselen+1);
+    return filename;
+}
+
+static FileList
+wildcardFileList(const char *wildcard)
+{
+    const char *basename;
+    FileList fl = FileList_new(16);
+    WildcardIterator it = WildcardIterator_for(wildcard);
+    if (it == NULL)
+        return NULL;
+    while ((basename = WildcardIterator_next(it)) != NULL)
+        if (isJarFileName(basename))
+            FileList_add(fl, wildcardConcat(wildcard, basename));
+    WildcardIterator_close(it);
+    return fl;
+}
+
+static int
+isWildcard(const char *filename)
+{
+    int len = strlen(filename);
+    return (len > 0) &&
+        (filename[len - 1] == '*') &&
+        (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
+        (! exists(filename));
+}
+
+static void
+FileList_expandWildcards(FileList fl)
+{
+    int i, j;
+    for (i = 0; i < fl->size; i++) {
+        if (isWildcard(fl->files[i])) {
+            FileList expanded = wildcardFileList(fl->files[i]);
+            if (expanded != NULL && expanded->size > 0) {
+                JLI_MemFree(fl->files[i]);
+                FileList_ensureCapacity(fl, fl->size + expanded->size);
+                for (j = fl->size - 1; j >= i+1; j--)
+                    fl->files[j+expanded->size-1] = fl->files[j];
+                for (j = 0; j < expanded->size; j++)
+                    fl->files[i+j] = expanded->files[j];
+                i += expanded->size - 1;
+                fl->size += expanded->size - 1;
+                /* fl expropriates expanded's elements. */
+                expanded->size = 0;
+            }
+            FileList_free(expanded);
+        }
+    }
+}
+
+const char *
+JLI_WildcardExpandClasspath(const char *classpath)
+{
+    char *expanded;
+    FileList fl;
+
+    if (strchr(classpath, '*') == NULL)
+        return classpath;
+    fl = FileList_split(classpath, PATH_SEPARATOR);
+    FileList_expandWildcards(fl);
+    expanded = FileList_join(fl, PATH_SEPARATOR);
+    FileList_free(fl);
+    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0)
+        printf("Expanded wildcards:\n"
+               "    before: \"%s\"\n"
+               "    after : \"%s\"\n",
+               classpath, expanded);
+    return expanded;
+}
+
+#ifdef DEBUG_WILDCARD
+static void
+wildcardExpandArgv(const char ***argv)
+{
+    int i;
+    for (i = 0; (*argv)[i]; i++) {
+        if (equal((*argv)[i], "-cp") ||
+            equal((*argv)[i], "-classpath")) {
+            i++;
+            (*argv)[i] = wildcardExpandClasspath((*argv)[i]);
+        }
+    }
+}
+
+static void
+debugPrintArgv(char *argv[])
+{
+    int i;
+    putchar('[');
+    for (i = 0; argv[i]; i++) {
+        if (i > 0) printf(", ");
+        printf("\"%s\"", argv[i]);
+    }
+    printf("]\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+    argv[0] = "java";
+    wildcardExpandArgv((const char***)&argv);
+    debugPrintArgv(argv);
+    /* execvp("java", argv); */
+    return 0;
+}
+#endif /* DEBUG_WILDCARD */
+
+/* Cute little perl prototype implementation....
+
+my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
+
+sub expand($) {
+  opendir DIR, $_[0] or return $_[0];
+  join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
+}
+
+sub munge($) {
+  join $sep,
+    map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
+}
+
+for (my $i = 0; $i < @ARGV - 1; $i++) {
+  $ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
+}
+
+$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
+@ARGV = ("java", @ARGV);
+print "@ARGV\n";
+exec @ARGV;
+
+*/
Index: /tags/icedtea-web/beta/launcher/wildcard.h
===================================================================
--- /tags/icedtea-web/beta/launcher/wildcard.h	(revision 403)
+++ /tags/icedtea-web/beta/launcher/wildcard.h	(revision 403)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#ifndef WILDCARD_H_
+#define WILDCARD_H_
+
+#ifdef EXPAND_CLASSPATH_WILDCARDS
+const char *JLI_WildcardExpandClasspath(const char *classpath);
+#else
+#define JLI_WildcardExpandClasspath(s) (s)
+#endif
+
+#endif /* include guard */
Index: /tags/icedtea-web/beta/missing
===================================================================
--- /tags/icedtea-web/beta/missing	(revision 403)
+++ /tags/icedtea-web/beta/missing	(revision 403)
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program 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 for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+  s/^gnu-//; t
+  s/^gnu//; t
+  s/^g//; t'`
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).  This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+  lex*|yacc*)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar*)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te*)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison*|yacc*)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f y.tab.h; then
+	echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex*|flex*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f lex.yy.c; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit $?
+    fi
+    ;;
+
+  makeinfo*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+	/^@setfilename/{
+	  s/.* \([^ ]*\) *$/\1/
+	  p
+	  q
+	}' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar*)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case $firstarg in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case $firstarg in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
Index: /tags/icedtea-web/beta/netx.manifest.in
===================================================================
--- /tags/icedtea-web/beta/netx.manifest.in	(revision 403)
+++ /tags/icedtea-web/beta/netx.manifest.in	(revision 403)
@@ -0,0 +1,2 @@
+Implementation-Title: @PACKAGE_NAME@
+Implementation-Version: @FULL_VERSION@
Index: /tags/icedtea-web/beta/netx/Makefile.kmk
===================================================================
--- /tags/icedtea-web/beta/netx/Makefile.kmk	(revision 403)
+++ /tags/icedtea-web/beta/netx/Makefile.kmk	(revision 403)
@@ -0,0 +1,71 @@
+## @file
+#
+
+SUB_DEPTH = ..
+include $(KBUILD_PATH)/subheader.kmk
+
+OTHERS += netx
+BLDDIRS += $(netx_0_OUTDIR)
+
+netx_BUILD_PROPERTIES = $(netx_0_OUTDIR)/net/sourceforge/jnlp/build.properties
+BLDDIRS += $(dir $(netx_BUILD_PROPERTIES))
+OTHER_CLEAN += $(netx_BUILD_PROPERTIES)
+
+netx_MANIFEST = $(netx_0_OUTDIR)/netx.manifest
+BLDDIRS += $(dir $(netx_MANIFEST))
+OTHER_CLEAN += $(netx_MANIFEST)
+
+netx_JAVASRCDIRS := $(PATH_SUB_CURRENT)
+
+netx_JAVASRCLIST = $(netx_0_OUTDIR)/javasrc.list
+BLDDIRS += $(dir $(netx_JAVASRCLIST))
+OTHER_CLEAN += $(netx_JAVASRCLIST) $(netx_JAVASRCLIST).rsp $(netx_JAVASRCLIST).stamp
+
+netx_JARFILE = $(PATH_STAGE)/lib/netx.jar
+BLDDIRS += $(dir $(netx_JARFILE))
+OTHER_CLEAN += $(netx_JARFILE)
+
+$$(netx_BUILD_PROPERTIES): $(PATH_ROOT)/build.properties.in | $$(call DIRDEP,$$(dir $$(@)))
+	sed "s/@RHINO_AVAILABLE@/$(if $(WITH_RHINO),true,false)/g" < $^ > $@
+
+$$(netx_MANIFEST): $(PATH_ROOT)/netx.manifest.in | $$(call DIRDEP,$$(dir $$(@)))
+	sed "s/@PACKAGE_NAME@/$(PACKAGE_NAME)/g; \
+         s/@FULL_VERSION@/$(FULL_VERSION)/g; " < $^ > $@
+
+$$(netx_JAVASRCLIST): $(MAKEFILE) | $$(call DIRDEP,$$(dir $$(@)))
+	@echo 'JAVASRC = \' > $@
+	find $(netx_JAVASRCDIRS) -name '*.java' \
+        $(if $(WITH_RHINO),,! -name '*RhinoBasedPacEvaluator*') \
+        -printf '%p \\\n' >> $@
+
+$$(netx_JAVASRCLIST).stamp: $$(JAVASRC) | $$(call DIRDEP,$$(dir $$(@)))
+	$(call MSG_COMPILE,netx,$(words $?) sources,$@,JAVA)
+	@echo $? > $(netx_JAVASRCLIST).rsp
+	$(PATH_BOOTSTRAP_JDK)/bin/javac $(IT_JAVACFLAGS) \
+        -d "$(netx_0_OUTDIR)" \
+        -sourcepath "$(subst ; ,;,$(foreach d,$(netx_JAVASRCDIRS),$(d);))" \
+        -bootclasspath "$(BOOTSTRAP_JDK_RUNTIME)" \
+        @"$(netx_JAVASRCLIST).rsp"
+	@touch "$@"
+
+$$(netx_JARFILE): $$(netx_BUILD_PROPERTIES) $$(netx_MANIFEST) \
+                  $$(netx_JAVASRCLIST).stamp | $$(call DIRDEP,$$(dir $$(@)))
+	(cd $(netx_DEFPATH)/net/sourceforge/jnlp/resources; \
+        for files in $$(find . -path ./.svn -prune -o -type f -print); \
+        do \
+            $(INSTALL_DATA) -D $${files} \
+            $(netx_0_OUTDIR)/net/sourceforge/jnlp/resources/$${files}; \
+        done)
+	cp -a $(netx_DEFPATH)/net/sourceforge/jnlp/runtime/pac-funcs.js \
+        $(netx_0_OUTDIR)/net/sourceforge/jnlp/runtime
+	(cd $(netx_0_OUTDIR); \
+        $(PATH_BOOTSTRAP_JDK)/bin/jar cfm $(netx_JARFILE) \
+            $(netx_MANIFEST) javax/jnlp net)
+
+netx: $$(netx_JARFILE)
+
+install:: netx
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+-include $(netx_JAVASRCLIST)
Index: /tags/icedtea-web/beta/netx/javaws.1
===================================================================
--- /tags/icedtea-web/beta/netx/javaws.1	(revision 403)
+++ /tags/icedtea-web/beta/netx/javaws.1	(revision 403)
@@ -0,0 +1,123 @@
+.TH javaws 1 "9 Sep 2010"
+.SH NAME
+javaws - a Java Web Start client
+.SH SYNOPSYS
+.B javaws
+[-run-options] jnlp-file
+.br
+.B javaws
+[-control-option]
+.SH DESCRIPTION
+.B javaws
+is an implementation of a JNLP  client. It uses a JNLP (Java Network
+Launch Protocol) file to securely run a remote Java application or
+a Java applet.  This implementation of
+.B javaws
+is from the IcedTea project and is based on the NetX project.
+.PP
+A JNLP file is an xml file that describes how to securely run a
+remote Java application or a Java applet.
+
+.SH OPTIONS
+When specifying options, the name of the jnlp file must be the last
+argument to
+.B javaws
+- all the options must preceede it.
+.PP
+The jnlp-file can either be a url or a local path.
+.PP
+.B Control Options
+.PP
+By default
+.B javaws
+will launch the jnlp file specified on the command line. The control
+options can be used to change this behaviour.
+.TP 12
+\-about
+Shows a sample application that can be used to test the basic functionality
+of this implementation.
+.TP
+\-viewer
+Shows the trusted certificate viewer. This allows a user to list, examine, remove
+or export trusted certificates. Note that this only reflects the certificates
+trusted by
+.B javaws
+and not any other certificates or programs.
+
+.PP
+.B Run Options
+.PP
+In the default mode, the following run-options can be used:
+.TP 12
+\-basedir dir
+Directory where the cache and certificates to be used are stored.
+.TP
+\-arg arg
+Adds an application argument before launching.
+.TP
+\-param name=value
+Adds an applet parameter before launching.
+.TP
+\-property name=value
+Sets a system property before launching.
+.TP
+\-update seconds
+Update check if seconds since last checked.
+.TP
+\-license
+Display the GPL license and exit.
+.TP
+\-verbose
+Enable verbose output. Very useful in debugging.
+.TP
+\-nosecurity
+Disables the secure runtime environment.
+.TP
+\-noupdate
+Disables checking for updates.
+.TP
+\-headless
+Disables download window, other UIs.
+.TP
+\-strict
+Enables strict checking of JNLP file format. Any deviations from
+the JNLP DTD will cause
+.B javaws
+to abort.
+.TP
+\-umask=value
+Sets the umask for files created by an application.
+.TP
+\-Xnofork
+Do not create another JVM, even if the JNLP file asks for running in
+a separate JVM. This is useful for debugging.
+.TP
+\-Jjava-option
+This passes along java-option to the java binary that is running
+javaws. For example, to make javaws run with a max heap size
+of 80m, use -J-Xmx80m.
+.TP
+\-help
+Print a help message and exit.
+
+.SH FILES
+~/.icedtea/deployment.properties specifies the settings used by javaws
+
+.SH BUGS
+There arent any known bugs. If you come across one, please file it at
+    http://icedtea.classpath.org/bugzilla/
+.br
+Please run javaws in verbose mode and include that output along
+with the jnlp file when filing out the bug report.
+
+.SH AUTHOR
+Originally written by Jon. A. Maxwell.
+.br
+Currently maintained by the IcedTea contributors.
+
+.SH SEE ALSO
+.BR java (1)
+.br
+http://icedtea.classpath.org/
+.br
+http://jnlp.sourceforge.net/netx/
Index: /tags/icedtea-web/beta/netx/javax/jnlp/BasicService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/BasicService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/BasicService.java	(revision 403)
@@ -0,0 +1,13 @@
+package javax.jnlp;
+
+public interface BasicService {
+
+    public java.net.URL getCodeBase();
+
+    public boolean isOffline();
+
+    public boolean showDocument(java.net.URL url);
+
+    public boolean isWebBrowserSupported();
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/ClipboardService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/ClipboardService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/ClipboardService.java	(revision 403)
@@ -0,0 +1,9 @@
+package javax.jnlp;
+
+public interface ClipboardService {
+
+    public java.awt.datatransfer.Transferable getContents();
+
+    public void setContents(java.awt.datatransfer.Transferable contents);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService.java	(revision 403)
@@ -0,0 +1,37 @@
+package javax.jnlp;
+
+public interface DownloadService {
+
+    public boolean isResourceCached(java.net.URL ref, java.lang.String version);
+
+    public boolean isPartCached(java.lang.String part);
+
+    public boolean isPartCached(java.lang.String[] parts);
+
+    public boolean isExtensionPartCached(java.net.URL ref, java.lang.String version, java.lang.String part);
+
+    public boolean isExtensionPartCached(java.net.URL ref, java.lang.String version, java.lang.String[] parts);
+
+    public void loadResource(java.net.URL ref, java.lang.String version, DownloadServiceListener progress) throws java.io.IOException;
+
+    public void loadPart(java.lang.String part, DownloadServiceListener progress) throws java.io.IOException;
+
+    public void loadPart(java.lang.String[] parts, DownloadServiceListener progress) throws java.io.IOException;
+
+    public void loadExtensionPart(java.net.URL ref, java.lang.String version, java.lang.String part, DownloadServiceListener progress) throws java.io.IOException;
+
+    public void loadExtensionPart(java.net.URL ref, java.lang.String version, java.lang.String[] parts, DownloadServiceListener progress) throws java.io.IOException;
+
+    public void removeResource(java.net.URL ref, java.lang.String version) throws java.io.IOException;
+
+    public void removePart(java.lang.String part) throws java.io.IOException;
+
+    public void removePart(java.lang.String[] parts) throws java.io.IOException;
+
+    public void removeExtensionPart(java.net.URL ref, java.lang.String version, java.lang.String part) throws java.io.IOException;
+
+    public void removeExtensionPart(java.net.URL ref, java.lang.String version, java.lang.String[] parts) throws java.io.IOException;
+
+    public DownloadServiceListener getDefaultProgressWindow();
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService2.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService2.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/DownloadService2.java	(revision 403)
@@ -0,0 +1,57 @@
+package javax.jnlp;
+
+public interface DownloadService2 {
+
+    public static class ResourceSpec {
+
+        public static final long UNKNOWN = Long.MIN_VALUE;
+
+        protected String url;
+        protected String version;
+        protected int type;
+
+        public ResourceSpec(java.lang.String url, java.lang.String version, int type) {
+            this.url = url;
+            this.version = version;
+            this.type = type;
+        }
+
+        public long getExpirationDate() {
+            return UNKNOWN;
+        }
+
+        public long getLastModified() {
+            return UNKNOWN;
+        }
+
+        public long getSize() {
+            return UNKNOWN;
+        }
+
+        public int getType() {
+            return type;
+        }
+
+        public java.lang.String getUrl() {
+            return url;
+        }
+
+        public java.lang.String getVersion() {
+            return version;
+        }
+    }
+
+    public static final int ALL = 0;
+    public static final int APPLET = 2;
+    public static final int APPLICATION = 1;
+    public static final int CLASS = 6;
+    public static final int EXTENSION = 3;
+    public static final int IMAGE = 5;
+    public static final int JAR = 4;
+
+    public DownloadService2.ResourceSpec[] getCachedResources(
+            javax.jnlp.DownloadService2.ResourceSpec resourceSpec);
+
+    public DownloadService2.ResourceSpec[] getUpdateAvaiableReosurces(
+            javax.jnlp.DownloadService2.ResourceSpec resourceSpec);
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/DownloadServiceListener.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/DownloadServiceListener.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/DownloadServiceListener.java	(revision 403)
@@ -0,0 +1,13 @@
+package javax.jnlp;
+
+public interface DownloadServiceListener {
+
+    public void progress(java.net.URL url, java.lang.String version, long readSoFar, long total, int overallPercent);
+
+    public void validating(java.net.URL url, java.lang.String version, long entry, long total, int overallPercent);
+
+    public void upgradingArchive(java.net.URL url, java.lang.String version, int patchPercent, int overallPercent);
+
+    public void downloadFailed(java.net.URL url, java.lang.String version);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/ExtendedService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/ExtendedService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/ExtendedService.java	(revision 403)
@@ -0,0 +1,51 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package javax.jnlp;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This interface provides a way for the JNLP application to open specific files
+ * in the client's system. It asks permission from the user before opening any
+ * files.
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+public interface ExtendedService {
+
+    /**
+     * Open a file on the client' system and return its contents. The user must
+     * grant permission to the application for this to work.
+     *
+     * @param file the file to open
+     * @return the opened file as a {@link FileContents} object
+     * @throws IOException on any io problems
+     */
+    FileContents openFile(File file) throws IOException;
+
+    /**
+     * Opens multiple files on the user's sytem and returns their contents as a
+     * {@link FileContents} array
+     *
+     * @param files the files to open
+     * @return an array of FileContents objects
+     * @throws IOException on any io problems
+     */
+    FileContents[] openFiles(File[] files) throws IOException;
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/ExtensionInstallerService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/ExtensionInstallerService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/ExtensionInstallerService.java	(revision 403)
@@ -0,0 +1,31 @@
+package javax.jnlp;
+
+public interface ExtensionInstallerService {
+
+    public java.lang.String getInstallPath();
+
+    public java.lang.String getExtensionVersion();
+
+    public java.net.URL getExtensionLocation();
+
+    public void hideProgressBar();
+
+    public void hideStatusWindow();
+
+    public void setHeading(java.lang.String heading);
+
+    public void setStatus(java.lang.String status);
+
+    public void updateProgress(int value);
+
+    public void installSucceeded(boolean needsReboot);
+
+    public void installFailed();
+
+    public void setJREInfo(java.lang.String platformVersion, java.lang.String jrePath);
+
+    public void setNativeLibraryInfo(java.lang.String path);
+
+    public java.lang.String getInstalledJRE(java.net.URL url, java.lang.String version);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/FileContents.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/FileContents.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/FileContents.java	(revision 403)
@@ -0,0 +1,23 @@
+package javax.jnlp;
+
+public interface FileContents {
+
+    public java.lang.String getName() throws java.io.IOException;
+
+    public java.io.InputStream getInputStream() throws java.io.IOException;
+
+    public java.io.OutputStream getOutputStream(boolean overwrite) throws java.io.IOException;
+
+    public long getLength() throws java.io.IOException;
+
+    public boolean canRead() throws java.io.IOException;
+
+    public boolean canWrite() throws java.io.IOException;
+
+    public JNLPRandomAccessFile getRandomAccessFile(java.lang.String mode) throws java.io.IOException;
+
+    public long getMaxLength() throws java.io.IOException;
+
+    public long setMaxLength(long maxlength) throws java.io.IOException;
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/FileOpenService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/FileOpenService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/FileOpenService.java	(revision 403)
@@ -0,0 +1,9 @@
+package javax.jnlp;
+
+public interface FileOpenService {
+
+    public FileContents openFileDialog(java.lang.String pathHint, java.lang.String[] extensions) throws java.io.IOException;
+
+    public FileContents[] openMultiFileDialog(java.lang.String pathHint, java.lang.String[] extensions) throws java.io.IOException;
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/FileSaveService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/FileSaveService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/FileSaveService.java	(revision 403)
@@ -0,0 +1,9 @@
+package javax.jnlp;
+
+public interface FileSaveService {
+
+    public FileContents saveFileDialog(java.lang.String pathHint, java.lang.String[] extensions, java.io.InputStream stream, java.lang.String name) throws java.io.IOException;
+
+    public FileContents saveAsFileDialog(java.lang.String pathHint, java.lang.String[] extensions, FileContents contents) throws java.io.IOException;
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/IntegrationService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/IntegrationService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/IntegrationService.java	(revision 403)
@@ -0,0 +1,19 @@
+package javax.jnlp;
+
+public interface IntegrationService {
+
+    public boolean hasAssociation(java.lang.String mimeType, java.lang.String[] extensions);
+
+    public boolean hasDesktopShortcut();
+
+    public boolean hasMenuShortcut();
+
+    public boolean removeAssociation(java.lang.String mimeType, java.lang.String[] extensions);
+
+    public boolean removeShortcuts();
+
+    public boolean requestAssociation(java.lang.String mimeType, java.lang.String[] extensions);
+
+    public boolean requestShortcut(boolean onDesktop, boolean inMenu, java.lang.String subMenu);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/JNLPRandomAccessFile.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/JNLPRandomAccessFile.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/JNLPRandomAccessFile.java	(revision 403)
@@ -0,0 +1,79 @@
+package javax.jnlp;
+
+public interface JNLPRandomAccessFile extends java.io.DataInput, java.io.DataOutput {
+
+    public void close() throws java.io.IOException;
+
+    public long length() throws java.io.IOException;
+
+    public long getFilePointer() throws java.io.IOException;
+
+    public int read() throws java.io.IOException;
+
+    public int read(byte[] b, int off, int len) throws java.io.IOException;
+
+    public int read(byte[] b) throws java.io.IOException;
+
+    public void readFully(byte[] b) throws java.io.IOException;
+
+    public void readFully(byte[] b, int off, int len) throws java.io.IOException;
+
+    public int skipBytes(int n) throws java.io.IOException;
+
+    public boolean readBoolean() throws java.io.IOException;
+
+    public byte readByte() throws java.io.IOException;
+
+    public int readUnsignedByte() throws java.io.IOException;
+
+    public short readShort() throws java.io.IOException;
+
+    public int readUnsignedShort() throws java.io.IOException;
+
+    public char readChar() throws java.io.IOException;
+
+    public int readInt() throws java.io.IOException;
+
+    public long readLong() throws java.io.IOException;
+
+    public float readFloat() throws java.io.IOException;
+
+    public double readDouble() throws java.io.IOException;
+
+    public java.lang.String readLine() throws java.io.IOException;
+
+    public java.lang.String readUTF() throws java.io.IOException;
+
+    public void seek(long pos) throws java.io.IOException;
+
+    public void setLength(long newLength) throws java.io.IOException;
+
+    public void write(int b) throws java.io.IOException;
+
+    public void write(byte[] b) throws java.io.IOException;
+
+    public void write(byte[] b, int off, int len) throws java.io.IOException;
+
+    public void writeBoolean(boolean v) throws java.io.IOException;
+
+    public void writeByte(int v) throws java.io.IOException;
+
+    public void writeShort(int v) throws java.io.IOException;
+
+    public void writeChar(int v) throws java.io.IOException;
+
+    public void writeInt(int v) throws java.io.IOException;
+
+    public void writeLong(long v) throws java.io.IOException;
+
+    public void writeFloat(float v) throws java.io.IOException;
+
+    public void writeDouble(double v) throws java.io.IOException;
+
+    public void writeBytes(java.lang.String s) throws java.io.IOException;
+
+    public void writeChars(java.lang.String s) throws java.io.IOException;
+
+    public void writeUTF(java.lang.String str) throws java.io.IOException;
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/PersistenceService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/PersistenceService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/PersistenceService.java	(revision 403)
@@ -0,0 +1,21 @@
+package javax.jnlp;
+
+public interface PersistenceService {
+
+    public static final int CACHED = 0;
+    public static final int TEMPORARY = 1;
+    public static final int DIRTY = 2;
+
+    public long create(java.net.URL url, long maxsize) throws java.net.MalformedURLException, java.io.IOException;
+
+    public FileContents get(java.net.URL url) throws java.net.MalformedURLException, java.io.IOException, java.io.FileNotFoundException;
+
+    public void delete(java.net.URL url) throws java.net.MalformedURLException, java.io.IOException;
+
+    public java.lang.String[] getNames(java.net.URL url) throws java.net.MalformedURLException, java.io.IOException;
+
+    public int getTag(java.net.URL url) throws java.net.MalformedURLException, java.io.IOException;
+
+    public void setTag(java.net.URL url, int tag) throws java.net.MalformedURLException, java.io.IOException;
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/PrintService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/PrintService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/PrintService.java	(revision 403)
@@ -0,0 +1,13 @@
+package javax.jnlp;
+
+public interface PrintService {
+
+    public java.awt.print.PageFormat getDefaultPage();
+
+    public java.awt.print.PageFormat showPageFormatDialog(java.awt.print.PageFormat page);
+
+    public boolean print(java.awt.print.Pageable document);
+
+    public boolean print(java.awt.print.Printable painter);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManager.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManager.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManager.java	(revision 403)
@@ -0,0 +1,48 @@
+package javax.jnlp;
+
+import java.util.*;
+
+public final class ServiceManager {
+
+    private static ServiceManagerStub stub = null;
+
+    private static Map<String, Object> lookupTable = new HashMap<String, Object>(); // ensure lookup is idempotent
+
+    private ServiceManager() {
+        // says it can't be instantiated
+    }
+
+    public static java.lang.Object lookup(java.lang.String name) throws UnavailableServiceException {
+        if (stub == null)
+            throw new UnavailableServiceException("service stub not set.");
+
+        synchronized (lookupTable) {
+            Object result = lookupTable.get(name);
+
+            if (result == null) {
+                result = stub.lookup(name);
+                if (result != null)
+                    lookupTable.put(name, result);
+            }
+
+            if (result == null)
+                throw new UnavailableServiceException("service not available (stub returned null).");
+
+            return result;
+        }
+    }
+
+    public static java.lang.String[] getServiceNames() {
+        // should this return the required ones even though no stub??
+        if (stub == null)
+            return new String[0];
+
+        return stub.getServiceNames();
+    }
+
+    public static void setServiceManagerStub(ServiceManagerStub stub) {
+        if (ServiceManager.stub == null)
+            ServiceManager.stub = stub;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManagerStub.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManagerStub.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/ServiceManagerStub.java	(revision 403)
@@ -0,0 +1,9 @@
+package javax.jnlp;
+
+public interface ServiceManagerStub {
+
+    public java.lang.Object lookup(java.lang.String name) throws UnavailableServiceException;
+
+    public java.lang.String[] getServiceNames();
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceListener.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceListener.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceListener.java	(revision 403)
@@ -0,0 +1,35 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package javax.jnlp;
+
+/**
+ * This interface specifies a listener which is notified whenever a new instance
+ * of the web start application is launched.
+ *
+ */
+public interface SingleInstanceListener {
+
+    /**
+     * This method is called when a new instance of the application is launched.
+     * The arguments passed to the new instance are passed into this method.
+     *
+     * @param arguments the arguments passed to the new instance of the
+     *        application
+     */
+    void newActivation(String[] arguments);
+
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceService.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/SingleInstanceService.java	(revision 403)
@@ -0,0 +1,46 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package javax.jnlp;
+
+/**
+ * The SingleInstanceService provides a way to ensure that only one instance of
+ * the application is ever running - singleton behavior at the application
+ * level.
+ *
+ */
+public interface SingleInstanceService {
+
+    /**
+     * Adds the specified SingleInstanceListener to the notification list. This
+     * listener is notified when a new instance of the application is started.
+     *
+     *
+     * @param listener the single instance listener to be added. No action is
+     *        performed if it is null.
+     */
+    void addSingleInstanceListener(SingleInstanceListener listener);
+
+    /**
+     * Removes the specified SingleInstanceListener from the notification list.
+     * This listener will not be notified if a new instance of the application
+     * is started.
+     *
+     * @param listener the single instance listener to be removed. No action is
+     *        performed if it is null or not in the notification list.
+     */
+    void removeSingleInstanceListener(SingleInstanceListener listener);
+}
Index: /tags/icedtea-web/beta/netx/javax/jnlp/UnavailableServiceException.java
===================================================================
--- /tags/icedtea-web/beta/netx/javax/jnlp/UnavailableServiceException.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/javax/jnlp/UnavailableServiceException.java	(revision 403)
@@ -0,0 +1,13 @@
+package javax.jnlp;
+
+public class UnavailableServiceException extends Exception {
+
+    public UnavailableServiceException() {
+        super();
+    }
+
+    public UnavailableServiceException(java.lang.String message) {
+        super(message);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletDesc.java	(revision 403)
@@ -0,0 +1,120 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.net.*;
+import java.util.*;
+
+/**
+ * The applet-desc element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.8 $
+ */
+public class AppletDesc {
+
+    /** the applet name */
+    private String name;
+
+    /** the main class name and package */
+    private String mainClass;
+
+    /** the document base */
+    private URL documentBase;
+
+    /** the width */
+    private int width;
+
+    /** the height */
+    private int height;
+
+    /** the parameters */
+    private Map<String, String> parameters;
+
+    /**
+     * Create an Applet descriptor.
+     *
+     * @param name the applet name
+     * @param mainClass the main class name and package
+     * @param documentBase the document base
+     * @param width the width
+     * @param height the height
+     * @param parameters the parameters
+     */
+    public AppletDesc(String name, String mainClass, URL documentBase, int width, int height,
+                      Map<String, String> parameters) {
+        this.name = name;
+        this.mainClass = mainClass;
+        this.documentBase = documentBase;
+        this.width = width;
+        this.height = height;
+        this.parameters = new HashMap<String, String>(parameters);
+    }
+
+    /**
+     * Returns the applet name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the main class name
+     */
+    public String getMainClass() {
+        return mainClass;
+    }
+
+    /**
+     * Returns the document base
+     */
+    public URL getDocumentBase() {
+        return documentBase;
+    }
+
+    /**
+     * Returns the width
+     */
+    public int getWidth() {
+        return width;
+    }
+
+    /**
+     * Returns the height
+     */
+    public int getHeight() {
+        return height;
+    }
+
+    /**
+     * Returns the applet parameters
+     */
+    public Map<String, String> getParameters() {
+        return new HashMap<String, String>(parameters);
+    }
+
+    /**
+     * Adds a parameter to the applet.  If the parameter already
+     * exists then it is overwritten with the new value.  Adding a
+     * parameter will have no effect on already-running applets
+     * launched from this JNLP file.
+     */
+    public void addParameter(String name, String value) {
+        parameters.put(name, value);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletLog.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletLog.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AppletLog.java	(revision 403)
@@ -0,0 +1,55 @@
+package net.sourceforge.jnlp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.XMLFormatter;
+
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * This class writes log information to file.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+class AppletLog extends Log {
+    private static Logger logger;
+    static {
+        try {
+            // If logging is enabled, we create logger.
+            if (enableLogging) {
+                String fn = icedteaLogDir + "plugin" + java.lang.System.currentTimeMillis() + ".log";
+                FileUtils.createRestrictedFile(new File(fn), true);
+                FileHandler fh = new FileHandler(fn, false);
+                fh.setFormatter(new XMLFormatter());
+                String logClassName = AppletLog.class.getName();
+                logger = Logger.getLogger(logClassName);
+                logger.setLevel(Level.ALL);
+                logger.addHandler(fh);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private AppletLog() {
+    }
+
+    /**
+     * Log the exception to file.
+     * 
+     * @param e Exception that was thrown.
+     */
+    public synchronized static void log(Throwable e) {
+        if (enableLogging && logger != null) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            PrintStream ps = new PrintStream(baos);
+            e.printStackTrace(ps);
+            logger.log(Level.FINE, baos.toString());
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ApplicationDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ApplicationDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ApplicationDesc.java	(revision 403)
@@ -0,0 +1,70 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.util.*;
+
+/**
+ * The application-desc element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+public class ApplicationDesc {
+
+    /** the main class name and package */
+    private String mainClass;
+
+    /** the arguments */
+    private String arguments[];
+
+    /**
+     * Create an Application descriptor.
+     *
+     * @param mainClass the main class name and package
+     * @param arguments the arguments
+     */
+    public ApplicationDesc(String mainClass, String arguments[]) {
+        this.mainClass = mainClass;
+        this.arguments = arguments;
+    }
+
+    /**
+     * Returns the main class name
+     */
+    public String getMainClass() {
+        return mainClass;
+    }
+
+    /**
+     * Returns the arguments
+     */
+    public String[] getArguments() {
+        return arguments.clone();
+    }
+
+    /**
+     * Add an argument to the end of the arguments.
+     */
+    public void addArgument(String arg) {
+        List<String> l = new ArrayList<String>(Arrays.asList(arguments));
+        l.add(arg);
+
+        arguments = l.toArray(arguments);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AssociationDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AssociationDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/AssociationDesc.java	(revision 403)
@@ -0,0 +1,56 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+public final class AssociationDesc {
+
+    /** the extensions this application wants to register with */
+    private String[] extensions;
+
+    /** the mime type for the association */
+    private String mimeType;
+
+    public AssociationDesc(String mimeType, String[] extensions) throws ParseException {
+        checkMimeType(mimeType);
+        this.mimeType = mimeType;
+        this.extensions = extensions;
+    }
+
+    /**
+     * Return the extensions for this association
+     */
+    public String[] getExtensions() {
+        return extensions;
+    }
+
+    /**
+     * Return the mimetype for this association
+     */
+    public String getMimeType() {
+        return mimeType;
+    }
+
+    /**
+     * Check for valid mimeType
+     * @param mimeType a mime type
+     * @throws ParseException if mimeType is an invalid MIME type
+     */
+    private void checkMimeType(String mimeType) throws ParseException {
+        // TODO check that mime type is valid
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ComponentDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ComponentDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ComponentDesc.java	(revision 403)
@@ -0,0 +1,35 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+/**
+ * The component-desc element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class ComponentDesc {
+
+    // this is for completeness and in case of changes to spec for components.
+
+    /**
+     * Create a component descriptor.
+     */
+    public ComponentDesc() {
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DefaultLaunchHandler.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DefaultLaunchHandler.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DefaultLaunchHandler.java	(revision 403)
@@ -0,0 +1,122 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * This default implementation shows prints the exception to
+ * stdout and if not in headless mode displays the exception in a
+ * dialog.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.1 $
+ */
+public class DefaultLaunchHandler implements LaunchHandler {
+
+    /**
+     * Called when the application could not be launched due to a
+     * fatal error, such as the inability to find the main class
+     * or non-parseable XML.
+     */
+    public void launchError(LaunchException exception) {
+        printMessage(exception);
+    }
+
+    /**
+     * Called when launching the application can not be launched
+     * due to an error that is not fatal.  For example a JNLP file
+     * that is not strictly correct yet does not necessarily
+     * prohibit the system from attempting to launch the
+     * application.
+     *
+     * @return true if the launch should continue, false to abort
+     */
+    public boolean launchWarning(LaunchException warning) {
+        printMessage(warning);
+        return true;
+    }
+
+    /**
+     * Called when a security validation error occurs while
+     * launching the application.
+     *
+     * @return true to allow the application to continue, false to stop it.
+     */
+    public boolean validationError(LaunchException security) {
+        printMessage(security);
+        return true;
+    }
+
+    /**
+     * Called when an application, applet, or installer has been
+     * launched successfully (the main method or applet start method
+     * returned normally).
+     *
+     * @param application the launched application instance
+     */
+    public void launchCompleted(ApplicationInstance application) {
+        //
+    }
+
+    /**
+     * Print a message to stdout.
+     */
+    protected static void printMessage(LaunchException ex) {
+        StringBuffer result = new StringBuffer();
+        result.append("netx: ");
+        result.append(ex.getCategory());
+        if (ex.getSummary() != null) {
+            result.append(": ");
+            result.append(ex.getSummary());
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            if (ex.getCause() != null)
+                ex.getCause().printStackTrace();
+            else
+                ex.printStackTrace();
+        }
+
+        Throwable causes[] = ex.getCauses();
+
+        for (int i = 0; i < causes.length; i++) {
+            result.append(" (");
+            result.append(causes[i].getClass().getName());
+            result.append(" ");
+            result.append(causes[i].getMessage());
+            result.append(")");
+        }
+    }
+
+    /**
+     * Do nothing on when initializing
+     */
+    @Override
+    public void launchInitialized(JNLPFile file) {
+        // do nothing
+    }
+
+    /**
+     * Do nothing when starting
+     */
+    @Override
+    public void launchStarting(ApplicationInstance application) {
+        // do nothing
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DownloadOptions.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DownloadOptions.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/DownloadOptions.java	(revision 403)
@@ -0,0 +1,64 @@
+/* DownloadOptions.java
+   Copyright (C) 2011 Red Hat, Inc
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp;
+
+public class DownloadOptions {
+
+    private final boolean usePack200;
+    private final boolean useVersion;
+
+    public DownloadOptions(boolean usePack, boolean useVersion) {
+        this.usePack200 = usePack;
+        this.useVersion = useVersion;
+    }
+
+    public boolean useExplicitPack() {
+        return usePack200;
+    }
+
+    public boolean useExplicitVersion() {
+        return useVersion;
+    }
+
+    @Override
+    public String toString() {
+        return "DownloadOptions[use pack: " + usePack200 + "; use version: " +
+            useVersion + "]";
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ExtensionDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ExtensionDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ExtensionDesc.java	(revision 403)
@@ -0,0 +1,142 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * The extension element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.8 $
+ */
+public class ExtensionDesc {
+
+    /** the extension name */
+    private String name;
+
+    /** the required extension version */
+    private Version version;
+
+    /** the location of the extension JNLP file */
+    private URL location;
+
+    /** the JNLPFile the extension refers to */
+    private JNLPFile file;
+
+    /** map from ext-part to local part */
+    private Map<String, String> extToPart = new HashMap<String, String>();
+
+    /** eager ext parts */
+    private List<String> eagerExtParts = new ArrayList<String>();
+
+    /**
+     * Create an extention descriptor.
+     *
+     * @param name the extension name
+     * @param version the required version of the extention JNLPFile
+     * @param location the location of the extention JNLP file
+     */
+    public ExtensionDesc(String name, Version version, URL location) {
+        this.name = name;
+        this.version = version;
+        this.location = location;
+    }
+
+    /**
+     * Adds an extension part to be downloaded when the specified
+     * part of the main JNLP file is loaded.  The extension part
+     * will be downloaded before the application is launched if the
+     * lazy value is false or the part is empty or null.
+     *
+     * @param extPart the part name in the extension file
+     * @param part the part name in the main file
+     * @param lazy whether to load the part before launching
+     */
+    protected void addPart(String extPart, String part, boolean lazy) {
+        extToPart.put(extPart, part);
+
+        if (!lazy || part == null || part.length() == 0)
+            eagerExtParts.add(extPart);
+    }
+
+    /**
+     * Returns the parts in the extension JNLP file mapped to the
+     * part of the main file.
+     */
+    public String[] getExtensionParts(String thisPart) {
+
+        return null;
+    }
+
+    /**
+     * Returns the name of the extension.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the required version of the extension JNLP file.
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns the location of the extension JNLP file.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Resolves the extension by creating a JNLPFile from the file
+     * specified by the extension's location property.
+     *
+     * @throws IOException if the extension JNLPFile could not be resolved.
+     * @throws ParseException if the extension JNLPFile could not be
+     * parsed or was not a component or installer descriptor.
+     */
+    public void resolve() throws ParseException, IOException {
+        if (file == null) {
+            file = new JNLPFile(location);
+
+            if (JNLPRuntime.isDebug())
+                System.out.println("Resolve: " + file.getInformation().getTitle());
+
+            // check for it being an extension descriptor
+            if (!file.isComponent() && !file.isInstaller())
+                throw new ParseException(R("JInvalidExtensionDescriptor", name, location));
+        }
+
+    }
+
+    /**
+     * Returns a JNLPFile for the extension, or null if the JNLP
+     * file has not been resolved.
+     */
+    public JNLPFile getJNLPFile() {
+        return file;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/GuiLaunchHandler.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/GuiLaunchHandler.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/GuiLaunchHandler.java	(revision 403)
@@ -0,0 +1,123 @@
+/* GuiLaunchHandler.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp;
+
+import java.net.URL;
+
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.cache.ResourceTracker;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.util.BasicExceptionDialog;
+
+/**
+ * A {@link LaunchHandler} that gives feedback to the user using GUI elements
+ * including splash screens and exception dialogs.
+ */
+public class GuiLaunchHandler implements LaunchHandler {
+
+    private JNLPSplashScreen splashScreen = null;
+    private UpdatePolicy policy = UpdatePolicy.ALWAYS;
+
+    @Override
+    public void launchCompleted(ApplicationInstance application) {
+        // do nothing
+    }
+
+    @Override
+    public void launchError(final LaunchException exception) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                BasicExceptionDialog.show(exception);
+            }
+        });
+    }
+
+    @Override
+    public void launchStarting(ApplicationInstance application) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                if (splashScreen != null) {
+                    if (splashScreen.isSplashScreenValid()) {
+                        splashScreen.setVisible(false);
+                    }
+                    splashScreen.dispose();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void launchInitialized(final JNLPFile file) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                final int preferredWidth = 500;
+                final int preferredHeight = 400;
+
+                URL splashImageURL = file.getInformation().getIconLocation(
+                        IconDesc.SPLASH, preferredWidth, preferredHeight);
+                if (splashImageURL != null) {
+                    ResourceTracker resourceTracker = new ResourceTracker(true);
+                    resourceTracker.addResource(splashImageURL, file.getFileVersion(), null, policy);
+                    splashScreen = new JNLPSplashScreen(resourceTracker, null, null);
+                    splashScreen.setSplashImageURL(splashImageURL);
+                    if (splashScreen.isSplashScreenValid()) {
+                        splashScreen.setVisible(true);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public boolean launchWarning(LaunchException warning) {
+        DefaultLaunchHandler.printMessage(warning);
+        return true;
+    }
+
+    @Override
+    public boolean validationError(LaunchException security) {
+        DefaultLaunchHandler.printMessage(security);
+        return true;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/IconDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/IconDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/IconDesc.java	(revision 403)
@@ -0,0 +1,129 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.net.*;
+
+/**
+ * The icon element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.8 $
+ */
+public class IconDesc {
+
+    /** default icon */
+    public static final Object DEFAULT = "default";
+
+    /** selected icon */
+    public static final Object SELECTED = "selected";
+
+    /** disabled icon */
+    public static final Object DISABLED = "disabled";
+
+    /** rollover icon */
+    public static final Object ROLLOVER = "rollover";
+
+    /** splash icon */
+    public static final Object SPLASH = "splash";
+
+    /** destop shortcut icon */
+    public static final Object SHORTCUT = "shortcut";
+
+    /** the location of the icon */
+    private URL location;
+
+    /** the type of icon*/
+    private Object kind;
+
+    /** the width, or -1 if unknown*/
+    private int width;
+
+    /** the height, or -1 if unknown*/
+    private int height;
+
+    /** the depth, or -1 if unknown*/
+    private int depth;
+
+    /** the size, or -1 if unknown*/
+    private int size;
+
+    /**
+     * Creates an icon descriptor with the specified information.
+     *
+     * @param location the location of the icon
+     * @param kind the type of icon
+     * @param width the width, or -1 if unknown
+     * @param height the height, or -1 if unknown
+     * @param depth the depth, or -1 if unknown
+     * @param size the size, or -1 if unknown
+     */
+    IconDesc(URL location, Object kind, int width, int height, int depth, int size) {
+        this.location = location;
+        this.kind = kind;
+        this.width = width;
+        this.height = height;
+        this.depth = depth;
+        this.size = size;
+    }
+
+    /**
+     * Returns the location of the icon.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the icon type.
+     */
+    public Object getKind() {
+        return kind;
+    }
+
+    /**
+     * Returns the icon width or -1 if not specified in the
+     * JNLPFile.
+     */
+    public int getWidth() {
+        return width;
+    }
+
+    /**
+     * Returns the icon height or -1 if not specified in the
+     * JNLPFile.
+     */
+    public int getHeight() {
+        return height;
+    }
+
+    /**
+     * Returns the icon size or -1 if not specified in the JNLPFile.
+     */
+    public int getSize() {
+        return size;
+    }
+
+    /**
+     * Returns the icon depth or -1 if not specified in the
+     * JNLPFile.
+     */
+    public int getDepth() {
+        return depth;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InformationDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InformationDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InformationDesc.java	(revision 403)
@@ -0,0 +1,262 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.net.*;
+import java.util.*;
+
+/**
+ * The information element.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.9 $
+ */
+public class InformationDesc {
+
+    // There is an understanding between this class and the parser
+    // that description and icon types are keyed by "icon-"+kind and
+    // "description-"+kind, and that other types are keyed by their
+    // specification name.
+
+    /** one-line description */
+    public static final Object ONE_LINE = "oneline";
+
+    /** short description */
+    public static final Object SHORT = "short";
+
+    /** tooltip description */
+    public static final Object TOOLTIP = "tooltip";
+
+    /** default description */
+    public static final Object DEFAULT = "default";
+
+    /** the locales for the information */
+    private Locale locales[];
+
+    /** the data as list of key,value pairs */
+    private List<Object> info;
+
+    /** the JNLPFile this information is for */
+    private JNLPFile jnlpFile;
+
+    /**
+     * Create an information element object.
+     *
+     * @param jnlpFile file that the information is for
+     * @param locales the locales the information is for
+     */
+    public InformationDesc(JNLPFile jnlpFile, Locale locales[]) {
+        this.jnlpFile = jnlpFile;
+        this.locales = locales;
+    }
+
+    /**
+     * Returns the application's title.
+     */
+    public String getTitle() {
+        return (String) getItem("title");
+    }
+
+    /**
+     * Returns the application's vendor.
+     */
+    public String getVendor() {
+        return (String) getItem("vendor");
+    }
+
+    /**
+     * Returns the application's homepage.
+     */
+    public URL getHomepage() {
+        return (URL) getItem("homepage");
+    }
+
+    /**
+     * Returns the default description for the application.
+     */
+    public String getDescription() {
+        String result = getDescription(DEFAULT);
+
+        // try to find any description if default is null
+        if (result == null)
+            result = getDescription(ONE_LINE);
+        if (result == null)
+            result = getDescription(SHORT);
+        if (result == null)
+            result = getDescription(TOOLTIP);
+
+        return result;
+    }
+
+    /**
+     * Returns the application's description of the specified type.
+     *
+     * @param kind one of Information.SHORT, Information.ONE_LINE,
+     * Information.TOOLTIP, Information.DEFAULT
+     */
+    public String getDescription(Object kind) {
+        String result = (String) getItem("description-" + kind);
+        if (result == null)
+            return (String) getItem("description-" + DEFAULT);
+        else
+            return result;
+    }
+
+    /**
+     * Returns the icons specified by the JNLP file.
+     *
+     * @param kind one of IconDesc.SELECTED, IconDesc.DISABLED,
+     * IconDesc.ROLLOVER, IconDesc.SPLASH, IconDesc.DEFAULT
+     * @return an array of zero of more IconDescs of the specified icon type
+     */
+    public IconDesc[] getIcons(Object kind) {
+        List<Object> icons = getItems("icon-" + kind);
+
+        return icons.toArray(new IconDesc[icons.size()]);
+    };
+
+    /**
+     * Returns the URL of the icon closest to the specified size and
+     * kind.  This method will not return an icon smaller than the
+     * specified width and height unless there are no other icons
+     * available.
+     *
+     * @param kind the kind of icon to get
+     * @param width desired width of icon
+     * @param height desired height of icon
+     * @return the closest icon by size or null if no icons declared
+     */
+    public URL getIconLocation(Object kind, int width, int height) {
+        IconDesc icons[] = getIcons(kind);
+        if (icons.length == 0)
+            return null;
+
+        IconDesc best = null;
+        for (int i = 0; i < icons.length; i++) {
+            if (icons[i].getWidth() >= width &&
+                    icons[i].getHeight() >= height) {
+                if (best == null)
+                    best = icons[i];
+
+                if (icons[i].getWidth() <= best.getWidth() && // Use <= so last specified of
+                        icons[i].getHeight() <= best.getHeight()) // equivalent icons is chosen.
+                    best = icons[i];
+            }
+        }
+
+        if (best == null)
+            best = icons[0];
+
+        return best.getLocation();
+    }
+
+    /**
+     * Returns the locales for the information.
+     */
+    public Locale[] getLocales() {
+        return locales;
+    }
+
+    /**
+     * Returns the JNLPFile the information is for.
+     */
+    public JNLPFile getJNLPFile() {
+        return jnlpFile;
+    }
+
+    /**
+     * Returns whether offline execution allowed.
+     */
+    public boolean isOfflineAllowed() {
+        return null != getItem("offline-allowed");
+    }
+
+    /**
+     * Returns whether the resources specified in the JNLP file may
+     * be shared by more than one instance in the same JVM
+     * (JNLP extension).  This is an extension to the JNLP spec and
+     * will always return false for standard JNLP files.
+     */
+    public boolean isSharingAllowed() {
+        return null != getItem("sharing-allowed");
+    }
+
+    /**
+     * Returns the associations specified in the JNLP file
+     */
+    public AssociationDesc[] getAssociations() {
+        List<Object> associations = getItems("association");
+
+        return associations.toArray(new AssociationDesc[associations.size()]);
+    }
+
+    /**
+     * Returns the shortcut specified by this JNLP file
+     */
+    public ShortcutDesc getShortcut() {
+        return (ShortcutDesc) getItem("shortcut");
+    }
+
+    /**
+     * Returns the related-contents specified by this JNLP file
+     */
+    public RelatedContentDesc[] getRelatedContents() {
+        List<Object> relatedContents = getItems("related-content");
+
+        return relatedContents.toArray(new RelatedContentDesc[relatedContents.size()]);
+    }
+
+    /**
+     * Returns the last item matching the specified key.
+     */
+    protected Object getItem(Object key) {
+        List<Object> items = getItems(key);
+        if (items.size() == 0)
+            return null;
+        else
+            return items.get(items.size() - 1);
+    }
+
+    /**
+     * Returns all items matching the specified key.
+     */
+    protected List<Object> getItems(Object key) {
+        if (info == null)
+            return Collections.emptyList();
+
+        List<Object> result = new ArrayList<Object>();
+        for (int i = 0; i < info.size(); i += 2)
+            if (info.get(i).equals(key))
+                result.add(info.get(i + 1));
+
+        return result;
+    }
+
+    /**
+     * Add an information item (description, icon, etc) under a
+     * specified key name.
+     */
+    protected void addItem(String key, Object value) {
+        if (info == null)
+            info = new ArrayList<Object>();
+
+        info.add(key);
+        info.add(value);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InstallerDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InstallerDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/InstallerDesc.java	(revision 403)
@@ -0,0 +1,46 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+/**
+ * The installer-desc element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class InstallerDesc {
+
+    /** the main class name and package. */
+    private String mainClass;
+
+    /**
+     * Creates a installer descriptor.
+     *
+     * @param mainClass main class name and package
+     */
+    public InstallerDesc(String mainClass) {
+        this.mainClass = mainClass;
+    }
+
+    /**
+     * Returns the main class name and package.
+     */
+    public String getMainClass() {
+        return mainClass;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JARDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JARDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JARDesc.java	(revision 403)
@@ -0,0 +1,139 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.net.URL;
+
+/**
+ * The JAR element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class JARDesc {
+
+    /** the location of the JAR file */
+    private URL location;
+
+    /** the required JAR versions, or null */
+    private Version version;
+
+    /** the part name */
+    private String part;
+
+    /** whether to load the JAR on demand */
+    private boolean lazy;
+
+    /** whether the JAR contains the main class */
+    private boolean main;
+
+    /** whether the JAR contains native libraries */
+    private boolean nativeJar;
+
+    /** whether the JAR can be cached */
+    private boolean cacheable;
+
+    /**
+     * Create a JAR descriptor.
+     *
+     * @param location the location of the JAR file
+     * @param version the required JAR versions, or null
+     * @param part the part name, or null
+     * @param lazy whether to load the JAR on demand
+     * @param main whether the JAR contains the main class
+     * @param nativeJar whether the JAR contains native libraries
+     * @param cacheable whether the JAR can be cached or not
+     */
+    public JARDesc(URL location, Version version, String part, boolean lazy, boolean main, boolean nativeJar, boolean cacheable) {
+        this.location = location;
+        this.version = version;
+        this.part = part;
+        this.lazy = lazy;
+        this.main = main;
+        this.nativeJar = nativeJar;
+        this.cacheable = cacheable;
+    }
+
+    /**
+     * Returns the URL of the JAR file.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the required version of the JAR file.
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns the part name, or null if not specified in the JNLP
+     * file.
+     */
+    public String getPart() {
+        return part;
+    }
+
+    /**
+     * Returns true if the JAR file contains native code
+     * libraries.
+     */
+    public boolean isNative() {
+        return nativeJar;
+    }
+
+    // these both are included in case the spec adds a new value,
+    // where !lazy would no longer imply eager.
+
+    /**
+     * Returns true if the JAR file should be downloaded before
+     * starting the application.
+     */
+    public boolean isEager() {
+        return !lazy;
+    }
+
+    /**
+     * Returns true if the JAR file should be downloaded on demand.
+     */
+    public boolean isLazy() {
+        return lazy;
+    }
+
+    /**
+     * Returns true if the JNLP file defined this JAR as containing
+     * the main class.  If no JARs were defined as the main JAR then
+     * the first JAR should be used to locate the main class.
+     *
+     * @see ResourcesDesc#getMainJAR
+     */
+    public boolean isMain() {
+        return main;
+    }
+
+    /**
+     * Returns if this jar is cacheable
+     *
+     * @return Whether or not this jar is cacheable
+     */
+    public boolean isCacheable() {
+        return cacheable;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPFile.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPFile.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPFile.java	(revision 403)
@@ -0,0 +1,677 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+import net.sourceforge.jnlp.cache.ResourceTracker;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * Provides methods to access the information in a Java Network
+ * Launching Protocol (JNLP) file.  The Java Network Launching
+ * Protocol specifies in an XML file the information needed to
+ * load, cache, and run Java code over the network and in a secure
+ * environment.<p>
+ *
+ * This class represents the overall information about a JNLP file
+ * from the jnlp element.  Other information is accessed through
+ * objects that represent the elements of a JNLP file
+ * (information, resources, application-desc, etc).  References to
+ * these objects are obtained by calling the getInformation,
+ * getResources, getSecurity, etc methods.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.21 $
+ */
+public class JNLPFile {
+
+    // todo: save the update policy, then if file was not updated
+    // then do not check resources for being updated.
+    //
+    // todo: make getLaunchInfo return a superclass that all the
+    // launch types implement (can get codebase from it).
+    //
+    // todo: currently does not filter resources by jvm version.
+    //
+
+    /** the location this JNLP file was created from */
+    protected URL sourceLocation = null;
+
+    /** the network location of this JNLP file */
+    protected URL fileLocation;
+
+    /** A key that uniquely identifies connected instances (main jnlp+ext) */
+    protected String uniqueKey = null;
+
+    /** the URL used to resolve relative URLs in the file */
+    protected URL codeBase;
+
+    /** file version */
+    protected Version fileVersion;
+
+    /** spec version */
+    protected Version specVersion;
+
+    /** information */
+    protected List<InformationDesc> info;
+
+    protected UpdateDesc update;
+
+    /** resources */
+    protected List<ResourcesDesc> resources;
+
+    /** additional resources not in JNLP file (from command line) */
+    protected ResourcesDesc sharedResources = new ResourcesDesc(this, null, null, null);
+
+    /** the application description */
+    protected Object launchType;
+
+    /** the component description */
+    protected ComponentDesc component;
+
+    /** the security descriptor */
+    protected SecurityDesc security;
+
+    /** the default OS */
+    protected Locale defaultLocale = null;
+
+    /** the default arch */
+    protected String defaultOS = null;
+
+    /** the default jvm */
+    protected String defaultArch = null;
+
+    { // initialize defaults if security allows
+        try {
+            defaultLocale = Locale.getDefault();
+            defaultOS = System.getProperty("os.name");
+            defaultArch = System.getProperty("os.arch");
+        } catch (SecurityException ex) {
+            // null values will still work, and app can set defaults later
+        }
+    }
+
+    /**
+     * Empty stub, allowing child classes to override the constructor
+     */
+    protected JNLPFile() {
+    }
+
+    /**
+     * Create a JNLPFile from a URL.
+     *
+     * @param location the location of the JNLP file
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(URL location) throws IOException, ParseException {
+        this(location, false); // not strict
+    }
+
+    /**
+     * Create a JNLPFile from a URL checking for updates using the
+     * default policy.
+     *
+     * @param location the location of the JNLP file
+     * @param strict whether to enforce the spec when
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(URL location, boolean strict) throws IOException, ParseException {
+        this(location, (Version) null, strict);
+    }
+
+    /**
+     * Create a JNLPFile from a URL and a Version checking for updates using
+     * the default policy.
+     *
+     * @param location the location of the JNLP file
+     * @param version the version of the JNLP file
+     * @param strict whether to enforce the spec when
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(URL location, Version version, boolean strict) throws IOException, ParseException {
+        this(location, version, strict, JNLPRuntime.getDefaultUpdatePolicy());
+    }
+
+    /**
+     * Create a JNLPFile from a URL and a version, checking for updates
+     * using the specified policy.
+     *
+     * @param location the location of the JNLP file
+     * @param version the version of the JNLP file
+     * @param strict whether to enforce the spec when
+     * @param policy the update policy
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {
+        Node root = Parser.getRootNode(openURL(location, version, policy));
+        parse(root, strict, location);
+
+        //Downloads the original jnlp file into the cache if possible
+        //(i.e. If the jnlp file being launched exist locally, but it
+        //originated from a website, then download the one from the website
+        //into the cache).
+        if (sourceLocation != null && location.getProtocol() == "file") {
+            openURL(sourceLocation, version, policy);
+        }
+
+        this.fileLocation = location;
+
+        this.uniqueKey = Calendar.getInstance().getTimeInMillis() + "-" +
+                         ((int)(Math.random()*Integer.MAX_VALUE)) + "-" +
+                         location;
+
+        if (JNLPRuntime.isDebug())
+            System.err.println("UNIQUEKEY=" + this.uniqueKey);
+    }
+
+    /**
+     * Create a JNLPFile from a URL, parent URLm a version and checking for
+     * updates using the specified policy.
+     *
+     * @param location the location of the JNLP file
+     * @param uniqueKey A string that uniquely identifies connected instances
+     * @param version the version of the JNLP file
+     * @param strict whether to enforce the spec when
+     * @param policy the update policy
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(URL location, String uniqueKey, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {
+        this(location, version, strict, policy);
+        this.uniqueKey = uniqueKey;
+
+        if (JNLPRuntime.isDebug())
+            System.err.println("UNIQUEKEY (override) =" + this.uniqueKey);
+    }
+
+    /**
+     * Create a JNLPFile from an input stream.
+     *
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    public JNLPFile(InputStream input, boolean strict) throws ParseException {
+        parse(Parser.getRootNode(input), strict, null);
+    }
+
+    /**
+     * Create a JNLPFile from a character stream.
+     *
+     * @param input the stream
+     * @param strict whether to enforce the spec when
+     * @throws IOException if an IO exception occurred
+     * @throws ParseException if the JNLP file was invalid
+     */
+    private JNLPFile(Reader input, boolean strict) throws ParseException {
+        // todo: now that we are using NanoXML we can use a Reader
+        //parse(Parser.getRootNode(input), strict, null);
+    }
+
+    /**
+     * Open the jnlp file URL from the cache if there, otherwise
+     * download to the cache.  Called from constructor.
+     */
+    private static InputStream openURL(URL location, Version version, UpdatePolicy policy) throws IOException {
+        if (location == null || policy == null)
+            throw new IllegalArgumentException(R("NullParameter"));
+
+        try {
+            ResourceTracker tracker = new ResourceTracker(false); // no prefetch
+            tracker.addResource(location, version, null, policy);
+
+            return tracker.getInputStream(location);
+        } catch (Exception ex) {
+            throw new IOException(ex.getMessage());
+        }
+    }
+
+    /**
+     * Returns the JNLP file's title.  This method returns the same
+     * value as InformationDesc.getTitle().
+     */
+    public String getTitle() {
+        return getInformation().getTitle();
+    }
+
+    /**
+     * Returns the JNLP file's network location as specified in the
+     * JNLP file.
+     */
+    public URL getSourceLocation() {
+        return sourceLocation;
+    }
+
+    /**
+     * Returns the location of the file parsed to create the JNLP
+     * file, or null if it was not created from a URL.
+     */
+    public URL getFileLocation() {
+        return fileLocation;
+    }
+
+    /**
+     * Returns the location of the parent file if it exists, null otherwise
+     */
+    public String getUniqueKey() {
+        return uniqueKey;
+    }
+
+    /**
+     * Returns the JNLP file's version.
+     */
+    public Version getFileVersion() {
+        return fileVersion;
+    }
+
+    /**
+     * Returns the specification version required by the file.
+     */
+    public Version getSpecVersion() {
+        return specVersion;
+    }
+
+    /**
+     * Returns the codebase URL for the JNLP file.
+     */
+    public URL getCodeBase() {
+        return codeBase;
+    }
+
+    /**
+     * Returns the information section of the JNLP file as viewed
+     * through the default locale.
+     */
+    public InformationDesc getInformation() {
+        return getInformation(defaultLocale);
+    }
+
+    /**
+     * Returns the information section of the JNLP file as viewed
+     * through the specified locale.
+     */
+    public InformationDesc getInformation(final Locale locale) {
+        return new InformationDesc(this, new Locale[] { locale }) {
+            protected List<Object> getItems(Object key) {
+                List<Object> result = new ArrayList<Object>();
+
+                for (int i = 0; i < info.size(); i++) {
+                    InformationDesc infoDesc = info.get(i);
+
+                    if (localMatches(locale, infoDesc.getLocales()))
+                        result.addAll(infoDesc.getItems(key));
+                }
+
+                return result;
+            }
+        };
+    }
+
+    /**
+     * Returns the update section of the JNLP file.
+     */
+    public UpdateDesc getUpdate() {
+        return update;
+    }
+
+    /**
+     * Returns the security section of the JNLP file.
+     */
+    public SecurityDesc getSecurity() {
+        return security;
+    }
+
+    /**
+     * Returns the resources section of the JNLP file as viewed
+     * through the default locale and the os.name and os.arch
+     * properties.
+     */
+    public ResourcesDesc getResources() {
+        return getResources(defaultLocale, defaultOS, defaultArch);
+    }
+
+    /**
+     * Returns the resources section of the JNLP file for the
+     * specified locale, os, and arch.
+     */
+    public ResourcesDesc getResources(final Locale locale, final String os, final String arch) {
+        return new ResourcesDesc(this, new Locale[] { locale }, new String[] { os }, new String[] { arch }) {
+            public <T> List<T> getResources(Class<T> launchType) {
+                List<T> result = new ArrayList<T>();
+
+                for (int i = 0; i < resources.size(); i++) {
+                    ResourcesDesc rescDesc = resources.get(i);
+
+                    if (localMatches(locale, rescDesc.getLocales())
+                            && stringMatches(os, rescDesc.getOS())
+                            && stringMatches(arch, rescDesc.getArch()))
+                        result.addAll(rescDesc.getResources(launchType));
+                }
+
+                result.addAll(sharedResources.getResources(launchType));
+
+                return result;
+            }
+
+            public void addResource(Object resource) {
+                // todo: honor the current locale, os, arch values
+                sharedResources.addResource(resource);
+            }
+        };
+    }
+
+    /**
+     * Returns the resources section of the JNLP file as viewed
+     * through the default locale and the os.name and os.arch
+     * properties.
+     * XXX: Before overriding this method or changing its implementation,
+     * read the comment in JNLPFile.getDownloadOptionsForJar(JARDesc).
+     */
+    public ResourcesDesc[] getResourcesDescs() {
+        return getResourcesDescs(defaultLocale, defaultOS, defaultArch);
+    }
+
+    /**
+     * Returns the resources section of the JNLP file for the
+     * specified locale, os, and arch.
+     */
+    public ResourcesDesc[] getResourcesDescs(final Locale locale, final String os, final String arch) {
+        List<ResourcesDesc> matchingResources = new ArrayList<ResourcesDesc>();
+        for (ResourcesDesc rescDesc: resources) {
+            if (localMatches(locale, rescDesc.getLocales())
+                    && stringMatches(os, rescDesc.getOS())
+                    && stringMatches(arch, rescDesc.getArch())) {
+                matchingResources.add(rescDesc);
+            }
+        }
+        return matchingResources.toArray(new ResourcesDesc[0]);
+    }
+
+    /**
+     * Returns an object of one of the following types: AppletDesc,
+     * ApplicationDesc and InstallerDesc
+     */
+    public Object getLaunchInfo() {
+        return launchType;
+    }
+
+    /**
+     * Returns the launch information for an applet.
+     *
+     * @throws UnsupportedOperationException if there is no applet information
+     */
+    public AppletDesc getApplet() {
+        if (!isApplet())
+            throw new UnsupportedOperationException(R("JNotApplet"));
+
+        return (AppletDesc) launchType;
+    }
+
+    /**
+     * Returns the launch information for an application.
+     *
+     * @throws UnsupportedOperationException if there is no application information
+     */
+    public ApplicationDesc getApplication() {
+        if (!isApplication())
+            throw new UnsupportedOperationException(R("JNotApplication"));
+
+        return (ApplicationDesc) launchType;
+    }
+
+    /**
+     * Returns the launch information for a component.
+     *
+     * @throws UnsupportedOperationException if there is no component information
+     */
+    public ComponentDesc getComponent() {
+        if (!isComponent())
+            throw new UnsupportedOperationException(R("JNotComponent"));
+
+        return component;
+    }
+
+    /**
+     * Returns the launch information for an installer.
+     *
+     * @throws UnsupportedOperationException if there is no installer information
+     */
+    public InstallerDesc getInstaller() {
+        if (!isInstaller())
+            throw new UnsupportedOperationException(R("NotInstaller"));
+
+        return (InstallerDesc) launchType;
+    }
+
+    /**
+     * Returns whether the lauch descriptor describes an Applet.
+     */
+    public boolean isApplet() {
+        return launchType instanceof AppletDesc;
+    }
+
+    /**
+     * Returns whether the lauch descriptor describes an Application.
+     */
+    public boolean isApplication() {
+        return launchType instanceof ApplicationDesc;
+    }
+
+    /**
+     * Returns whether the lauch descriptor describes a Component.
+     */
+    public boolean isComponent() {
+        return component != null;
+    }
+
+    /**
+     * Returns whether the lauch descriptor describes an Installer.
+     */
+    public boolean isInstaller() {
+        return launchType instanceof InstallerDesc;
+    }
+
+    /**
+     * Sets the default view of the JNLP file returned by
+     * getInformation, getResources, etc.  If unset, the defaults
+     * are the properties os.name, os.arch, and the locale returned
+     * by Locale.getDefault().
+     */
+    public void setDefaults(String os, String arch, Locale locale) {
+        defaultOS = os;
+        defaultArch = arch;
+        defaultLocale = locale;
+    }
+
+    /**
+     * Returns whether a locale is matched by one of more other
+     * locales.  Only the non-empty language, country, and variant
+     * codes are compared; for example, a requested locale of
+     * Locale("","","") would always return true.
+     *
+     * @param requested the local
+     * @param available the available locales
+     * @return true if requested matches any of available, or if
+     * available is empty or null.
+     */
+    private boolean localMatches(Locale requested, Locale available[]) {
+        if (available == null || available.length == 0)
+            return true;
+
+        for (int i = 0; i < available.length; i++) {
+            String language = requested.getLanguage(); // "" but never null
+            String country = requested.getCountry();
+            String variant = requested.getVariant();
+
+            if (!"".equals(language) && !language.equalsIgnoreCase(available[i].getLanguage()))
+                continue;
+            if (!"".equals(country) && !country.equalsIgnoreCase(available[i].getCountry()))
+                continue;
+            if (!"".equals(variant) && !variant.equalsIgnoreCase(available[i].getVariant()))
+                continue;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns whether the string is a prefix for any of the strings
+     * in the specified array.
+     *
+     * @param prefixStr the prefix string
+     * @param available the strings to test
+     * @return true if prefixStr is a prefix of any strings in
+     * available, or if available is empty or null.
+     */
+    private boolean stringMatches(String prefixStr, String available[]) {
+        if (available == null || available.length == 0)
+            return true;
+
+        for (int i = 0; i < available.length; i++)
+            if (available[i] != null && available[i].startsWith(prefixStr))
+                return true;
+
+        return false;
+    }
+
+    /**
+     * Initialize the JNLPFile fields. Private because it's called
+     * from the constructor.
+     *
+     * @param root the root node
+     * @param strict whether to enforce the spec when
+     * @param location the file location or null
+     */
+    private void parse(Node root, boolean strict, URL location) throws ParseException {
+        try {
+            //if (location != null)
+            //  location = new URL(location, "."); // remove filename
+
+            Parser parser = new Parser(this, location, root, strict, true); // true == allow extensions
+
+            // JNLP tag information
+            specVersion = parser.getSpecVersion();
+            fileVersion = parser.getFileVersion();
+            codeBase = parser.getCodeBase();
+            sourceLocation = parser.getFileLocation() != null ? parser.getFileLocation() : location;
+            info = parser.getInfo(root);
+            update = parser.getUpdate(root);
+            resources = parser.getResources(root, false); // false == not a j2se/java resources section
+            launchType = parser.getLauncher(root);
+            component = parser.getComponent(root);
+            security = parser.getSecurity(root);
+        } catch (ParseException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            throw new RuntimeException(ex.toString());
+        }
+    }
+
+    /**
+     *
+     * @return true if the JNLP file specifies things that can only be
+     * applied on a new vm (eg: different max heap memory)
+     */
+    public boolean needsNewVM() {
+
+        if (getNewVMArgs().size() == 0) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     *  @return a list of args to pass to the new
+     *  JVM based on this JNLP file
+     */
+    public List<String> getNewVMArgs() {
+
+        List<String> newVMArgs = new LinkedList<String>();
+
+        JREDesc[] jres = getResources().getJREs();
+        for (int jreIndex = 0; jreIndex < jres.length; jreIndex++) {
+            String initialHeapSize = jres[jreIndex].getInitialHeapSize();
+            if (initialHeapSize != null) {
+                newVMArgs.add("-Xms" + initialHeapSize);
+            }
+
+            String maxHeapSize = jres[jreIndex].getMaximumHeapSize();
+            if (maxHeapSize != null) {
+                newVMArgs.add("-Xmx" + maxHeapSize);
+            }
+
+            String vmArgsFromJre = jres[jreIndex].getVMArgs();
+            if (vmArgsFromJre != null) {
+                String[] args = vmArgsFromJre.split(" ");
+                newVMArgs.addAll(Arrays.asList(args));
+            }
+        }
+
+        return newVMArgs;
+    }
+
+    /**
+     * XXX: this method does a "==" comparison between the input JARDesc and
+     * jars it finds through getResourcesDescs(). If ever the implementation
+     * of that function should change to return copies of JARDescs objects,
+     * then the "jar == aJar" comparison below should change accordingly.
+     * @param jar: the jar whose download options to get.
+     * @return the download options.
+     */
+    public DownloadOptions getDownloadOptionsForJar(JARDesc jar) {
+        boolean usePack = false;
+        boolean useVersion = false;
+        ResourcesDesc[] descs = getResourcesDescs();
+        for (ResourcesDesc desc: descs) {
+            JARDesc[] jars = desc.getJARs();
+            for (JARDesc aJar: jars) {
+                if (jar == aJar) {
+                    if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.packEnabled"))) {
+                        usePack = true;
+                    }
+                    if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.versionEnabled"))) {
+                        useVersion = true;
+                    }
+                }
+            }
+        }
+        return new DownloadOptions(usePack, useVersion);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPSplashScreen.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPSplashScreen.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JNLPSplashScreen.java	(revision 403)
@@ -0,0 +1,99 @@
+package net.sourceforge.jnlp;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+
+import net.sourceforge.jnlp.cache.ResourceTracker;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class JNLPSplashScreen extends JFrame {
+
+    String applicationTitle;
+    String applicationVendor;
+
+    ResourceTracker resourceTracker;
+
+    URL splashImageUrl;
+    Image splashImage;
+
+    public JNLPSplashScreen(ResourceTracker resourceTracker,
+            String applicationTitle, String applicationVendor) {
+
+        // If the JNLP file does not contain any icon images, the splash image
+        // will consist of the application's title and vendor, as taken from the
+        // JNLP file.
+
+        this.resourceTracker = resourceTracker;
+        this.applicationTitle = applicationTitle;
+        this.applicationVendor = applicationVendor;
+
+    }
+
+    public void setSplashImageURL(URL url) {
+        splashImageUrl = url;
+        splashImage = null;
+        try {
+            splashImage = ImageIO.read(resourceTracker
+                    .getCacheFile(splashImageUrl));
+            if (splashImage == null) {
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("Error loading splash image: " + url);
+                }
+                return;
+            }
+        } catch (IOException e) {
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Error loading splash image: " + url);
+            }
+            splashImage = null;
+            return;
+        } catch (IllegalArgumentException argumentException) {
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Error loading splash image: " + url);
+            }
+            splashImage = null;
+            return;
+        }
+
+        correctSize();
+    }
+
+    public boolean isSplashScreenValid() {
+        return (splashImage != null);
+    }
+
+    private void correctSize() {
+
+        Insets insets = getInsets();
+        int minimumWidth = splashImage.getWidth(null) + insets.left
+                + insets.right;
+        int minimumHeight = splashImage.getHeight(null) + insets.top
+                + insets.bottom;
+        setMinimumSize(new Dimension(minimumWidth, minimumHeight));
+
+        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+        setLocation((screenSize.width - minimumWidth) / 2,
+                (screenSize.height - minimumHeight) / 2);
+    }
+
+    @Override
+    public void paint(Graphics g) {
+        if (splashImage == null) {
+            return;
+        }
+
+        correctSize();
+        Graphics2D g2 = (Graphics2D) g;
+        g2.drawImage(splashImage, getInsets().left, getInsets().top, null);
+
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JREDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JREDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/JREDesc.java	(revision 403)
@@ -0,0 +1,162 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.net.*;
+import java.util.*;
+
+/**
+ * The J2SE/Java element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public class JREDesc {
+
+    /** the platform version or the product version if location is not null */
+    private Version version;
+
+    /** the location of a JRE product or null */
+    private URL location;
+
+    /** inital heap size */
+    private String initialHeapSize;
+
+    /** maximum head size */
+    private String maximumHeapSize;
+
+    /** args to pass to the vm */
+    private String vmArgs;
+
+    /** list of ResourceDesc objects */
+    private List resources;
+
+    /**
+     * Create a JRE descriptor.
+     *
+     * @param version the platform version or the product version
+     * if location is not null
+     * @param location the location of a JRE product or null
+     * @param initialHeapSize inital heap size
+     * @param maximumHeapSize maximum head size
+     * @param resources list of ResourceDesc objects
+     */
+    public JREDesc(Version version, URL location,
+            String vmArgs, String initialHeapSize,
+            String maximumHeapSize, List resources) throws ParseException {
+        this.version = version;
+        this.location = location;
+        this.vmArgs = vmArgs;
+        checkHeapSize(initialHeapSize);
+        this.initialHeapSize = initialHeapSize;
+        checkHeapSize(maximumHeapSize);
+        this.maximumHeapSize = maximumHeapSize;
+        this.resources = resources;
+    }
+
+    /**
+     * Returns the JRE version.  Use isPlatformVersion to
+     * determine if this version corresponds to a platform or
+     * product version.
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns true if the JRE version is a Java platform version
+     * (java.specification.version property) or false if it is a
+     * product version (java.version property).
+     */
+    public boolean isPlatformVersion() {
+        return getLocation() == null;
+    }
+
+    /**
+     * Returns the JRE version string.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the maximum heap size in bytes.
+     */
+    public String getMaximumHeapSize() {
+        return maximumHeapSize;
+    }
+
+    /**
+     * Returns the initial heap size in bytes.
+     */
+    public String getInitialHeapSize() {
+        return initialHeapSize;
+    }
+
+    /**
+     * Returns the resources defined for this JRE.
+     */
+    public List getResourcesDesc() {
+        return resources;
+    }
+
+    /**
+     * Returns the additional arguments to pass to the Java VM
+     * Can be null
+     */
+    public String getVMArgs() {
+        return vmArgs;
+    }
+
+    /**
+     * Check for valid heap size string
+     * @throws ParseException if heapSize is invalid
+     */
+    static private void checkHeapSize(String heapSize) throws ParseException {
+        // need to implement for completeness even though not used in netx
+        if (heapSize == null) {
+            return;
+        }
+
+        boolean lastCharacterIsDigit = true;
+        // the last character must be 0-9 or k/K/m/M
+        char lastChar = Character.toLowerCase(heapSize.charAt(heapSize.length() - 1));
+        if ((lastChar < '0' || lastChar > '9')) {
+            lastCharacterIsDigit = false;
+            if (lastChar != 'k' && lastChar != 'm') {
+                throw new ParseException(R("PBadHeapSize", heapSize));
+            }
+        }
+
+        int indexOfLastDigit = heapSize.length() - 1;
+        if (!lastCharacterIsDigit) {
+            indexOfLastDigit = indexOfLastDigit - 1;
+        }
+
+        String size = heapSize.substring(0, indexOfLastDigit);
+        try {
+            // check that the number is a number!
+            Integer.valueOf(size);
+        } catch (NumberFormatException numberFormat) {
+            throw new ParseException(R("PBadHeapSize", heapSize), numberFormat);
+        }
+
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchException.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchException.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchException.java	(revision 403)
@@ -0,0 +1,187 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.io.*;
+import java.util.*;
+
+import net.sourceforge.jnlp.util.*;
+
+/**
+ * Thrown when a JNLP application, applet, or installer could not
+ * be created.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.9 $
+ */
+public class LaunchException extends Exception {
+
+    /** the original exception */
+    private Throwable cause = null;
+
+    /** the file being launched */
+    private JNLPFile file;
+
+    /** the category of the exception */
+    private String category;
+
+    /** summary */
+    private String summary;
+
+    /** description of the action that was taking place */
+    private String description;
+
+    /** severity of the warning/error */
+    private String severity;
+
+    /**
+     * Creates a LaunchException without detail message.
+     */
+    public LaunchException(JNLPFile file, Exception cause, String severity, String category, String summary, String description) {
+        super(severity + ": " + category + ": " + summary);
+
+        this.file = file;
+        this.category = category;
+        this.summary = summary;
+        this.description = description;
+        this.severity = severity;
+
+        // replace with setCause when no longer 1.3 compatible
+        this.cause = cause;
+    }
+
+    /**
+     * Creates a LaunchException with a cause.
+     */
+    public LaunchException(Throwable cause) {
+        this(cause.getMessage());
+
+        // replace with setCause when no longer 1.3 compatible
+        this.cause = cause;
+    }
+
+    /**
+     * Creates a LaunchException with a cause and detail message
+     */
+    public LaunchException(String message, Throwable cause) {
+        this(message + ": " + cause.getMessage());
+
+        // replace with setCause when no longer 1.3 compatible
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a LaunchException with the specified detail
+     * message.
+     *
+     * @param message the detail message
+     */
+    public LaunchException(String message) {
+        super(message);
+    }
+
+    /**
+     * Returns the JNLPFile being launched.
+     */
+    public JNLPFile getFile() {
+        return file;
+    }
+
+    /**
+     * Returns the category string, a short description of the
+     * exception suitable for displaying in a window title.
+     */
+    public String getCategory() {
+        return category;
+    }
+
+    /**
+     * Returns a one-sentence summary of the problem.
+     */
+    public String getSummary() {
+        return summary;
+    }
+
+    /**
+     * Return a description of the exception and the action being
+     * performed when the exception occurred.
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Returns a short description of the severity of the problem.
+     */
+    public String getSeverity() {
+        return severity;
+    }
+
+    /**
+     * Return the cause of the launch exception or null if there
+     * is no cause exception.
+     */
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the causes for this exception.  This method is
+     * useful on JRE 1.3 since getCause is not a standard method,
+     * and will be removed once netx no longer supports 1.3.
+     */
+    public Throwable[] getCauses() {
+        ArrayList<Throwable> result = new ArrayList<Throwable>();
+
+        Reflect r = new Reflect();
+        Throwable cause = this.cause;
+
+        while (cause != null) {
+            result.add(cause);
+            cause = (Throwable) r.invoke(cause, "getCause");
+        }
+
+        return result.toArray(new Throwable[0]);
+    }
+
+    /**
+     * Print the stack trace and the cause exception (1.3
+     * compatible)
+     */
+    public void printStackTrace(PrintStream stream) {
+        super.printStackTrace(stream);
+
+        if (cause != null) {
+            stream.println("Caused by: ");
+            cause.printStackTrace(stream);
+        }
+    }
+
+    /**
+     * Print the stack trace and the cause exception (1.3
+     * compatible)
+     */
+    public void printStackTrace(PrintWriter stream) {
+        super.printStackTrace(stream);
+
+        if (cause != null) {
+            stream.println("Caused by: ");
+            cause.printStackTrace(stream);
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchHandler.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchHandler.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/LaunchHandler.java	(revision 403)
@@ -0,0 +1,85 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * This optional interface is used to handle conditions that occur
+ * while launching JNLP applications, applets, and installers.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.9 $
+ */
+public interface LaunchHandler {
+
+    /**
+     * Called when the application could not be launched due to a
+     * fatal error, such as the inability to find the main class or
+     * non-parseable XML.
+     */
+    public void launchError(LaunchException exception);
+
+    /**
+     * Called when launching the application can not be launched due
+     * to an error that is not fatal.  For example a JNLP file that
+     * is not strictly correct yet does not necessarily prohibit the
+     * system from attempting to launch the application.
+     *
+     * @return true if the launch should continue, false to abort
+     */
+    public boolean launchWarning(LaunchException warning);
+
+    /**
+     * Called when a security validation error occurs while
+     * launching the application.
+     *
+     * @return true to allow the application to continue, false to stop it.
+     */
+    public boolean validationError(LaunchException security);
+
+    // this method will probably be replaced when real security
+    // controller is in place.
+
+    /**
+     * Called when an application, applet or installer has been determined.
+     * We have some very basic information about the application at this point,
+     * but do not have everything required. This is a nice point to show the
+     * splash screen.
+     *
+     * @param application the application instance that is starting
+     */
+    public void launchInitialized(JNLPFile file);
+
+    /**
+     * Called when an application, applet or installer is ready to start.
+     * Good point to hide the splash screen.
+     *
+     * @param application the application instance that is ready
+     */
+    public void launchStarting(ApplicationInstance application);
+
+    /**
+     * Called when an application, applet, or installer has been
+     * launched successfully (the main method or applet start method
+     * returned normally).
+     *
+     * @param application the launched application instance
+     */
+    public void launchCompleted(ApplicationInstance application);
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Launcher.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Launcher.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Launcher.java	(revision 403)
@@ -0,0 +1,943 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.applet.Applet;
+import java.awt.Container;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarFile;
+
+import net.sourceforge.jnlp.cache.CacheUtil;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.runtime.AppThreadGroup;
+import net.sourceforge.jnlp.runtime.AppletInstance;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.services.InstanceExistsException;
+import net.sourceforge.jnlp.services.ServiceUtil;
+
+import javax.swing.SwingUtilities;
+import javax.swing.text.html.parser.ParserDelegator;
+
+import sun.awt.SunToolkit;
+
+/**
+ * Launches JNLPFiles either in the foreground or background.<p>
+ *
+ * An optional LaunchHandler can be specified that is notified of
+ * warning and error condition while launching and that indicates
+ * whether a launch may proceed after a warning has occurred.  If
+ * specified, the LaunchHandler is notified regardless of whether
+ * the file is launched in the foreground or background.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.22 $
+ */
+public class Launcher {
+
+    // defines class Launcher.BgRunner, Launcher.TgThread
+
+    /** shared thread group */
+    /*package*/static final ThreadGroup mainGroup = new ThreadGroup(R("LAllThreadGroup"));
+
+    /** the handler */
+    private LaunchHandler handler = null;
+
+    /** the update policy */
+    private UpdatePolicy updatePolicy = JNLPRuntime.getDefaultUpdatePolicy();
+
+    /** whether to create an AppContext (if possible) */
+    private boolean context = true;
+
+    /** If the application should call System.exit on fatal errors */
+    private boolean exitOnFailure = true;
+
+    private ParserSettings parserSettings = new ParserSettings();
+
+    private Map<String, String[]> extra = null;
+
+    /**
+     * Create a launcher with the runtime's default update policy
+     * and launch handler.
+     */
+    public Launcher() {
+        this(null, null);
+
+        if (handler == null)
+            handler = JNLPRuntime.getDefaultLaunchHandler();
+    }
+
+    /**
+     * Create a launcher with the runtime's default update policy
+     * and launch handler.
+     *
+     * @param exitOnFailure Exit if there is an error (usually default, but false when being used from the plugin)
+     */
+    public Launcher(boolean exitOnFailure) {
+        this(null, null);
+
+        if (handler == null)
+            handler = JNLPRuntime.getDefaultLaunchHandler();
+
+        this.exitOnFailure = exitOnFailure;
+    }
+
+    /**
+     * Create a launcher with the specified handler and the
+     * runtime's default update policy.
+     *
+     * @param handler the handler to use or null for no handler.
+     */
+    public Launcher(LaunchHandler handler) {
+        this(handler, null);
+    }
+
+    /**
+     * Create a launcher with an optional handler using the
+     * specified update policy and launch handler.
+     *
+     * @param handler the handler to use or null for no handler.
+     * @param policy the update policy to use or null for default policy.
+     */
+    public Launcher(LaunchHandler handler, UpdatePolicy policy) {
+        if (policy == null)
+            policy = JNLPRuntime.getDefaultUpdatePolicy();
+
+        this.handler = handler;
+        this.updatePolicy = policy;
+
+    }
+
+    /**
+     * Sets the update policy used by launched applications.
+     */
+    public void setUpdatePolicy(UpdatePolicy policy) {
+        if (policy == null)
+            throw new IllegalArgumentException(R("LNullUpdatePolicy"));
+
+        this.updatePolicy = policy;
+    }
+
+    /**
+     * Returns the update policy used when launching applications.
+     */
+    public UpdatePolicy getUpdatePolicy() {
+        return updatePolicy;
+    }
+
+    /**
+     * Sets whether to launch the application in a new AppContext
+     * (a separate event queue, look and feel, etc).  If the
+     * sun.awt.SunToolkit class is not present then this method
+     * has no effect.  The default value is true.
+     */
+    public void setCreateAppContext(boolean context) {
+        this.context = context;
+    }
+
+    /**
+     * Returns whether applications are launched in their own
+     * AppContext.
+     */
+    public boolean isCreateAppContext() {
+        return this.context;
+    }
+
+    /**
+     * Set the parser settings to use when the Launcher initiates parsing of
+     * a JNLP file.
+     * @param settings
+     */
+    public void setParserSettings(ParserSettings settings) {
+        parserSettings = settings;
+    }
+
+    /**
+     * Set a map to use when trying to extract extra information, including
+     * arguments, properties and parameters, to be merged into the main JNLP
+     * @param input a map containing extra information to add to the main JNLP.
+     * the values for keys "arguments", "parameters", and "properties" are
+     * used.
+     */
+    public void setInformationToMerge(Map<String, String[]> input) {
+        this.extra = input;
+    }
+
+    /**
+     * Launches a JNLP file by calling the launch method for the
+     * appropriate file type.  The application will be started in
+     * a new window.
+     *
+     * @param file the JNLP file to launch
+     * @return the application instance
+     * @throws LaunchException if an error occurred while launching (also sent to handler)
+     */
+    public ApplicationInstance launch(JNLPFile file) throws LaunchException {
+        return launch(file, null);
+    }
+
+    /**
+     * Launches a JNLP file inside the given container if it is an applet.  Specifying a
+     * container has no effect for Applcations and Installers.
+     *
+     * @param file the JNLP file to launch
+     * @param cont the container in which to place the application, if it is an applet
+     * @return the application instance
+     * @throws LaunchException if an error occurred while launching (also sent to handler)
+     */
+    public ApplicationInstance launch(JNLPFile file, Container cont) throws LaunchException {
+        TgThread tg;
+
+        mergeExtraInformation(file, extra);
+
+        JNLPRuntime.markNetxRunning();
+
+        //First checks whether offline-allowed tag is specified inside the jnlp
+        //file.
+        if (!file.getInformation().isOfflineAllowed()) {
+            try {
+                //Checks the offline/online status of the system.
+                //If system is offline do not launch.
+                InetAddress.getByName(file.getSourceLocation().getHost());
+
+            } catch (UnknownHostException ue) {
+                System.err.println("File cannot be launched because offline-allowed tag not specified and system currently offline.");
+                return null;
+            } catch (Exception e) {
+                System.err.println(e);
+            }
+        }
+
+        if (file instanceof PluginBridge && cont != null)
+            tg = new TgThread(file, cont, true);
+        else if (cont == null)
+            tg = new TgThread(file);
+        else
+            tg = new TgThread(file, cont);
+
+        tg.start();
+
+        try {
+            tg.join();
+        } catch (InterruptedException ex) {
+            //By default, null is thrown here, and the message dialog is shown.
+            throw launchWarning(new LaunchException(file, ex, R("LSMinor"), R("LCSystem"), R("LThreadInterrupted"), R("LThreadInterruptedInfo")));
+        }
+
+        if (tg.getException() != null)
+            throw tg.getException(); // passed to handler when first created
+
+        if (handler != null)
+            handler.launchCompleted(tg.getApplication());
+
+        return tg.getApplication();
+    }
+
+    /**
+     * Launches a JNLP file by calling the launch method for the
+     * appropriate file type.
+     *
+     * @param location the URL of the JNLP file to launch
+     * @throws LaunchException if there was an exception
+     * @return the application instance
+     */
+    public ApplicationInstance launch(URL location) throws LaunchException {
+        return launch(toFile(location));
+    }
+
+    /**
+     * Launches a JNLP file by calling the launch method for the
+     * appropriate file type.
+     *
+     * @param location the URL of the JNLP file to launch
+     * @param fromSource if true, the JNLP file will be re-read from the source
+     * location to get the pristine version
+     * @throws LaunchException if there was an exception
+     * @return the application instance
+     */
+    public ApplicationInstance launch(URL location, boolean fromSource) throws LaunchException {
+        return launch(fromUrl(location, fromSource));
+    }
+
+    /**
+     * Merges extra information into the jnlp file
+     *
+     * @param file the JNLPFile
+     * @param extra extra information to merge into the JNLP file
+     * @throws LaunchException if an exception occurs while extracting
+     * extra information
+     */
+    private void mergeExtraInformation(JNLPFile file, Map<String, String[]> extra) throws LaunchException {
+        if (extra == null) {
+            return;
+        }
+
+        String[] properties = extra.get("properties");
+        if (properties != null) {
+            addProperties(file, properties);
+        }
+
+        String[] arguments = extra.get("arguments");
+        if (arguments != null && file.isApplication()) {
+            addArguments(file, arguments);
+        }
+
+        String[] parameters = extra.get("parameters");
+        if (parameters != null && file.isApplet()) {
+            addParameters(file, parameters);
+        }
+    }
+
+    /**
+     * Add the properties to the JNLP file.
+     * @throws LaunchException if an exception occurs while extracting
+     * extra information
+     */
+    private void addProperties(JNLPFile file, String[] props) throws LaunchException {
+        ResourcesDesc resources = file.getResources();
+
+        for (int i = 0; i < props.length; i++) {
+            // allows empty property, not sure about validity of that.
+            int equals = props[i].indexOf("=");
+            if (equals == -1) {
+                throw launchError(new LaunchException(R("BBadProp", props[i])));
+            }
+
+            String key = props[i].substring(0, equals);
+            String value = props[i].substring(equals + 1, props[i].length());
+
+            resources.addResource(new PropertyDesc(key, value));
+        }
+    }
+
+    /**
+     * Add the params to the JNLP file; only call if file is
+     * actually an applet file.
+     * @throws LaunchException if an exception occurs while extracting
+     * extra information
+     */
+    private void addParameters(JNLPFile file, String[] params) throws LaunchException {
+        AppletDesc applet = file.getApplet();
+
+        for (int i = 0; i < params.length; i++) {
+            // allows empty param, not sure about validity of that.
+            int equals = params[i].indexOf("=");
+            if (equals == -1) {
+                throw launchError(new LaunchException(R("BBadParam", params[i])));
+            }
+
+            String name = params[i].substring(0, equals);
+            String value = params[i].substring(equals + 1, params[i].length());
+
+            applet.addParameter(name, value);
+        }
+    }
+
+    /**
+     * Add the arguments to the JNLP file; only call if file is
+     * actually an application (not installer).
+     */
+    private void addArguments(JNLPFile file, String[] args) {
+        ApplicationDesc app = file.getApplication();
+
+        for (int i = 0; i < args.length; i++) {
+            app.addArgument(args[i]);
+        }
+    }
+
+    /**
+     * Launches a JNLP file by calling the launch method for the
+     * appropriate file type in a different thread.
+     *
+     * @param file the JNLP file to launch
+     */
+    public void launchBackground(JNLPFile file) {
+        BgRunner runner = new BgRunner(file, null);
+        new Thread(runner).start();
+    }
+
+    /**
+     * Launches the JNLP file at the specified location in the
+     * background by calling the launch method for its file type.
+     *
+     * @param location the location of the JNLP file
+     */
+    public void launchBackground(URL location) {
+        BgRunner runner = new BgRunner(null, location);
+        new Thread(runner).start();
+    }
+
+    /**
+     * Launches the JNLP file in a new JVM instance.  The launched
+     * application's output is sent to the system out and it's
+     * standard input channel is closed.
+     *
+     * @param vmArgs the arguments to pass to the new JVM. Can be empty but
+     *        must not be null.
+     * @param file the JNLP file to launch
+     * @param javawsArgs the arguments to pass to the javaws command. Can be
+     *        an empty list but must not be null.
+     * @throws LaunchException if there was an exception
+     */
+    public void launchExternal(List<String> vmArgs, JNLPFile file, List<String> javawsArgs) throws LaunchException {
+        List<String> updatedArgs = new LinkedList<String>(javawsArgs);
+
+        if (file.getFileLocation() != null)
+            updatedArgs.add(file.getFileLocation().toString());
+        else if (file.getSourceLocation() != null)
+            updatedArgs.add(file.getFileLocation().toString());
+        else
+            launchError(new LaunchException(file, null, R("LSFatal"), R("LCExternalLaunch"), R("LNullLocation"), R("LNullLocationInfo")));
+
+        launchExternal(vmArgs, updatedArgs);
+
+    }
+
+    /**
+     * Launches the JNLP file in a new JVM instance.  The launched
+     * application's output is sent to the system out and it's
+     * standard input channel is closed.
+     *
+     * @param url the URL of the JNLP file to launch
+     * @throws LaunchException if there was an exception
+     */
+    public void launchExternal(URL url) throws LaunchException {
+        List<String> javawsArgs = new LinkedList<String>();
+        javawsArgs.add(url.toString());
+        launchExternal(new LinkedList<String>(), javawsArgs);
+    }
+
+    /**
+     * Launches the JNLP file at the specified location in a new JVM
+     * instance.  The launched application's output is sent to the
+     * system out and it's standard input channel is closed.
+     * @param vmArgs the arguments to pass to the jvm
+     * @param javawsArgs the arguments to pass to javaws (aka Netx)
+     * @throws LaunchException if there was an exception
+     */
+    public void launchExternal(List<String> vmArgs, List<String> javawsArgs) throws LaunchException {
+        try {
+
+            List<String> commands = new LinkedList<String>();
+
+            // this property is set by the javaws launcher to point to the javaws binary
+            String pathToWebstartBinary = System.getProperty("icedtea-web.bin.location");
+            commands.add(pathToWebstartBinary);
+            // use -Jargument format to pass arguments to the JVM through the launcher
+            for (String arg : vmArgs) {
+                commands.add("-J" + arg);
+            }
+            commands.addAll(javawsArgs);
+
+            String[] command = commands.toArray(new String[] {});
+
+            Process p = Runtime.getRuntime().exec(command);
+            new StreamEater(p.getErrorStream()).start();
+            new StreamEater(p.getInputStream()).start();
+            p.getOutputStream().close();
+
+        } catch (NullPointerException ex) {
+            throw launchError(new LaunchException(null, null, R("LSFatal"), R("LCExternalLaunch"), R("LNetxJarMissing"), R("LNetxJarMissingInfo")));
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(null, ex, R("LSFatal"), R("LCExternalLaunch"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")));
+        }
+    }
+
+    /**
+     * Returns the JNLPFile for the URL, with error handling.
+     */
+    private JNLPFile fromUrl(URL location, boolean fromSource) throws LaunchException {
+        try {
+            JNLPFile file = null;
+
+            file = new JNLPFile(location, parserSettings.isStrict());
+
+            if (fromSource) {
+                // Launches the jnlp file where this file originated.
+                if (file.getSourceLocation() != null) {
+                    file = new JNLPFile(file.getSourceLocation(), parserSettings.isStrict());
+                }
+            }
+            return file;
+        } catch (Exception ex) {
+            if (ex instanceof LaunchException)
+                throw (LaunchException) ex; // already sent to handler when first thrown
+            else
+                // IO and Parse
+                throw launchError(new LaunchException(null, ex, R("LSFatal"), R("LCReadError"), R("LCantRead"), R("LCantReadInfo")));
+        }
+    }
+
+    /**
+     * Returns the JNLPFile for the URL, with error handling.
+     */
+    @Deprecated
+    private JNLPFile toFile(URL location) throws LaunchException {
+        try {
+            JNLPFile file = null;
+
+            try {
+                file = new JNLPFile(location, (Version) null, true, updatePolicy); // strict
+            } catch (ParseException ex) {
+                file = new JNLPFile(location, (Version) null, false, updatePolicy);
+
+                // only here if strict failed but lax did not fail
+                LaunchException lex =
+                        launchWarning(new LaunchException(file, ex, R("LSMinor"), R("LCFileFormat"), R("LNotToSpec"), R("LNotToSpecInfo")));
+
+                if (lex != null)
+                    throw lex;
+            }
+
+            return file;
+        } catch (Exception ex) {
+            if (ex instanceof LaunchException)
+                throw (LaunchException) ex; // already sent to handler when first thrown
+            else
+                // IO and Parse
+                throw launchError(new LaunchException(null, ex, R("LSFatal"), R("LCReadError"), R("LCantRead"), R("LCantReadInfo")));
+        }
+    }
+
+    /**
+     * Launches a JNLP application.  This method should be called
+     * from a thread in the application's thread group.
+     */
+    protected ApplicationInstance launchApplication(JNLPFile file) throws LaunchException {
+        if (!file.isApplication())
+            throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplication"), R("LNotApplicationInfo")));
+
+        try {
+
+            try {
+                ServiceUtil.checkExistingSingleInstance(file);
+            } catch (InstanceExistsException e) {
+                return null;
+            }
+
+            if (JNLPRuntime.getForksAllowed() && file.needsNewVM()) {
+                List<String> netxArguments = new LinkedList<String>();
+                netxArguments.add("-Xnofork");
+                netxArguments.addAll(JNLPRuntime.getInitialArguments());
+                launchExternal(file.getNewVMArgs(), netxArguments);
+                return null;
+            }
+
+            handler.launchInitialized(file);
+
+            ApplicationInstance app = createApplication(file);
+            app.initialize();
+
+            String mainName = file.getApplication().getMainClass();
+
+            // When the application-desc field is empty, we should take a
+            // look at the main jar for the main class.
+            if (mainName == null) {
+                JARDesc mainJarDesc = file.getResources().getMainJAR();
+                File f = CacheUtil.getCacheFile(mainJarDesc.getLocation(), null);
+                if (f != null) {
+                    JarFile mainJar = new JarFile(f);
+                    mainName = mainJar.getManifest().
+                                getMainAttributes().getValue("Main-Class");
+                }
+            }
+
+            if (mainName == null)
+                throw launchError(new LaunchException(file, null,
+                        R("LSFatal"), R("LCClient"), R("LCantDetermineMainClass"),
+                        R("LCantDetermineMainClassInfo")));
+
+            Class<?> mainClass = app.getClassLoader().loadClass(mainName);
+
+            Method main = mainClass.getMethod("main", new Class<?>[] { String[].class });
+            String args[] = file.getApplication().getArguments();
+
+            SwingUtilities.invokeAndWait(new Runnable() {
+                // dummy method to force Event Dispatch Thread creation
+                public void run() {
+                }
+            });
+
+            setContextClassLoaderForAllThreads(app.getThreadGroup(), app.getClassLoader());
+
+            handler.launchStarting(app);
+
+            main.setAccessible(true);
+            main.invoke(null, new Object[] { args });
+
+            return app;
+        } catch (LaunchException lex) {
+            throw launchError(lex);
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")));
+        }
+    }
+
+    /**
+     * Set the classloader as the context classloader for all threads in
+     * the given threadgroup. This is required to make some applications
+     * work. For example, an application that provides a custom Swing LnF
+     * may ask the swing thread to load resources from their JNLP, which
+     * would only work if the Swing thread knows about the JNLPClassLoader.
+     *
+     * @param tg The threadgroup for which the context classloader should be set
+     * @param classLoader the classloader to set as the context classloader
+     */
+    private void setContextClassLoaderForAllThreads(ThreadGroup tg, ClassLoader classLoader) {
+
+        /* be prepared for change in thread size */
+        int threadCountGuess = tg.activeCount();
+        Thread[] threads;
+        do {
+            threadCountGuess = threadCountGuess * 2;
+            threads = new Thread[threadCountGuess];
+            tg.enumerate(threads, true);
+        } while (threads[threadCountGuess - 1] != null);
+
+        for (Thread thread : threads) {
+            if (thread != null) {
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("Setting " + classLoader + " as the classloader for thread " + thread.getName());
+                }
+                thread.setContextClassLoader(classLoader);
+            }
+        }
+
+    }
+
+    /**
+     * Launches a JNLP applet. This method should be called from a
+     * thread in the application's thread group.<p>
+     *
+     * The enableCodeBase parameter adds the applet's codebase to
+     * the locations searched for resources and classes.  This can
+     * slow down the applet loading but allows browser-style applets
+     * that don't use JAR files exclusively to be run from a applet
+     * JNLP file.  If the applet JNLP file does not specify any
+     * resources then the code base will be enabled regardless of
+     * the specified value.<p>
+     *
+     * @param file the JNLP file
+     * @param enableCodeBase whether to add the codebase URL to the classloader
+     */
+    protected ApplicationInstance launchApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException {
+        if (!file.isApplet())
+            throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo")));
+
+        try {
+            AppletInstance applet = createApplet(file, enableCodeBase, cont);
+            applet.initialize();
+
+            applet.getAppletEnvironment().startApplet(); // this should be a direct call to applet instance
+            return applet;
+        } catch (LaunchException lex) {
+            throw launchError(lex);
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")));
+        }
+    }
+
+    /**
+     * Gets an ApplicationInstance, but does not launch the applet.
+     */
+    protected ApplicationInstance getApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException {
+        if (!file.isApplet())
+            throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo")));
+
+        try {
+            AppletInstance applet = createApplet(file, enableCodeBase, cont);
+            applet.initialize();
+            return applet;
+        } catch (LaunchException lex) {
+            throw launchError(lex);
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")));
+        }
+    }
+
+    /**
+     * Launches a JNLP installer.  This method should be called from
+     * a thread in the application's thread group.
+     */
+    protected ApplicationInstance launchInstaller(JNLPFile file) throws LaunchException {
+        throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCNotSupported"), R("LNoInstallers"), R("LNoInstallersInfo")));
+    }
+
+    /**
+     * Create an AppletInstance.
+     *
+     * @param enableCodeBase whether to add the code base URL to the classloader
+     */
+    protected AppletInstance createApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException {
+        try {
+            JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy);
+
+            if (enableCodeBase) {
+                loader.enableCodeBase();
+            } else if (file.getResources().getJARs().length == 0) {
+                throw new ClassNotFoundException("Can't do a codebase look up and there are no jars. Failing sooner rather than later");
+            }
+
+            AppThreadGroup group = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+
+            String appletName = file.getApplet().getMainClass();
+
+            //Classloader chokes if there's '/' in the path to the main class.
+            //Must replace with '.' instead.
+            appletName = appletName.replace('/', '.');
+            Class appletClass = loader.loadClass(appletName);
+            Applet applet = (Applet) appletClass.newInstance();
+
+            AppletInstance appletInstance;
+            if (cont == null)
+                appletInstance = new AppletInstance(file, group, loader, applet);
+            else
+                appletInstance = new AppletInstance(file, group, loader, applet, cont);
+
+            group.setApplication(appletInstance);
+            loader.setApplication(appletInstance);
+
+            setContextClassLoaderForAllThreads(appletInstance.getThreadGroup(), appletInstance.getClassLoader());
+
+            return appletInstance;
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo")));
+        }
+    }
+
+    /**
+     * Creates an Applet object from a JNLPFile. This is mainly to be used with
+     * gcjwebplugin.
+     * @param file the PluginBridge to be used.
+     * @param enableCodeBase whether to add the code base URL to the classloader.
+     */
+    protected Applet createAppletObject(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException {
+        try {
+            JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy);
+
+            if (enableCodeBase) {
+                loader.enableCodeBase();
+            } else if (file.getResources().getJARs().length == 0) {
+                throw new ClassNotFoundException("Can't do a codebase look up and there are no jars. Failing sooner rather than later");
+            }
+
+            String appletName = file.getApplet().getMainClass();
+
+            //Classloader chokes if there's '/' in the path to the main class.
+            //Must replace with '.' instead.
+            appletName = appletName.replace('/', '.');
+            Class appletClass = loader.loadClass(appletName);
+            Applet applet = (Applet) appletClass.newInstance();
+
+            return applet;
+        } catch (Exception ex) {
+            throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo")));
+        }
+    }
+
+    /**
+     * Creates an Application.
+     */
+    protected ApplicationInstance createApplication(JNLPFile file) throws LaunchException {
+        try {
+            JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy);
+            AppThreadGroup group = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+
+            ApplicationInstance app = new ApplicationInstance(file, group, loader);
+            group.setApplication(app);
+            loader.setApplication(app);
+
+            return app;
+        } catch (Exception ex) {
+            throw new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplication"), R("LInitApplicationInfo"));
+        }
+    }
+
+    /**
+     * Create a thread group for the JNLP file.
+     *
+     * Note: if the JNLPFile is an applet (ie it is a subclass of PluginBridge)
+     * then this method simply returns the existing ThreadGroup. The applet
+     * ThreadGroup has to be created at an earlier point in the applet code.
+     */
+    protected AppThreadGroup createThreadGroup(JNLPFile file) {
+        AppThreadGroup appThreadGroup = null;
+
+        if (file instanceof PluginBridge) {
+            appThreadGroup = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+        } else {
+            appThreadGroup = new AppThreadGroup(mainGroup, file.getTitle());
+        }
+
+        return appThreadGroup;
+    }
+
+    /**
+     * Send n launch error to the handler, if set, and also to the
+     * caller.
+     */
+    private LaunchException launchError(LaunchException ex) {
+        if (handler != null)
+            handler.launchError(ex);
+
+        return ex;
+    }
+
+    /**
+     * Send a launch error to the handler, if set, and to the
+     * caller only if the handler indicated that the launch should
+     * continue despite the warning.
+     *
+     * @return an exception to throw if the launch should be aborted, or null otherwise
+     */
+    private LaunchException launchWarning(LaunchException ex) {
+        if (handler != null)
+            if (!handler.launchWarning(ex))
+                // no need to destroy the app b/c it hasn't started
+                return ex; // chose to abort
+
+        return null; // chose to continue, or no handler
+    }
+
+    /**
+     * Do hacks on per-application level to allow different AppContexts to work
+     *
+     * @see JNLPRuntime#doMainAppContextHacks
+     */
+    private static void doPerApplicationAppContextHacks() {
+
+        /*
+         * With OpenJDK6 (but not with 7) a per-AppContext dtd is maintained.
+         * This dtd is created by the ParserDelgate. However, the code in
+         * HTMLEditorKit (used to render HTML in labels and textpanes) creates
+         * the ParserDelegate only if there are no existing ParserDelegates. The
+         * result is that all other AppContexts see a null dtd.
+         */
+        new ParserDelegator();
+    }
+
+    /**
+     * This runnable is used to call the appropriate launch method
+     * for the application, applet, or installer in its thread group.
+     */
+    private class TgThread extends Thread { // ThreadGroupThread
+        private JNLPFile file;
+        private ApplicationInstance application;
+        private LaunchException exception;
+        private Container cont;
+        private boolean isPlugin = false;
+
+        TgThread(JNLPFile file) {
+            this(file, null);
+        }
+
+        TgThread(JNLPFile file, Container cont) {
+            super(createThreadGroup(file), file.getTitle());
+
+            this.file = file;
+            this.cont = cont;
+        }
+
+        TgThread(JNLPFile file, Container cont, boolean isPlugin) {
+            super(createThreadGroup(file), file.getTitle());
+            this.file = file;
+            this.cont = cont;
+            this.isPlugin = isPlugin;
+        }
+
+        public void run() {
+            try {
+                // Do not create new AppContext if we're using NetX and icedteaplugin.
+                // The plugin needs an AppContext too, but it has to be created earlier.
+                if (context && !isPlugin)
+                    SunToolkit.createNewAppContext();
+
+                doPerApplicationAppContextHacks();
+
+                if (isPlugin) {
+                    // Do not display download indicators if we're using gcjwebplugin.
+                    JNLPRuntime.setDefaultDownloadIndicator(null);
+                    application = getApplet(file, ((PluginBridge)file).codeBaseLookup(), cont);
+                } else {
+                    if (file.isApplication())
+                        application = launchApplication(file);
+                    else if (file.isApplet())
+                        application = launchApplet(file, true, cont); // enable applet code base
+                    else if (file.isInstaller())
+                        application = launchInstaller(file);
+                    else
+                        throw launchError(new LaunchException(file, null,
+                                                R("LSFatal"), R("LCClient"), R("LNotLaunchable"),
+                                                R("LNotLaunchableInfo")));
+                }
+            } catch (LaunchException ex) {
+                ex.printStackTrace();
+                exception = ex;
+                // Exit if we can't launch the application.
+                if (exitOnFailure)
+                    System.exit(1);
+            }
+        }
+
+        public LaunchException getException() {
+            return exception;
+        }
+
+        public ApplicationInstance getApplication() {
+            return application;
+        }
+
+    };
+
+    /**
+     * This runnable is used by the <code>launchBackground</code>
+     * methods to launch a JNLP file from a separate thread.
+     */
+    private class BgRunner implements Runnable {
+        private JNLPFile file;
+        private URL location;
+
+        BgRunner(JNLPFile file, URL location) {
+            this.file = file;
+            this.location = location;
+        }
+
+        public void run() {
+            try {
+                if (file != null)
+                    launch(file);
+                if (location != null)
+                    launch(location);
+            } catch (LaunchException ex) {
+                // launch method communicates error conditions to the
+                // handler if it exists, otherwise we don't care because
+                // there's nothing that can be done about the exception.
+            }
+        }
+    };
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Log.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Log.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Log.java	(revision 403)
@@ -0,0 +1,42 @@
+package net.sourceforge.jnlp;
+
+import java.io.File;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * This file provides the information required to do logging.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+abstract class Log {
+
+    // Directory where the logs are stored.
+    protected static String icedteaLogDir;
+
+    protected static boolean enableLogging = false;
+    protected static boolean enableTracing = false;
+
+    // Prepare for logging.
+    static {
+        DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+
+        // Check whether logging and tracing is enabled.
+        enableLogging = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING));
+        enableTracing = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_TRACING));
+
+        // Get log directory, create it if it doesn't exist. If unable to create and doesn't exist, don't log.
+        icedteaLogDir = config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR);
+        if (icedteaLogDir != null) {
+            File f = new File(icedteaLogDir);
+            if (f.isDirectory() || f.mkdirs())
+                icedteaLogDir += File.separator;
+            else {
+                enableLogging = false;
+                enableTracing = false;
+            }
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/MenuDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/MenuDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/MenuDesc.java	(revision 403)
@@ -0,0 +1,38 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+public class MenuDesc {
+
+    /** the submenu for this menu entry */
+    private String subMenu;
+
+    /**
+     * Create a new menu descriptor
+     */
+    public MenuDesc(String subMenu) {
+        this.subMenu = subMenu;
+    }
+
+    /**
+     * Returns the submenu for this menu entry.
+     */
+    public String getSubMenu() {
+        return subMenu;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/NetxPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/NetxPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/NetxPanel.java	(revision 403)
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2007 Red Hat, Inc.
+ * This file is part of IcedTea, http://icedtea.classpath.org
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package net.sourceforge.jnlp;
+
+import net.sourceforge.jnlp.AppletLog;
+import net.sourceforge.jnlp.runtime.AppThreadGroup;
+import net.sourceforge.jnlp.runtime.AppletInstance;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+import java.net.URL;
+import java.util.Hashtable;
+
+import sun.applet.AppletViewerPanel;
+import sun.awt.SunToolkit;
+
+/**
+ * This panel calls into netx to run an applet, and pipes the display
+ * into a panel from gcjwebplugin.
+ *
+ * @author      Francis Kung <fkung@redhat.com>
+ */
+public class NetxPanel extends AppletViewerPanel {
+    private PluginBridge bridge = null;
+    private boolean exitOnFailure = true;
+    private AppletInstance appInst = null;
+    private boolean appletAlive;
+
+    public NetxPanel(URL documentURL, Hashtable<String, String> atts) {
+        super(documentURL, atts);
+    }
+
+    // overloaded constructor, called when initialized via plugin
+    public NetxPanel(URL documentURL, Hashtable<String, String> atts,
+                     boolean exitOnFailure) {
+        this(documentURL, atts);
+        this.exitOnFailure = exitOnFailure;
+        this.appletAlive = true;
+    }
+
+    @Override
+    public void run() {
+        /*
+         * create an AppContext for this thread associated with this particular
+         * plugin instance (which runs in a different thread group from the rest
+         * of the plugin).
+         */
+        SunToolkit.createNewAppContext();
+
+        super.run();
+    }
+
+    @Override
+    protected void showAppletException(Throwable t) {
+        /*
+         * Log any exceptions thrown while loading, initializing, starting,
+         * and stopping the applet. 
+         */
+        AppletLog.log(t);
+        super.showAppletException(t);
+    }
+    
+    //Overriding to use Netx classloader. You might need to relax visibility
+    //in sun.applet.AppletPanel for runLoader().
+    protected void runLoader() {
+
+        try {
+            bridge = new PluginBridge(baseURL,
+                                getDocumentBase(),
+                                getJarFiles(),
+                                getCode(),
+                                getWidth(),
+                                getHeight(),
+                                atts);
+
+            doInit = true;
+            dispatchAppletEvent(APPLET_LOADING, null);
+            status = APPLET_LOAD;
+
+            Launcher l = new Launcher(exitOnFailure);
+
+            try {
+                appInst = (AppletInstance) l.launch(bridge, this);
+            } catch (LaunchException e) {
+                // Assume user has indicated he does not trust the
+                // applet.
+                if (exitOnFailure)
+                    System.exit(1);
+            }
+            applet = appInst.getApplet();
+
+            //On the other hand, if you create an applet this way, it'll work
+            //fine. Note that you might to open visibility in sun.applet.AppletPanel
+            //for this to work (the loader field, and getClassLoader).
+            //loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());
+            //applet = createApplet(loader);
+
+            // This shows that when using NetX's JNLPClassLoader, keyboard input
+            // won't make it to the applet, whereas using sun.applet.AppletClassLoader
+            // works just fine.
+
+            dispatchAppletEvent(APPLET_LOADING_COMPLETED, null);
+
+            if (applet != null) {
+                // Stick it in the frame
+                applet.setStub(this);
+                applet.setVisible(false);
+                add("Center", applet);
+                showAppletStatus("loaded");
+                validate();
+            }
+        } catch (Exception e) {
+            this.appletAlive = false;
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Creates a new Thread (in a new applet-specific ThreadGroup) for running
+     * the applet
+     */
+    // Reminder: Relax visibility in sun.applet.AppletPanel
+    protected synchronized void createAppletThread() {
+        // initialize JNLPRuntime in the main threadgroup
+        synchronized (JNLPRuntime.initMutex) {
+            //The custom NetX Policy and SecurityManager are set here.
+            if (!JNLPRuntime.isInitialized()) {
+                if (JNLPRuntime.isDebug())
+                    System.out.println("initializing JNLPRuntime...");
+
+                JNLPRuntime.initialize(false);
+            } else {
+                if (JNLPRuntime.isDebug())
+                    System.out.println("JNLPRuntime already initialized");
+            }
+        }
+
+        // when this was being done (incorrectly) in Launcher, the call was
+        // new AppThreadGroup(mainGroup, file.getTitle());
+        ThreadGroup tg = new AppThreadGroup(Launcher.mainGroup,
+                this.documentURL.toString());
+        handler = new Thread(tg, this);
+        handler.start();
+    }
+
+    public void updateSizeInAtts(int height, int width) {
+        this.atts.put("height", Integer.toString(height));
+        this.atts.put("width", Integer.toString(width));
+    }
+
+    public ClassLoader getAppletClassLoader() {
+        return appInst.getClassLoader();
+    }
+
+    public boolean isAlive() {
+        return handler != null && handler.isAlive() && this.appletAlive;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Node.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Node.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Node.java	(revision 403)
@@ -0,0 +1,146 @@
+package net.sourceforge.jnlp;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import net.sourceforge.nanoxml.XMLElement;
+
+// this class makes assumptions on how parser calls methods (such
+// as getFirstChild->getNextChild only called by a single loop at
+// a time, so no need for an iterator).
+
+/**
+ * This class converts the NanoXML's XMLElement nodes into the
+ * regular XML Node interface (for the methods used by Parser).
+ */
+/* NANO */
+class Node {
+    private XMLElement xml;
+    private Node next;
+    private Node children[];
+
+    Node(XMLElement xml) {
+        this.xml = xml;
+    }
+
+    Node getFirstChild() {
+        if (children == null)
+            getChildNodes();
+
+        if (children.length == 0)
+            return null;
+        else
+            return children[0];
+    }
+
+    Node getNextSibling() {
+        return next;
+    }
+
+    void normalize() {
+    }
+
+    String getNodeValue() {
+        return xml.getContent();
+    }
+
+    Node[] getChildNodes() {
+        if (children == null) {
+            List<Node> list = new ArrayList<Node>();
+
+            for (Enumeration e = xml.enumerateChildren(); e.hasMoreElements();)
+                list.add(new Node((XMLElement) e.nextElement()));
+
+            children = list.toArray(new Node[list.size()]);
+
+            for (int i = 0; i < children.length - 1; i++)
+                children[i].next = children[i + 1];
+        }
+
+        return children;
+    }
+
+    String getAttribute(String name) {
+        return (String) xml.getAttribute(name);
+    }
+
+    String getNodeName() {
+        if (xml.getName() == null)
+            return "";
+        else
+            return xml.getName();
+    }
+
+    public String toString() {
+        return getNodeName();
+    }
+}
+
+/**
+ * This class converts the TinyXML's ParsedXML nodes into the
+ * regular XML Node interface (for the methods used by Parser).
+ */
+/* TINY
+class Node {
+    private ParsedXML tinyNode;
+    private Node next;
+    private Node children[];
+
+    Node(ParsedXML tinyNode) {
+        this.tinyNode = tinyNode;
+    }
+
+    Node getFirstChild() {
+        if (children == null)
+            getChildNodes();
+
+        if (children.length == 0)
+            return null;
+        else
+            return children[0];
+    }
+
+    Node getNextSibling() {
+        return next;
+    }
+
+    void normalize() {
+    }
+
+    String getNodeValue() {
+        return tinyNode.getContent();
+    }
+
+    Node[] getChildNodes() {
+        if (children == null) {
+            List list = new ArrayList();
+
+            for (Enumeration e = tinyNode.elements(); e.hasMoreElements();) {
+                list.add( new Node((ParsedXML)e.nextElement()) );
+            }
+            children = (Node[]) list.toArray( new Node[list.size()] );
+
+            for (int i=0; i < children.length-1; i++)
+                children[i].next = children[i+1];
+        }
+
+        return children;
+    }
+
+    String getAttribute(String name) {
+        return tinyNode.getAttribute(name);
+    }
+
+    String getNodeName() {
+        if (tinyNode.getName() == null)
+            return "";
+        else
+            return tinyNode.getName();
+    }
+
+    public String toString() {
+        return getNodeName();
+    }
+}
+*/
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PackageDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PackageDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PackageDesc.java	(revision 403)
@@ -0,0 +1,96 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+/**
+ * The package element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class PackageDesc {
+
+    /** the package name */
+    private String name;
+
+    /** the part required by the package */
+    private String part;
+
+    /** whether the package includes subpackages */
+    private boolean recursive;
+
+    /**
+     * Create a package descriptor.
+     *
+     * @param name the package name
+     * @param part the part required by the package
+     * @param recursive whether the package includes subpackages
+     */
+    public PackageDesc(String name, String part, boolean recursive) {
+        this.name = name;
+        this.part = part;
+        this.recursive = recursive;
+    }
+
+    /**
+     * Returns whether the specified class is part of this package.
+     *
+     * @param className the fully qualified class name
+     */
+    public boolean matches(String className) {
+        // form 1: exact class
+        if (name.equals(className))
+            return true;
+
+        // form 2: package.*
+        if (name.endsWith(".*")) {
+            String pkName = name.substring(0, name.length() - 1);
+
+            if (className.startsWith(pkName)) {
+                String postfix = className.substring(pkName.length() + 1);
+
+                if (recursive || -1 == postfix.indexOf("."))
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the package name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the part name.
+     */
+    public String getPart() {
+        return part;
+    }
+
+    /**
+     * Returns whether subpackages should be matched by this
+     * package.
+     */
+    public boolean isRecursive() {
+        return recursive;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParseException.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParseException.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParseException.java	(revision 403)
@@ -0,0 +1,88 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.io.*;
+
+/**
+ * Thrown to indicate that an error has occurred while parsing a
+ * JNLP file.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+public class ParseException extends Exception {
+
+    // todo: add meaningful information, such as the invalid
+    // element, parse position, etc.
+
+    /** the original exception */
+    private Throwable cause = null;
+
+    /**
+     * Create a parse exception with the specified message.
+     */
+    public ParseException(String message) {
+        super(message);
+    }
+
+    /**
+     * Create a parse exception with the specified message and
+     * cause.
+     */
+    public ParseException(String message, Throwable cause) {
+        super(message);
+
+        // replace with setCause when no longer 1.3 compatible
+        this.cause = cause;
+    }
+
+    /**
+     * Return the cause of the launch exception or null if there
+     * is no cause exception.
+     */
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Print the stack trace and the cause exception (1.3
+     * compatible)
+     */
+    public void printStackTrace(PrintStream stream) {
+        super.printStackTrace(stream);
+
+        if (cause != null) {
+            stream.println("Caused by: ");
+            cause.printStackTrace(stream);
+        }
+    }
+
+    /**
+     * Print the stack trace and the cause exception (1.3
+     * compatible)
+     */
+    public void printStackTrace(PrintWriter stream) {
+        super.printStackTrace(stream);
+
+        if (cause != null) {
+            stream.println("Caused by: ");
+            cause.printStackTrace(stream);
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Parser.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Parser.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Parser.java	(revision 403)
@@ -0,0 +1,1319 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+//import javax.xml.parsers.*; // commented to use right Node
+//import org.w3c.dom.*;       // class for using Tiny XML | NanoXML
+//import org.xml.sax.*;
+//import gd.xml.tiny.*;
+import net.sourceforge.jnlp.UpdateDesc.Check;
+import net.sourceforge.jnlp.UpdateDesc.Policy;
+import net.sourceforge.nanoxml.*;
+
+/**
+ * Contains methods to parse an XML document into a JNLPFile.
+ * Implements JNLP specification version 1.0.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.13 $
+ */
+class Parser {
+
+    // defines netx.jnlp.Node class if using Tiny XML or Nano XML
+
+    // Currently uses the Nano XML parse.  Search for "SAX" or
+    // "TINY" or "NANO" and uncomment those blocks and comment the
+    // active ones (if any) to switch XML parsers.  Also
+    // (un)comment appropriate Node class at end of this file and
+    // do a clean build.
+
+    /**
+     * Ensure consistent error handling.
+     */
+    /* SAX
+    static ErrorHandler errorHandler = new ErrorHandler() {
+        public void error(SAXParseException exception) throws SAXParseException {
+            //throw exception;
+        }
+        public void fatalError(SAXParseException exception) throws SAXParseException {
+            //throw exception;
+        }
+        public void warning(SAXParseException exception) {
+            System.err.println("XML parse warning:");
+            exception.printStackTrace();
+        }
+    };
+    */
+
+    // fix: some descriptors need to use the jnlp file at a later
+    // date and having file ref lets us pass it to their
+    // constructors
+    //
+    /** the file reference */
+    private JNLPFile file; // do not use (uninitialized)
+
+    /** the root node */
+    private Node root;
+
+    /** the specification version */
+    private Version spec;
+
+    /** the base URL that all hrefs are relative to */
+    private URL base;
+
+    /** the codebase URL */
+    private URL codebase;
+
+    /** the file URL */
+    private URL fileLocation;
+
+    /** whether to throw errors on non-fatal errors. */
+    private boolean strict; // if strict==true parses a file with no error then strict==false should also
+
+    /** whether to allow extensions to the JNLP specification */
+    private boolean allowExtensions; // true if extensions to JNLP spec are ok
+
+    /**
+     * Create a parser for the JNLP file.  If the location
+     * parameters is not null it is used as the default codebase
+     * (does not override value of jnlp element's href
+     * attribute).<p>
+     *
+     * The root node may be normalized as a side effect of this
+     * constructor.
+     *
+     * @param file the (uninitialized) file reference
+     * @param base if codebase is not specified, a default base for relative URLs
+     * @param root the root node
+     * @param strict whether to enforce strict compliance with the JNLP spec
+     * @param allowExtensions whether to allow extensions to the JNLP spec
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions) throws ParseException {
+        this.file = file;
+        this.root = root;
+        this.strict = strict;
+        this.allowExtensions = allowExtensions;
+
+        // ensure it's a JNLP node
+        if (root == null || !root.getNodeName().equals("jnlp"))
+            throw new ParseException(R("PInvalidRoot"));
+
+        // JNLP tag information
+        this.spec = getVersion(root, "spec", "1.0+");
+        this.codebase = addSlash(getURL(root, "codebase", base));
+        this.base = (codebase != null) ? codebase : base; // if codebase not specified use default codebase
+        fileLocation = getURL(root, "href", this.base);
+
+        // normalize the text nodes
+        root.normalize();
+    }
+
+    /**
+     * Returns the file version.
+     */
+    public Version getFileVersion() {
+        return getVersion(root, "version", null);
+    }
+
+    /**
+     * Returns the file location.
+     */
+    public URL getFileLocation() {
+        return fileLocation;
+    }
+
+    /**
+     * Returns the codebase.
+     */
+    public URL getCodeBase() {
+        return codebase;
+    }
+
+    /**
+     * Returns the specification version.
+     */
+    public Version getSpecVersion() {
+        return spec;
+    }
+
+    public UpdateDesc getUpdate(Node parent) throws ParseException {
+        UpdateDesc updateDesc = null;
+        Node child = parent.getFirstChild();
+        while (child != null) {
+            if (child.getNodeName().equals("update")) {
+                if (strict && updateDesc != null) {
+                    throw new ParseException(R("PTwoUpdates"));
+                }
+
+                Node node = child;
+
+                Check check;
+                String checkValue = getAttribute(node, "check", "timeout");
+                if (checkValue.equals("always")) {
+                    check = Check.ALWAYS;
+                } else if (checkValue.equals("timeout")) {
+                    check = Check.TIMEOUT;
+                } else if (checkValue.equals("background")) {
+                    check = Check.BACKGROUND;
+                } else {
+                    check = Check.TIMEOUT;
+                }
+
+                String policyString = getAttribute(node, "policy", "always");
+                Policy policy;
+                if (policyString.equals("always")) {
+                    policy = Policy.ALWAYS;
+                } else if (policyString.equals("prompt-update")) {
+                    policy = Policy.PROMPT_UPDATE;
+                } else if (policyString.equals("prompt-run")) {
+                    policy = Policy.PROMPT_RUN;
+                } else {
+                    policy = Policy.ALWAYS;
+                }
+
+                updateDesc = new UpdateDesc(check, policy);
+            }
+
+            child = child.getNextSibling();
+        }
+
+        if (updateDesc == null) {
+            updateDesc = new UpdateDesc(Check.TIMEOUT, Policy.ALWAYS);
+        }
+        return updateDesc;
+    }
+
+    //
+    // This section loads the resources elements
+    //
+
+    /**
+     * Returns all of the ResourcesDesc elements under the specified
+     * node (jnlp or j2se).
+     *
+     * @param parent the parent node (either jnlp or j2se)
+     * @param j2se true if the resources are located under a j2se or java node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public List<ResourcesDesc> getResources(Node parent, boolean j2se)
+            throws ParseException {
+        List<ResourcesDesc> result = new ArrayList<ResourcesDesc>();
+        Node resources[] = getChildNodes(parent, "resources");
+
+        // ensure that there are at least one information section present
+        if (resources.length == 0 && !j2se)
+            throw new ParseException(R("PNoResources"));
+
+        // create objects from the resources sections
+        for (int i = 0; i < resources.length; i++)
+            result.add(getResourcesDesc(resources[i], j2se));
+
+        return result;
+    }
+
+    /**
+     * Returns the ResourcesDesc element at the specified node.
+     *
+     * @param node the resources node
+     * @param j2se true if the resources are located under a j2se or java node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public ResourcesDesc getResourcesDesc(Node node, boolean j2se) throws ParseException {
+        boolean mainFlag = false; // if found a main tag
+
+        // create resources
+        ResourcesDesc resources =
+                new ResourcesDesc(file,
+                              getLocales(node),
+                              splitString(getAttribute(node, "os", null)),
+                              splitString(getAttribute(node, "arch", null)));
+
+        // step through the elements
+        Node child = node.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            // check for nativelib but no trusted environment
+            if ("nativelib".equals(name))
+                if (!isTrustedEnvironment())
+                    throw new ParseException(R("PUntrustedNative"));
+
+            if ("j2se".equals(name) || "java".equals(name)) {
+                if (getChildNode(root, "component-desc") != null)
+                    if (strict)
+                        throw new ParseException(R("PExtensionHasJ2SE"));
+                if (!j2se)
+                    resources.addResource(getJRE(child));
+                else
+                    throw new ParseException(R("PInnerJ2SE"));
+            }
+
+            if ("jar".equals(name) || "nativelib".equals(name)) {
+                JARDesc jar = getJAR(child);
+
+                // check for duplicate main entries
+                if (jar.isMain()) {
+                    if (mainFlag == true)
+                        if (strict)
+                            throw new ParseException(R("PTwoMains"));
+                    mainFlag = true;
+                }
+
+                resources.addResource(jar);
+            }
+
+            if ("extension".equals(name))
+                resources.addResource(getExtension(child));
+
+            if ("property".equals(name))
+                resources.addResource(getProperty(child));
+
+            if ("package".equals(name))
+                resources.addResource(getPackage(child));
+
+            child = child.getNextSibling();
+        }
+
+        return resources;
+    }
+
+    /**
+     * Returns the JRE element at the specified node.
+     *
+     * @param node the j2se/java node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public JREDesc getJRE(Node node) throws ParseException {
+        Version version = getVersion(node, "version", null);
+        URL location = getURL(node, "href", base);
+        String vmArgs = getAttribute(node, "java-vm-args", null);
+        try {
+            checkVMArgs(vmArgs);
+        } catch (IllegalArgumentException argumentException) {
+            vmArgs = null;
+        }
+        String initialHeap = getAttribute(node, "initial-heap-size", null);
+        String maxHeap = getAttribute(node, "max-heap-size", null);
+        List resources = getResources(node, true);
+
+        // require version attribute
+        getRequiredAttribute(node, "version", null);
+
+        return new JREDesc(version, location, vmArgs, initialHeap, maxHeap, resources);
+    }
+
+    /**
+     * Returns the JAR element at the specified node.
+     *
+     * @param node the jar or nativelib node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public JARDesc getJAR(Node node) throws ParseException {
+        boolean nativeJar = "nativelib".equals(node.getNodeName());
+        URL location = getRequiredURL(node, "href", base);
+        Version version = getVersion(node, "version", null);
+        String part = getAttribute(node, "part", null);
+        boolean main = "true".equals(getAttribute(node, "main", "false"));
+        boolean lazy = "lazy".equals(getAttribute(node, "download", "eager"));
+
+        if (nativeJar && main)
+            if (strict)
+                throw new ParseException(R("PNativeHasMain"));
+
+        return new JARDesc(location, version, part, lazy, main, nativeJar, true);
+
+    }
+
+    /**
+     * Returns the Extension element at the specified node.
+     *
+     * @param node the extension node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public ExtensionDesc getExtension(Node node) throws ParseException {
+        String name = getAttribute(node, "name", null);
+        Version version = getVersion(node, "version", null);
+        URL location = getRequiredURL(node, "href", base);
+
+        ExtensionDesc ext = new ExtensionDesc(name, version, location);
+
+        Node dload[] = getChildNodes(node, "ext-download");
+        for (int i = 0; i < dload.length; i++) {
+            boolean lazy = "lazy".equals(getAttribute(dload[i], "download", "eager"));
+
+            ext.addPart(getRequiredAttribute(dload[i], "ext-part", null),
+                        getAttribute(dload[i], "part", null),
+                        lazy);
+        }
+
+        return ext;
+    }
+
+    /**
+     * Returns the Property element at the specified node.
+     *
+     * @param node the property node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public PropertyDesc getProperty(Node node) throws ParseException {
+        String name = getRequiredAttribute(node, "name", null);
+        String value = getRequiredAttribute(node, "value", "");
+
+        return new PropertyDesc(name, value);
+    }
+
+    /**
+     * Returns the Package element at the specified node.
+     *
+     * @param node the package node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public PackageDesc getPackage(Node node) throws ParseException {
+        String name = getRequiredAttribute(node, "name", null);
+        String part = getRequiredAttribute(node, "part", "");
+        boolean recursive = getAttribute(node, "recursive", "false").equals("true");
+
+        return new PackageDesc(name, part, recursive);
+    }
+
+    //
+    // This section loads the information elements
+    //
+
+    /**
+     * Returns all of the information elements under the specified
+     * node.
+     *
+     * @param parent the parent node (jnlp)
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public List<InformationDesc> getInfo(Node parent)
+            throws ParseException {
+        List<InformationDesc> result = new ArrayList<InformationDesc>();
+        Node info[] = getChildNodes(parent, "information");
+
+        // ensure that there are at least one information section present
+        if (info.length == 0)
+            throw new ParseException(R("PNoInfoElement"));
+
+        // create objects from the info sections
+        for (int i = 0; i < info.length; i++)
+            result.add(getInformationDesc(info[i]));
+
+        return result;
+    }
+
+    /**
+     * Returns the information element at the specified node.
+     *
+     * @param node the information node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public InformationDesc getInformationDesc(Node node) throws ParseException {
+        List<String> descriptionsUsed = new ArrayList<String>();
+
+        // locale
+        Locale locales[] = getLocales(node);
+
+        // create information
+        InformationDesc info = new InformationDesc(file, locales);
+
+        // step through the elements
+        Node child = node.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            if ("title".equals(name))
+                addInfo(info, child, null, getSpanText(child, false));
+            if ("vendor".equals(name))
+                addInfo(info, child, null, getSpanText(child, false));
+            if ("description".equals(name)) {
+                String kind = getAttribute(child, "kind", "default");
+                if (descriptionsUsed.contains(kind))
+                    if (strict)
+                        throw new ParseException(R("PTwoDescriptions", kind));
+
+                descriptionsUsed.add(kind);
+                addInfo(info, child, kind, getSpanText(child, false));
+            }
+            if ("homepage".equals(name))
+                addInfo(info, child, null, getRequiredURL(child, "href", base));
+            if ("icon".equals(name))
+                addInfo(info, child, getAttribute(child, "kind", "default"), getIcon(child));
+            if ("offline-allowed".equals(name))
+                addInfo(info, child, null, Boolean.TRUE);
+            if ("sharing-allowed".equals(name)) {
+                if (strict && !allowExtensions)
+                    throw new ParseException(R("PSharing"));
+                addInfo(info, child, null, Boolean.TRUE);
+            }
+            if ("association".equals(name)) {
+                addInfo(info, child, null, getAssociation(child));
+            }
+            if ("shortcut".equals(name)) {
+                addInfo(info, child, null, getShortcut(child));
+            }
+            if ("related-content".equals(name)) {
+                addInfo(info, child, null, getRelatedContent(child));
+            }
+
+            child = child.getNextSibling();
+        }
+
+        return info;
+    }
+
+    /**
+     * Adds a key,value pair to the information object.
+     *
+     * @param info the information object
+     * @param node node name to be used as the key
+     * @param mod key name appended with "-"+mod if not null
+     * @param value the info object to add (icon or string)
+     */
+    protected void addInfo(InformationDesc info, Node node, String mod, Object value) {
+        String modStr = (mod == null) ? "" : "-" + mod;
+
+        if (node == null)
+            return;
+
+        info.addItem(node.getNodeName() + modStr, value);
+    }
+
+    /**
+     * Returns the icon element at the specified node.
+     *
+     * @param node the icon node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public IconDesc getIcon(Node node) throws ParseException {
+        int width = Integer.parseInt(getAttribute(node, "width", "-1"));
+        int height = Integer.parseInt(getAttribute(node, "height", "-1"));
+        int size = Integer.parseInt(getAttribute(node, "size", "-1"));
+        int depth = Integer.parseInt(getAttribute(node, "depth", "-1"));
+        URL location = getRequiredURL(node, "href", base);
+        Object kind = getAttribute(node, "kind", "default");
+
+        return new IconDesc(location, kind, width, height, depth, size);
+    }
+
+    //
+    // This section loads the security descriptor element
+    //
+
+    /**
+     * Returns the security descriptor element.  If no security
+     * element was specified in the JNLP file then a SecurityDesc
+     * with applet permissions is returned.
+     *
+     * @param parent the parent node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public SecurityDesc getSecurity(Node parent) throws ParseException {
+        Node nodes[] = getChildNodes(parent, "security");
+
+        // test for too many security elements
+        if (nodes.length > 1)
+            if (strict)
+                throw new ParseException(R("PTwoSecurity"));
+
+        Object type = SecurityDesc.SANDBOX_PERMISSIONS;
+
+        if (nodes.length == 0)
+            type = SecurityDesc.SANDBOX_PERMISSIONS;
+        else if (null != getChildNode(nodes[0], "all-permissions"))
+            type = SecurityDesc.ALL_PERMISSIONS;
+        else if (null != getChildNode(nodes[0], "j2ee-application-client-permissions"))
+            type = SecurityDesc.J2EE_PERMISSIONS;
+        else if (strict)
+            throw new ParseException(R("PEmptySecurity"));
+
+        if (base != null)
+            return new SecurityDesc(file, type, base.getHost());
+        else
+            return new SecurityDesc(file, type, null);
+    }
+
+    /**
+     * Returns whether the JNLP file requests a trusted execution
+     * environment.
+     */
+    protected boolean isTrustedEnvironment() {
+        Node security = getChildNode(root, "security");
+
+        if (security != null)
+            if (getChildNode(security, "all-permissions") != null
+                    || getChildNode(security, "j2ee-application-client-permissions") != null)
+                return true;
+
+        return false;
+    }
+
+    //
+    // This section loads the launch descriptor element
+    //
+
+    /**
+     * Returns the launch descriptor element, either AppletDesc,
+     * ApplicationDesc, or InstallerDesc.
+     *
+     * @param parent the parent node
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public Object getLauncher(Node parent) throws ParseException {
+        // check for other than one application type
+        if (1 < getChildNodes(parent, "applet-desc").length
+                + getChildNodes(parent, "application-desc").length
+                + getChildNodes(parent, "installer-desc").length)
+            throw new ParseException(R("PTwoDescriptors"));
+
+        Node child = parent.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            if ("applet-desc".equals(name))
+                return getApplet(child);
+            if ("application-desc".equals(name))
+                return getApplication(child);
+            if ("installer-desc".equals(name))
+                return getInstaller(child);
+
+            child = child.getNextSibling();
+        }
+
+        // not reached
+        return null;
+    }
+
+    /**
+     * Returns the applet descriptor.
+     *
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public AppletDesc getApplet(Node node) throws ParseException {
+        String name = getRequiredAttribute(node, "name", R("PUnknownApplet"));
+        String main = getRequiredAttribute(node, "main-class", null);
+        URL docbase = getURL(node, "documentbase", base);
+        Map<String, String> paramMap = new HashMap<String, String>();
+        int width = 0;
+        int height = 0;
+
+        try {
+            width = Integer.parseInt(getRequiredAttribute(node, "width", "100"));
+            height = Integer.parseInt(getRequiredAttribute(node, "height", "100"));
+        } catch (NumberFormatException nfe) {
+            if (width <= 0)
+                throw new ParseException(R("PBadWidth"));
+            throw new ParseException(R("PBadWidth"));
+        }
+
+        // read params
+        Node params[] = getChildNodes(node, "param");
+        for (int i = 0; i < params.length; i++) {
+            paramMap.put(getRequiredAttribute(params[i], "name", null),
+                         getRequiredAttribute(params[i], "value", ""));
+        }
+
+        return new AppletDesc(name, main, docbase, width, height, paramMap);
+    }
+
+    /**
+     * Returns the application descriptor.
+     *
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public ApplicationDesc getApplication(Node node) throws ParseException {
+        String main = getAttribute(node, "main-class", null);
+        List<String> argsList = new ArrayList<String>();
+
+        // if (main == null)
+        //   only ok if can be found in main jar file (can't check here but make a note)
+
+        // read parameters
+        Node args[] = getChildNodes(node, "argument");
+        for (int i = 0; i < args.length; i++) {
+            //argsList.add( args[i].getNodeValue() );
+
+            //This approach was not finding the argument text
+            argsList.add(getSpanText(args[i]));
+        }
+
+        String argStrings[] = argsList.toArray(new String[argsList.size()]);
+
+        return new ApplicationDesc(main, argStrings);
+    }
+
+    /**
+     * Returns the component descriptor.
+     */
+    public ComponentDesc getComponent(Node parent) throws ParseException {
+
+        if (1 < getChildNodes(parent, "component-desc").length) {
+            throw new ParseException(R("PTwoDescriptors"));
+        }
+
+        Node child = parent.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            if ("component-desc".equals(name))
+                return new ComponentDesc();
+
+            child = child.getNextSibling();
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the installer descriptor.
+     */
+    public InstallerDesc getInstaller(Node node) {
+        String main = getAttribute(node, "main-class", null);
+
+        return new InstallerDesc(main);
+    }
+
+    /**
+     * Returns the association descriptor.
+     */
+    public AssociationDesc getAssociation(Node node) throws ParseException {
+        String[] extensions = getRequiredAttribute(node, "extensions", null).split(" ");
+        String mimeType = getRequiredAttribute(node, "mime-type", null);
+
+        return new AssociationDesc(mimeType, extensions);
+    }
+
+    /**
+     * Returns the shortcut descriptor.
+     */
+    public ShortcutDesc getShortcut(Node node) throws ParseException {
+
+        String online = getAttribute(node, "online", "true");
+        boolean shortcutIsOnline = Boolean.valueOf(online);
+
+        boolean showOnDesktop = false;
+        MenuDesc menu = null;
+
+        // step through the elements
+        Node child = node.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            if ("desktop".equals(name)) {
+                if (showOnDesktop && strict) {
+                    throw new ParseException(R("PTwoDesktops"));
+                }
+                showOnDesktop = true;
+            } else if ("menu".equals(name)) {
+                if (menu != null && strict) {
+                    throw new ParseException(R("PTwoMenus"));
+                }
+                menu = getMenu(child);
+            }
+
+            child = child.getNextSibling();
+        }
+
+        ShortcutDesc shortcut = new ShortcutDesc(shortcutIsOnline, showOnDesktop);
+        if (menu != null) {
+            shortcut.addMenu(menu);
+        }
+        return shortcut;
+    }
+
+    /**
+     * Returns the menu descriptor.
+     */
+    public MenuDesc getMenu(Node node) {
+        String subMenu = getAttribute(node, "submenu", null);
+
+        return new MenuDesc(subMenu);
+    }
+
+    /**
+     * Returns the related-content descriptor.
+     */
+    public RelatedContentDesc getRelatedContent(Node node) throws ParseException {
+
+        getRequiredAttribute(node, "href", null);
+        URL location = getURL(node, "href", base);
+
+        String title = null;
+        String description = null;
+        IconDesc icon = null;
+
+        // step through the elements
+        Node child = node.getFirstChild();
+        while (child != null) {
+            String name = child.getNodeName();
+
+            if ("title".equals(name)) {
+                if (title != null && strict) {
+                    throw new ParseException(R("PTwoTitles"));
+                }
+                title = getSpanText(child, false);
+            } else if ("description".equals(name)) {
+                if (description != null && strict) {
+                    throw new ParseException(R("PTwoDescriptions"));
+                }
+                description = getSpanText(child, false);
+            } else if ("icon".equals(name)) {
+                if (icon != null && strict) {
+                    throw new ParseException(R("PTwoIcons"));
+                }
+                icon = getIcon(child);
+            }
+
+            child = child.getNextSibling();
+        }
+
+        RelatedContentDesc relatedContent = new RelatedContentDesc(location);
+        relatedContent.setDescription(description);
+        relatedContent.setIconDesc(icon);
+        relatedContent.setTitle(title);
+
+        return relatedContent;
+
+    }
+
+    // other methods
+
+    /**
+     * Returns an array of substrings seperated by spaces (spaces
+     * escaped with backslash do not separate strings).  This method
+     * splits strings as per the spec except that it does replace
+     * escaped other characters with their own value.
+     */
+    public String[] splitString(String source) {
+        if (source == null)
+            return new String[0];
+
+        List<String> result = new ArrayList<String>();
+        StringTokenizer st = new StringTokenizer(source, " ");
+        StringBuilder part = new StringBuilder();
+        while (st.hasMoreTokens()) {
+            part.setLength(0);
+
+            // tack together tokens joined by backslash
+            while (true) {
+                part.append(st.nextToken());
+
+                if (st.hasMoreTokens() && part.charAt(part.length() - 1) == '\\')
+                    part.setCharAt(part.length() - 1, ' '); // join with the space
+                else
+                    break; // bizarre while format gets \ at end of string right (no extra space added at end)
+            }
+
+            // delete \ quote chars
+            for (int i = part.length(); i-- > 0;)
+                // sweet syntax for reverse loop
+                if (part.charAt(i) == '\\')
+                    part.deleteCharAt(i--); // and skip previous char so \\ becomes \
+
+            result.add(part.toString());
+        }
+
+        return result.toArray(new String[result.size()]);
+    }
+
+    /**
+     * Returns the Locale object(s) from a node's locale attribute.
+     *
+     * @param node the node with a locale attribute
+     */
+    public Locale[] getLocales(Node node) {
+        List<Locale> locales = new ArrayList<Locale>();
+        String localeParts[] =
+                splitString(getAttribute(node, "locale", ""));
+
+        for (int i = 0; i < localeParts.length; i++) {
+            Locale l = getLocale(localeParts[i]);
+            if (l != null)
+                locales.add(l);
+        }
+
+        return locales.toArray(new Locale[locales.size()]);
+    }
+
+    /**
+     * Returns a Locale from a single locale.
+     *
+     * @param locale the locale string
+     */
+    public Locale getLocale(String localeStr) {
+        if (localeStr.length() < 2)
+            return null;
+
+        String language = localeStr.substring(0, 2);
+        String country = (localeStr.length() < 5) ? "" : localeStr.substring(3, 5);
+        String variant = (localeStr.length() < 7) ? "" : localeStr.substring(6, 8);
+
+        // null is not allowed n locale but "" is
+        return new Locale(language, country, variant);
+    }
+
+    // XML junk
+    /**
+     * Returns the implied text under a node, for example "text" in
+     * "<description>text</description>".
+     *
+     * @param node the node with text under it
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public String getSpanText(Node node) throws ParseException {
+        return getSpanText(node, true);
+    }
+
+    /**
+     * Returns the implied text under a node, for example "text" in
+     * "<description>text</description>". If preserveSpacing is false,
+     * sequences of whitespace characters are turned into a single
+     * space character.
+     *
+     * @param node the node with text under it
+     * @param preserveSpacing if true, preserve whitespace
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public String getSpanText(Node node, boolean preserveSpacing)
+            throws ParseException {
+        if (node == null)
+            return null;
+
+        // NANO
+        String val = node.getNodeValue();
+        if (preserveSpacing) {
+            return val;
+        } else {
+            if (val == null) {
+                return null;
+            } else {
+                return val.replaceAll("\\s+", " ");
+            }
+        }
+
+        /* TINY
+        Node child = node.getFirstChild();
+
+        if (child == null) {
+            if (strict)
+                // not sure if this is an error or whether "" is proper
+                throw new ParseException("No text specified (node="+node.getNodeName()+")");
+            else
+                return "";
+        }
+
+        return child.getNodeValue();
+        */
+    }
+
+    /**
+     * Returns the first child node with the specified name.
+     */
+    public static Node getChildNode(Node node, String name) {
+        Node[] result = getChildNodes(node, name);
+        if (result.length == 0)
+            return null;
+        else
+            return result[0];
+    }
+
+    /**
+     * Returns all child nodes with the specified name.
+     */
+    public static Node[] getChildNodes(Node node, String name) {
+        List<Node> result = new ArrayList<Node>();
+
+        Node child = node.getFirstChild();
+        while (child != null) {
+            if (child.getNodeName().equals(name))
+                result.add(child);
+            child = child.getNextSibling();
+        }
+
+        return result.toArray(new Node[result.size()]);
+    }
+
+    /**
+     * Returns a URL with a trailing / appended to it if there is no
+     * trailing slash on the specifed URL.
+     */
+    private URL addSlash(URL source) {
+        if (source == null)
+            return null;
+
+        if (!source.toString().endsWith("/")) {
+            try {
+                source = new URL(source.toString() + "/");
+            } catch (MalformedURLException ex) {
+            }
+        }
+
+        return source;
+    }
+
+    /**
+     * Returns the same result as getURL except that a
+     * ParseException is thrown if the attribute is null or empty.
+     *
+     * @param node the node
+     * @param name the attribute containing an href
+     * @param base the base URL
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public URL getRequiredURL(Node node, String name, URL base) throws ParseException {
+        // probably should change "" to null so that url is always
+        // required even if !strict
+        getRequiredAttribute(node, name, "");
+
+        return getURL(node, name, base);
+    }
+
+    /**
+     * Returns a URL object from a href string relative to the
+     * code base.  If the href denotes a relative URL, it must
+     * reference a location that is a subdirectory of the
+     * codebase.<p>
+     *
+     * @param node the node
+     * @param name the attribute containing an href
+     * @param base the base URL
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public URL getURL(Node node, String name, URL base) throws ParseException {
+        String href = getAttribute(node, name, null);
+        if (href == null)
+            return null; // so that code can throw an exception if attribute was required
+
+        try {
+            if (base == null)
+                return new URL(href);
+            else {
+                try {
+                    return new URL(href);
+                } catch (MalformedURLException ex) {
+                    // is relative
+                }
+
+                URL result = new URL(base, href);
+
+                // check for going above the codebase
+                if (!result.toString().startsWith(base.toString()))
+                    if (strict)
+                        throw new ParseException(R("PUrlNotInCodebase", node.getNodeName(), href, base));
+
+                return result;
+            }
+
+        } catch (MalformedURLException ex) {
+            if (base == null)
+                throw new ParseException(R("PBadNonrelativeUrl", node.getNodeName(), href));
+            else
+                throw new ParseException(R("PBadRelativeUrl", node.getNodeName(), href, base));
+        }
+    }
+
+    /**
+     * Returns a Version from the specified attribute and default
+     * value.
+     *
+     * @param node the node
+     * @param name the attribute
+     * @param defaultValue default if no such attribute
+     * @return a Version, or null if no such attribute and default is null
+     */
+    public Version getVersion(Node node, String name, String defaultValue) {
+        String version = getAttribute(node, name, defaultValue);
+        if (version == null)
+            return null;
+        else
+            return new Version(version);
+    }
+
+    /**
+     * Check that the VM args are valid and safe
+     * @param vmArgs a string containing the args
+     * @throws ParseException if the VM arguments are invalid or dangerous
+     */
+    private void checkVMArgs(String vmArgs) throws IllegalArgumentException {
+        if (vmArgs == null) {
+            return;
+        }
+
+        List<String> validArguments = Arrays.asList(getValidVMArguments());
+        List<String> validStartingArguments = Arrays.asList(getValidStartingVMArguments());
+
+        String[] arguments = vmArgs.split(" ");
+        boolean argumentIsValid = false;
+        for (String argument : arguments) {
+            argumentIsValid = false;
+
+            if (validArguments.contains(argument)) {
+                argumentIsValid = true;
+            } else {
+                for (String validStartingArgument : validStartingArguments) {
+                    if (argument.startsWith(validStartingArgument)) {
+                        argumentIsValid = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!argumentIsValid) {
+                throw new IllegalArgumentException(argument);
+            }
+        }
+
+    }
+
+    /**
+     * Returns an array of valid (ie safe and supported) arguments for the JVM
+     *
+     * Based on http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html
+     */
+    private String[] getValidVMArguments() {
+        return new String[] {
+                "-d32", /* use a 32-bit data model if available */
+                "-client", /* to select the client VM */
+                "-server", /* to select the server VM */
+                "-verbose", /* enable verbose output */
+                "-version", /* print product version and exit */
+                "-showversion", /* print product version and continue */
+                "-help", /* print this help message */
+                "-X", /* print help on non-standard options */
+                "-ea", /* enable assertions */
+                "-enableassertions", /* enable assertions */
+                "-da", /* disable assertions */
+                "-disableassertions", /* disable assertions */
+                "-esa", /* enable system assertions */
+                "-enablesystemassertions", /* enable system assertions */
+                "-dsa", /* disable system assertione */
+                "-disablesystemassertions", /* disable system assertione */
+                "-Xmixed", /* mixed mode execution (default) */
+                "-Xint", /* interpreted mode execution only */
+                "-Xnoclassgc", /* disable class garbage collection */
+                "-Xincgc", /* enable incremental garbage collection */
+                "-Xbatch", /* disable background compilation */
+                "-Xprof", /* output cpu profiling data */
+                "-Xdebug", /* enable remote debugging */
+                "-Xfuture", /* enable strictest checks, anticipating future default */
+                "-Xrs", /* reduce use of OS signals by Java/VM (see documentation) */
+                "-XX:+ForceTimeHighResolution", /* use high resolution timer */
+                "-XX:-ForceTimeHighResolution", /* use low resolution (default) */
+        };
+    }
+
+    /**
+     * Returns an array containing the starts of valid (ie safe and supported)
+     * arguments for the JVM
+     *
+     * Based on http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html
+     */
+    private String[] getValidStartingVMArguments() {
+        return new String[] {
+                "-ea", /* enable assertions for classes */
+                "-enableassertions", /* enable assertions for classes */
+                "-da", /* disable assertions for classes */
+                "-disableassertions", /* disable assertions for classes */
+                "-verbose", /* enable verbose output */
+                "-Xms", /* set initial Java heap size */
+                "-Xmx", /* set maximum Java heap size */
+                "-Xss", /* set java thread stack size */
+                "-XX:NewRatio", /* set Ratio of new/old gen sizes */
+                "-XX:NewSize", /* set initial size of new generation */
+                "-XX:MaxNewSize", /* set max size of new generation */
+                "-XX:PermSize", /* set initial size of permanent gen */
+                "-XX:MaxPermSize", /* set max size of permanent gen */
+                "-XX:MaxHeapFreeRatio", /* heap free percentage (default 70) */
+                "-XX:MinHeapFreeRatio", /* heap free percentage (default 40) */
+                "-XX:UseSerialGC", /* use serial garbage collection */
+                "-XX:ThreadStackSize", /* thread stack size (in KB) */
+                "-XX:MaxInlineSize", /* set max num of bytecodes to inline */
+                "-XX:ReservedCodeCacheSize", /* Reserved code cache size (bytes) */
+                "-XX:MaxDirectMemorySize",
+
+        };
+    }
+
+    /**
+     * Returns the same result as getAttribute except that if strict
+     * mode is enabled or the default value is null a parse
+     * exception is thrown instead of returning the default value.
+     *
+     * @param node the node
+     * @param name the attribute
+     * @param defaultValue default value
+     * @throws ParseException if the attribute does not exist or is empty
+     */
+    public String getRequiredAttribute(Node node, String name, String defaultValue) throws ParseException {
+        String result = getAttribute(node, name, null);
+
+        if (result == null || result.length() == 0)
+            if (strict || defaultValue == null)
+                throw new ParseException(R("PNeedsAttribute", node.getNodeName(), name));
+
+        if (result == null)
+            return defaultValue;
+        else
+            return result;
+    }
+
+    /**
+     * Retuns an attribute or the specified defaultValue if there is
+     * no such attribute.
+     *
+     * @param node the node
+     * @param name the attribute
+     * @param defaultValue default if no such attribute
+     */
+    public String getAttribute(Node node, String name, String defaultValue) {
+        // SAX
+        // String result = ((Element) node).getAttribute(name);
+        String result = node.getAttribute(name);
+
+        if (result == null || result.length() == 0)
+            return defaultValue;
+
+        return result;
+    }
+
+    /**
+     * Return the root node from the XML document in the specified
+     * input stream.
+     *
+     * @throws ParseException if the JNLP file is invalid
+     */
+    public static Node getRootNode(InputStream input) throws ParseException {
+        try {
+            /* SAX
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setValidating(false);
+            factory.setNamespaceAware(true);
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            builder.setErrorHandler(errorHandler);
+
+            Document doc = builder.parse(input);
+            return doc.getDocumentElement();
+            */
+
+            /* TINY
+            Node document = new Node(TinyParser.parseXML(input));
+            Node jnlpNode = getChildNode(document, "jnlp"); // skip comments
+            */
+
+            //A BufferedInputStream is used to allow marking and reseting
+            //of a stream.
+            BufferedInputStream bs = new BufferedInputStream(input);
+
+            /* NANO */
+            final XMLElement xml = new XMLElement();
+            final PipedInputStream pin = new PipedInputStream();
+            final PipedOutputStream pout = new PipedOutputStream(pin);
+            final InputStreamReader isr = new InputStreamReader(bs, getEncoding(bs));
+            // Clean the jnlp xml file of all comments before passing
+            // it to the parser.
+            new Thread(
+                    new Runnable() {
+                        public void run() {
+                            (new XMLElement()).sanitizeInput(isr, pout);
+                            try {
+                                pout.close();
+                            } catch (IOException ioe) {
+                                ioe.printStackTrace();
+                            }
+                        }
+                    }).start();
+            xml.parseFromReader(new InputStreamReader(pin));
+            Node jnlpNode = new Node(xml);
+            return jnlpNode;
+        } catch (Exception ex) {
+            throw new ParseException(R("PBadXML"), ex);
+        }
+    }
+
+    /**
+     * Returns the name of the encoding used in this InputStream.
+     *
+     * @param input the InputStream
+     * @return a String representation of encoding
+     */
+    private static String getEncoding(InputStream input) throws IOException {
+        //Fixme: This only recognizes UTF-8, UTF-16, and
+        //UTF-32, which is enough to parse the prolog portion of xml to
+        //find out the exact encoding (if it exists). The reason being
+        //there could be other encodings, such as ISO 8859 which is 8-bits
+        //but it supports latin characters.
+        //So what needs to be done is to parse the prolog and retrieve
+        //the exact encoding from it.
+
+        int[] s = new int[4];
+        String encoding = "UTF-8";
+
+        //Determine what the first four bytes are and store
+        //them into an int array.
+        input.mark(4);
+        for (int i = 0; i < 4; i++) {
+            s[i] = input.read();
+        }
+        input.reset();
+
+        //Set the encoding base on what the first four bytes of the
+        //inputstream turn out to be (following the information from
+        //www.w3.org/TR/REC-xml/#sec-guessing).
+        if (s[0] == 255) {
+            if (s[1] == 254) {
+                if (s[2] != 0 || s[3] != 0) {
+                    encoding = "UnicodeLittle";
+                } else {
+                    encoding = "X-UTF-32LE-BOM";
+                }
+            }
+        } else if (s[0] == 254 && s[1] == 255 && (s[2] != 0 ||
+                s[3] != 0)) {
+            encoding = "UTF-16";
+
+        } else if (s[0] == 0 && s[1] == 0 && s[2] == 254 &&
+                s[3] == 255) {
+            encoding = "X-UTF-32BE-BOM";
+
+        } else if (s[0] == 0 && s[1] == 0 && s[2] == 0 &&
+                s[3] == 60) {
+            encoding = "UTF-32BE";
+
+        } else if (s[0] == 60 && s[1] == 0 && s[2] == 0 &&
+                s[3] == 0) {
+            encoding = "UTF-32LE";
+
+        } else if (s[0] == 0 && s[1] == 60 && s[2] == 0 &&
+                s[3] == 63) {
+            encoding = "UTF-16BE";
+        } else if (s[0] == 60 && s[1] == 0 && s[2] == 63 &&
+                s[3] == 0) {
+            encoding = "UTF-16LE";
+        }
+
+        return encoding;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParserSettings.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParserSettings.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ParserSettings.java	(revision 403)
@@ -0,0 +1,61 @@
+/* ParserSettings.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+
+package net.sourceforge.jnlp;
+
+/**
+ * Contains settings to be used by the Parser while parsing JNLP files.
+ *
+ * Immutable and therefore thread-safe.
+ */
+public class ParserSettings {
+
+    private final boolean isStrict;
+
+    public ParserSettings() {
+        isStrict = false;
+    }
+
+    public ParserSettings(boolean strict) {
+        isStrict = strict;
+    }
+
+    public boolean isStrict() {
+        return isStrict;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PluginBridge.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PluginBridge.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PluginBridge.java	(revision 403)
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2007 Red Hat, Inc.
+ * This file is part of IcedTea, http://icedtea.classpath.org
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package net.sourceforge.jnlp;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class PluginBridge extends JNLPFile {
+
+    String name;
+    String[] jars = new String[0];
+    String[] cacheJars = new String[0];
+    String[] cacheExJars = new String[0];
+    Hashtable<String, String> atts;
+    private boolean usePack;
+    private boolean useVersion;
+    private boolean codeBaseLookup;
+
+    public PluginBridge(URL codebase, URL documentBase, String jar, String main,
+                        int width, int height, Hashtable<String, String> atts)
+            throws Exception {
+        specVersion = new Version("1.0");
+        fileVersion = new Version("1.1");
+        this.codeBase = codebase;
+        this.sourceLocation = documentBase;
+
+        if (atts.containsKey("jnlp_href")) {
+            try {
+                URL jnlp = new URL(codeBase.toExternalForm() + atts.get("jnlp_href"));
+                JNLPFile jnlpFile = new JNLPFile(jnlp);
+                Map<String, String> jnlpParams = jnlpFile.getApplet().getParameters();
+
+                // Change the parameter name to lowercase to follow conventions.
+                for (Map.Entry<String, String> entry : jnlpParams.entrySet()) {
+                    atts.put(entry.getKey().toLowerCase(), entry.getValue());
+                }
+            } catch (MalformedURLException e) {
+                // Don't fail because we cannot get the jnlp file. Parameters are optional not required.
+                // it is the site developer who should ensure that file exist.
+                System.err.println("Unable to get JNLP file at: " + codeBase.toExternalForm()
+                        + atts.get("jnlp_href"));
+            }
+        }
+
+        // also, see if cache_archive is specified
+        String cacheArchive = atts.get("cache_archive");
+        if (cacheArchive != null && cacheArchive.length() > 0) {
+
+            String[] versions = new String[0];
+
+            // are there accompanying versions?
+            String cacheVersion = atts.get("cache_version");
+            if (cacheVersion != null) {
+                versions = cacheVersion.split(",");
+            }
+
+            String[] jars = cacheArchive.split(",");
+            cacheJars = new String[jars.length];
+
+            for (int i = 0; i < jars.length; i++) {
+
+                cacheJars[i] = jars[i].trim();
+
+                if (versions.length > 0) {
+                    cacheJars[i] += ";" + versions[i].trim();
+                }
+            }
+        }
+
+        String cacheArchiveEx = atts.get("cache_archive_ex");
+        if (cacheArchiveEx != null && cacheArchiveEx.length() > 0) {
+            cacheExJars = cacheArchiveEx.split(",");
+        }
+
+        if (jar != null && jar.length() > 0) {
+            this.jars = jar.split(",");
+
+            // trim white spaces
+            for (int i = 0; i < this.jars.length; i++) {
+                this.jars[i] = this.jars[i].trim();
+            }
+
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Jar string: " + jar);
+                System.err.println("jars length: " + jars.length);
+            }
+        }
+        this.atts = atts;
+
+        name = atts.get("name");
+        if (name == null)
+            name = "Applet";
+        else
+            name = name + " applet";
+
+        if (main.endsWith(".class"))
+            main = main.substring(0, main.length() - 6);
+
+        launchType = new AppletDesc(name, main, documentBase, width,
+                                    height, atts);
+
+        if (main.endsWith(".class")) //single class file only
+            security = new SecurityDesc(this, SecurityDesc.SANDBOX_PERMISSIONS,
+                                        codebase.getHost());
+        else
+            security = null;
+
+        /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html, 
+         * classloaders are shared iff these properties match:
+         * codebase, cache_archive, java_archive, archive
+         * 
+         * To achieve this, we create the uniquekey based on those 4 values,
+         * always in the same order. The initial "<NAME>=" parts ensure a 
+         * bad tag cannot trick the loader into getting shared with another.
+         */
+
+        // Firefox sometimes skips the codebase if it is default  -- ".", 
+        // so set it that way if absent
+        String codebaseAttr =      atts.get("codebase") != null ?
+                                   atts.get("codebase") : ".";
+
+        String cache_archiveAttr = atts.get("cache_archive") != null ? 
+                                   atts.get("cache_archive") : "";
+
+        String java_archiveAttr =  atts.get("java_archive") != null ? 
+                                   atts.get("java_archive") : "";
+
+        String archiveAttr =       atts.get("archive") != null ? 
+                                   atts.get("archive") : "";
+
+        this.uniqueKey = "codebase=" + codebaseAttr +
+                         "cache_archive=" + cache_archiveAttr + 
+                         "java_archive=" + java_archiveAttr + 
+                         "archive=" +  archiveAttr;
+
+        usePack = false;
+        useVersion = false;
+        String jargs = atts.get("java_arguments");
+        if (jargs != null) {
+            for (String s : jargs.split(" ")) {
+                String[] parts = s.trim().split("=");
+                if (parts.length == 2 && Boolean.valueOf(parts[1])) {
+                    if ("-Djnlp.packEnabled".equals(parts[0])) {
+                        usePack = true;
+                    } else if ("-Djnlp.versionEnabled".equals(parts[0])) {
+                        useVersion = true;
+                    }
+                }
+            }
+        }
+        String cbl = atts.get("codebase_lookup");
+        codeBaseLookup = cbl == null || (Boolean.valueOf(cbl));
+    }
+
+    public boolean codeBaseLookup() {
+    	return codeBaseLookup;
+    }
+
+    /**
+     * {@inheritdoc }
+     */
+    @Override
+    public DownloadOptions getDownloadOptionsForJar(JARDesc jar) {
+        return new DownloadOptions(usePack, useVersion);
+    }
+
+    public String getTitle() {
+        return name;
+    }
+
+    public InformationDesc getInformation(final Locale locale) {
+        return new InformationDesc(this, new Locale[] { locale }) {
+            protected List<Object> getItems(Object key) {
+                // Should we populate this list with applet attribute tags?
+                return new ArrayList<Object>();
+            }
+        };
+    }
+
+    public ResourcesDesc getResources(final Locale locale, final String os,
+                                      final String arch) {
+        return new ResourcesDesc(this, new Locale[] { locale }, new String[] { os },
+                new String[] { arch }) {
+            @Override
+            public <T> List<T> getResources(Class<T> launchType) {
+                // Need to add the JAR manually...
+                //should this be done to sharedResources on init?
+                if (launchType.equals(JARDesc.class)) {
+                    try {
+                        List<JARDesc> jarDescs = new ArrayList<JARDesc>();
+                        jarDescs.addAll(sharedResources.getResources(JARDesc.class));
+
+                        for (int i = 0; i < jars.length; i++)
+                            if (jars[i].length() > 0)
+                                jarDescs.add(new JARDesc(new URL(codeBase, jars[i]),
+                                        null, null, false, true, false, true));
+
+                        boolean cacheable = true;
+
+                        String cacheOption = atts.get("cache_option");
+                        if (cacheOption != null && cacheOption.equalsIgnoreCase("no"))
+                            cacheable = false;
+
+                        for (int i = 0; i < cacheJars.length; i++) {
+
+                            String[] jarAndVer = cacheJars[i].split(";");
+
+                            String jar = jarAndVer[0];
+                            Version version = null;
+
+                            if (jar.length() == 0)
+                                continue;
+
+                            if (jarAndVer.length > 1) {
+                                version = new Version(jarAndVer[1]);
+                            }
+
+                            jarDescs.add(new JARDesc(new URL(codeBase, jar),
+                                    version, null, false, true, false, cacheable));
+                        }
+
+                        for (int i = 0; i < cacheExJars.length; i++) {
+
+                            if (cacheExJars[i].length() == 0)
+                                continue;
+
+                            String[] jarInfo = cacheExJars[i].split(";");
+
+                            String jar = jarInfo[0].trim();
+                            Version version = null;
+                            boolean lazy = true;
+
+                            if (jarInfo.length > 1) {
+
+                                // format is name[[;preload];version]
+
+                                if (jarInfo[1].equals("preload")) {
+                                    lazy = false;
+                                } else {
+                                    version = new Version(jarInfo[1].trim());
+                                }
+
+                                if (jarInfo.length > 2) {
+                                    lazy = false;
+                                    version = new Version(jarInfo[2].trim());
+                                }
+                            }
+
+                            jarDescs.add(new JARDesc(new URL(codeBase, jar),
+                                    version, null, lazy, true, false, false));
+                        }
+                        // We know this is a safe list of JarDesc objects
+                        @SuppressWarnings("unchecked")
+                        List<T> result = (List<T>) jarDescs;
+                        return result;
+                    } catch (MalformedURLException ex) { /* Ignored */
+                    }
+                }
+                return sharedResources.getResources(launchType);
+            }
+
+            @Override
+            public JARDesc[] getJARs() {
+                List<JARDesc> jarDescs = getResources(JARDesc.class);
+                return jarDescs.toArray(new JARDesc[jarDescs.size()]);
+            }
+
+            public void addResource(Object resource) {
+                // todo: honor the current locale, os, arch values
+                sharedResources.addResource(resource);
+            }
+
+        };
+    }
+
+    /**
+     * Returns the resources section of the JNLP file for the
+     * specified locale, os, and arch.
+     */
+    public ResourcesDesc[] getResourcesDescs(final Locale locale, final String os, final String arch) {
+        return new ResourcesDesc[] { getResources(locale, os, arch) };
+    }
+
+    public boolean isApplet() {
+        return true;
+    }
+
+    public boolean isApplication() {
+        return false;
+    }
+
+    public boolean isComponent() {
+        return false;
+    }
+
+    public boolean isInstaller() {
+        return false;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PropertyDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PropertyDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/PropertyDesc.java	(revision 403)
@@ -0,0 +1,58 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+/**
+ * The property element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class PropertyDesc {
+
+    /** the key name */
+    private String key;
+
+    /** the value */
+    private String value;
+
+    /**
+     * Creates a property descriptor.
+     *
+     * @param key the key name
+     * @param value the value
+     */
+    public PropertyDesc(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * Returns the property's key
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * Returns the property's value
+     */
+    public String getValue() {
+        return value;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/RelatedContentDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/RelatedContentDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/RelatedContentDesc.java	(revision 403)
@@ -0,0 +1,93 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.net.URL;
+
+public class RelatedContentDesc {
+
+    /** title of the content */
+    private String title = null;;
+
+    /** the description of the content */
+    private String description = null;
+
+    /** the location of the content */
+    private URL location = null;
+
+    /** the icon for this related content */
+    private IconDesc icon = null;
+
+    /**
+     * Create a related-content descriptor
+     * @param href the url of the related content
+     */
+    public RelatedContentDesc(URL href) {
+        this.location = href;
+    }
+
+    /**
+     * Set the title of this content
+     * @param title the title of this content
+     */
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    /**
+     * Returns the title of this content..
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * Set the description of this related content
+     */
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * Returns the description of the related content
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Returns the location of the related content. Not null
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Set the icon for this related content
+     */
+    public void setIconDesc(IconDesc icon) {
+        this.icon = icon;
+    }
+
+    /**
+     * Returns the icon descriptor for the realted content
+     */
+    public IconDesc getIcon() {
+        return icon;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ResourcesDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ResourcesDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ResourcesDesc.java	(revision 403)
@@ -0,0 +1,227 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.util.*;
+
+/**
+ * The resources element.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+public class ResourcesDesc {
+
+    /** the locales of these resources */
+    private Locale locales[];
+
+    /** the OS for these resources */
+    private String os[];
+
+    /** the arch for these resources */
+    private String arch[];
+
+    /** the JNLPFile this information is for */
+    private JNLPFile jnlpFile;
+
+    /** list of jars, packages, properties, and extensions */
+    private List<Object> resources = new ArrayList<Object>();
+
+    // mixed list makes easier for lookup code
+
+    /**
+     * Create a representation of one information section of the
+     * JNLP File.
+     *
+     * @param jnlpFile JNLP file the resources are for
+     * @param locales the locales of these resources
+     * @param os the os of these resources
+     * @param arch the arch of these resources
+     */
+    public ResourcesDesc(JNLPFile jnlpFile, Locale locales[], String os[], String arch[]) {
+        this.jnlpFile = jnlpFile;
+        this.locales = locales;
+        this.os = os;
+        this.arch = arch;
+    }
+
+    /**
+     * Returns the JVMs.
+     */
+    public JREDesc[] getJREs() {
+        List<JREDesc> resources = getResources(JREDesc.class);
+        return resources.toArray(new JREDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the main JAR for these resources.  There first JAR
+     * is returned if no JARs are specified as the main JAR, and if
+     * there are no JARs defined then null is returned.
+     */
+    public JARDesc getMainJAR() {
+        JARDesc jars[] = getJARs();
+
+        for (int i = 0; i < jars.length; i++)
+            if (jars[i].isMain())
+                return jars[i];
+
+        if (jars.length > 0)
+            return jars[0];
+        else
+            return null;
+    }
+
+    /**
+     * Returns all of the JARs.
+     */
+    public JARDesc[] getJARs() {
+        List<JARDesc> resources = getResources(JARDesc.class);
+        return resources.toArray(new JARDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the JARs with the specified part name.
+     *
+     * @param partName the part name, null and "" equivalent
+     */
+    public JARDesc[] getJARs(String partName) {
+        List<JARDesc> resources = getResources(JARDesc.class);
+
+        for (int i = resources.size(); i-- > 0;) {
+            JARDesc jar = resources.get(i);
+
+            if (!("" + jar.getPart()).equals("" + partName))
+                resources.remove(i);
+        }
+
+        return resources.toArray(new JARDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the Extensions.
+     */
+    public ExtensionDesc[] getExtensions() {
+        List<ExtensionDesc> resources = getResources(ExtensionDesc.class);
+        return resources.toArray(new ExtensionDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the Packages.
+     */
+    public PackageDesc[] getPackages() {
+        List<PackageDesc> resources = getResources(PackageDesc.class);
+        return resources.toArray(new PackageDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the Packages that match the specified class name.
+     *
+     * @param className the fully qualified class name
+     * @return the PackageDesc objects matching the class name
+     */
+    public PackageDesc[] getPackages(String className) {
+        List<PackageDesc> resources = getResources(PackageDesc.class);
+
+        for (int i = resources.size(); i-- > 0;) {
+            PackageDesc pk = resources.get(i);
+
+            if (!pk.matches(className))
+                resources.remove(i);
+        }
+
+        return resources.toArray(new PackageDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the Properties as a list.
+     */
+    public PropertyDesc[] getProperties() {
+        List<PropertyDesc> resources = getResources(PropertyDesc.class);
+        return resources.toArray(new PropertyDesc[resources.size()]);
+    }
+
+    /**
+     * Returns the properties as a map.
+     */
+    public Map<String, String> getPropertiesMap() {
+        Map<String, String> properties = new HashMap<String, String>();
+        List<PropertyDesc> resources = getResources(PropertyDesc.class);
+        for (int i = 0; i < resources.size(); i++) {
+            PropertyDesc prop = resources.get(i);
+            properties.put(prop.getKey(), prop.getValue());
+        }
+
+        return properties;
+    }
+
+    /**
+     * Returns the os required by these resources, or null if no
+     * locale was specified in the JNLP file.
+     */
+    public String[] getOS() {
+        return os;
+    }
+
+    /**
+     * Returns the architecture required by these resources, or null
+     * if no locale was specified in the JNLP file.
+     */
+    public String[] getArch() {
+        return arch;
+    }
+
+    /**
+     * Returns the locale required by these resources, or null if no
+     * locale was specified in the JNLP file.
+     */
+    public Locale[] getLocales() {
+        return locales;
+    }
+
+    /**
+     * Returns the JNLPFile the resources are for.
+     */
+    public JNLPFile getJNLPFile() {
+        return jnlpFile;
+    }
+
+    /**
+     * Returns all resources of the specified type.
+     */
+    public <T> List<T> getResources(Class<T> type) {
+        List<T> result = new ArrayList<T>();
+
+        for (int i = 0; i < resources.size(); i++)
+            if (type.isAssignableFrom(resources.get(i).getClass()))
+                result.add(type.cast(resources.get(i)));
+
+        return result;
+    }
+
+    /**
+     * Add a resource.
+     */
+    public void addResource(Object resource) {
+        // if this is going to stay public it should probably take an
+        // interface instead of an Object
+        if (resource == null)
+            throw new IllegalArgumentException("null resource");
+
+        resources.add(resource);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/SecurityDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/SecurityDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/SecurityDesc.java	(revision 403)
@@ -0,0 +1,248 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.security.*;
+import java.awt.AWTPermission;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * The security element.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+public class SecurityDesc {
+
+    /*
+     * We do not verify security here, the classloader deals with security
+     */
+
+    /** All permissions. */
+    public static final Object ALL_PERMISSIONS = "All";
+
+    /** Applet permissions. */
+    public static final Object SANDBOX_PERMISSIONS = "Sandbox";
+
+    /** J2EE permissions. */
+    public static final Object J2EE_PERMISSIONS = "J2SE";
+
+    /** permissions type */
+    private Object type;
+
+    /** the download host */
+    private String downloadHost;
+
+    /** whether sandbox applications should get the show window without banner permission */
+    private final boolean grantAwtPermissions;
+
+    /** the JNLP file */
+    private JNLPFile file;
+
+    private final Policy customTrustedPolicy;
+
+    // We go by the rules here:
+    // http://java.sun.com/docs/books/tutorial/deployment/doingMoreWithRIA/properties.html
+
+    // Since this is security sensitive, take a conservative approach:
+    // Allow only what is specifically allowed, and deny everything else
+
+    /** basic permissions for restricted mode */
+    private static Permission j2eePermissions[] = {
+            new AWTPermission("accessClipboard"),
+            // disabled because we can't at this time prevent an
+            // application from accessing other applications' event
+            // queues, or even prevent access to security dialog queues.
+            //
+            // new AWTPermission("accessEventQueue"),
+            new RuntimePermission("exitVM"),
+            new RuntimePermission("loadLibrary"),
+            new RuntimePermission("queuePrintJob"),
+            new SocketPermission("*", "connect"),
+            new SocketPermission("localhost:1024-", "accept, listen"),
+            new FilePermission("*", "read, write"),
+            new PropertyPermission("*", "read"),
+    };
+
+    /** basic permissions for restricted mode */
+    private static Permission sandboxPermissions[] = {
+            new SocketPermission("localhost:1024-", "listen"),
+            // new SocketPermission("<DownloadHost>", "connect, accept"), // added by code
+            new PropertyPermission("java.version", "read"),
+            new PropertyPermission("java.vendor", "read"),
+            new PropertyPermission("java.vendor.url", "read"),
+            new PropertyPermission("java.class.version", "read"),
+            new PropertyPermission("os.name", "read"),
+            new PropertyPermission("os.version", "read"),
+            new PropertyPermission("os.arch", "read"),
+            new PropertyPermission("file.separator", "read"),
+            new PropertyPermission("path.separator", "read"),
+            new PropertyPermission("line.separator", "read"),
+            new PropertyPermission("java.specification.version", "read"),
+            new PropertyPermission("java.specification.vendor", "read"),
+            new PropertyPermission("java.specification.name", "read"),
+            new PropertyPermission("java.vm.specification.vendor", "read"),
+            new PropertyPermission("java.vm.specification.name", "read"),
+            new PropertyPermission("java.vm.version", "read"),
+            new PropertyPermission("java.vm.vendor", "read"),
+            new PropertyPermission("java.vm.name", "read"),
+            new PropertyPermission("javawebstart.version", "read"),
+            new PropertyPermission("javaplugin.*", "read"),
+            new PropertyPermission("jnlp.*", "read,write"),
+            new PropertyPermission("javaws.*", "read,write"),
+            new PropertyPermission("browser", "read"),
+            new PropertyPermission("browser.*", "read"),
+            new RuntimePermission("exitVM"),
+            new RuntimePermission("stopThread"),
+        // disabled because we can't at this time prevent an
+        // application from accessing other applications' event
+        // queues, or even prevent access to security dialog queues.
+        //
+        // new AWTPermission("accessEventQueue"),
+        };
+
+    /** basic permissions for restricted mode */
+    private static Permission jnlpRIAPermissions[] = {
+            new PropertyPermission("awt.useSystemAAFontSettings", "read,write"),
+            new PropertyPermission("http.agent", "read,write"),
+            new PropertyPermission("http.keepAlive", "read,write"),
+            new PropertyPermission("java.awt.syncLWRequests", "read,write"),
+            new PropertyPermission("java.awt.Window.locationByPlatform", "read,write"),
+            new PropertyPermission("javaws.cfg.jauthenticator", "read,write"),
+            new PropertyPermission("javax.swing.defaultlf", "read,write"),
+            new PropertyPermission("sun.awt.noerasebackground", "read,write"),
+            new PropertyPermission("sun.awt.erasebackgroundonresize", "read,write"),
+            new PropertyPermission("sun.java2d.d3d", "read,write"),
+            new PropertyPermission("sun.java2d.dpiaware", "read,write"),
+            new PropertyPermission("sun.java2d.noddraw", "read,write"),
+            new PropertyPermission("sun.java2d.opengl", "read,write"),
+            new PropertyPermission("swing.boldMetal", "read,write"),
+            new PropertyPermission("swing.metalTheme", "read,write"),
+            new PropertyPermission("swing.noxp", "read,write"),
+            new PropertyPermission("swing.useSystemFontSettings", "read,write"),
+    };
+
+    /**
+     * Create a security descriptor.
+     *
+     * @param file the JNLP file
+     * @param type the type of security
+     * @param downloadHost the download host (can always connect to)
+     */
+    public SecurityDesc(JNLPFile file, Object type, String downloadHost) {
+        this.file = file;
+        this.type = type;
+        this.downloadHost = downloadHost;
+
+        String key = DeploymentConfiguration.KEY_SECURITY_ALLOW_HIDE_WINDOW_WARNING;
+        grantAwtPermissions = Boolean.valueOf(JNLPRuntime.getConfiguration().getProperty(key));
+
+        customTrustedPolicy = getCustomTrustedPolicy();
+    }
+
+    /**
+     * Returns a Policy object that represents a custom policy to use instead
+     * of granting {@link AllPermission} to a {@link CodeSource}
+     *
+     * @return a {@link Policy} object to delegate to. May be null, which
+     * indicates that no policy exists and AllPermissions should be granted
+     * instead.
+     */
+    private Policy getCustomTrustedPolicy() {
+        String key = DeploymentConfiguration.KEY_SECURITY_TRUSTED_POLICY;
+        String policyLocation = JNLPRuntime.getConfiguration().getProperty(key);
+
+        Policy policy = null;
+        if (policyLocation != null) {
+            try {
+                URI policyUri = new URI("file://" + policyLocation);
+                policy = Policy.getInstance("JavaPolicy", new URIParameter(policyUri));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        // return the appropriate policy, or null
+        return policy;
+    }
+
+    /**
+     * Returns the permissions type, one of: ALL_PERMISSIONS,
+     * SANDBOX_PERMISSIONS, J2EE_PERMISSIONS.
+     */
+    public Object getSecurityType() {
+        return type;
+    }
+
+    /**
+     * Returns a PermissionCollection containing the basic
+     * permissions granted depending on the security type.
+     *
+     * @param cs the CodeSource to get permissions for
+     */
+    public PermissionCollection getPermissions(CodeSource cs) {
+        PermissionCollection permissions = getSandBoxPermissions();
+
+        // discard sandbox, give all
+        if (type == ALL_PERMISSIONS) {
+            permissions = new Permissions();
+            if (customTrustedPolicy == null) {
+                permissions.add(new AllPermission());
+                return permissions;
+            } else {
+                return customTrustedPolicy.getPermissions(cs);
+            }
+        }
+
+        // add j2ee to sandbox if needed
+        if (type == J2EE_PERMISSIONS)
+            for (int i = 0; i < j2eePermissions.length; i++)
+                permissions.add(j2eePermissions[i]);
+
+        return permissions;
+    }
+
+    /**
+     * Returns a PermissionCollection containing the sandbox permissions
+     */
+    public PermissionCollection getSandBoxPermissions() {
+
+        Permissions permissions = new Permissions();
+
+        for (int i = 0; i < sandboxPermissions.length; i++)
+            permissions.add(sandboxPermissions[i]);
+
+        if (grantAwtPermissions) {
+            permissions.add(new AWTPermission("showWindowWithoutWarningBanner"));
+        }
+
+        if (file.isApplication())
+            for (int i = 0; i < jnlpRIAPermissions.length; i++)
+                permissions.add(jnlpRIAPermissions[i]);
+
+        if (downloadHost != null)
+            permissions.add(new SocketPermission(downloadHost,
+                                                 "connect, accept"));
+
+        return permissions;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ShortcutDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ShortcutDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/ShortcutDesc.java	(revision 403)
@@ -0,0 +1,81 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+public final class ShortcutDesc {
+
+    /** Never create a shortcut */
+    public static final String CREATE_NEVER = "NEVER";
+    /** Always create a shortcut */
+    public static final String CREATE_ALWAYS = "ALWAYS";
+    /** Always ask user whether to create a shortcut */
+    public static final String CREATE_ASK_USER = "ASK_USER";
+    /** Ask user whether to create a shortcut but only if jnlp file asks for it */
+    public static final String CREATE_ASK_USER_IF_HINTED = "ASK_IF_HINTED";
+    /** Create a desktop shortcut without prompting if the jnlp asks for it */
+    public static final String CREATE_ALWAYS_IF_HINTED = "ALWAYS_IF_HINTED";
+
+    /** the application wants to be placed on the desktop */
+    private boolean onDesktop = false;
+
+    /** the application needs to be launched online */
+    private boolean requiresOnline = true;
+
+    /** the menu descriptor */
+    private MenuDesc menu = null;
+
+    /**
+     * Create a new Shortcut descriptor
+     * @param requiresOnline whether the shortcut requires connectivity
+     * @param onDesktop whether the shortcut wants to be placed on the desktop
+     */
+    public ShortcutDesc(boolean requiresOnline, boolean onDesktop) {
+        this.requiresOnline = requiresOnline;
+        this.onDesktop = onDesktop;
+    }
+
+    /**
+     * Returns whether the shortcut requires being online
+     */
+    public boolean isOnline() {
+        return requiresOnline;
+    }
+
+    /**
+     * Return whether the shortcut should be placed on the desktop
+     */
+    public boolean onDesktop() {
+        return onDesktop;
+    }
+
+    /**
+     * Add a shortcut to the 'start menu'
+     * (whatever that means on gnome/kde/other ...)
+     * @param menu if/what menu this shortcut should be added to
+     */
+    public void addMenu(MenuDesc menu) {
+        this.menu = menu;
+    }
+
+    /**
+     * Returns the menu this shortcut should be added to
+     */
+    public MenuDesc getMenu() {
+        return menu;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/StreamEater.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/StreamEater.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/StreamEater.java	(revision 403)
@@ -0,0 +1,45 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class reads the output from a launched process and writes it to stdout.
+ */
+public class StreamEater extends Thread {
+    private InputStream stream;
+
+    public StreamEater(InputStream stream) {
+        this.stream = new BufferedInputStream(stream);
+    }
+
+    public void run() {
+        try {
+            while (true) {
+                int c = stream.read();
+                if (c == -1)
+                    break;
+
+                System.out.write(c);
+            }
+        } catch (IOException ex) {
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/UpdateDesc.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/UpdateDesc.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/UpdateDesc.java	(revision 403)
@@ -0,0 +1,70 @@
+package net.sourceforge.jnlp;
+
+/**
+ * Represents an 'update' element in a JNLP file. This element describes when to
+ * check for updates and what actions to take if updates are available
+ *
+ * @see Check
+ * @see Policy
+ */
+public class UpdateDesc {
+
+    /**
+     * Describes when/how long to check for updates.
+     */
+    public enum Check {
+        /** Always check for updates before launching the application */
+        ALWAYS,
+
+        /**
+         * Default. Check for updates until a certain timeout. If the update
+         * check is not completed by timeout, launch the cached application and
+         * continue updating in the background
+         */
+        TIMEOUT,
+
+        /** Check for application updates in the background */
+        BACKGROUND
+    }
+
+    /**
+     * Describes what to do when the Runtime knows there is an applicatFion
+     * update before the application is launched.
+     */
+    public enum Policy {
+        /**
+         * Default. Always download updates without any user prompt and then launch the
+         * application
+         */
+        ALWAYS,
+
+        /**
+         * Prompt the user asking whether the user wants to download and run the
+         * updated application or run the version in the cache
+         */
+        PROMPT_UPDATE,
+
+        /**
+         * Prompts the user asking to download and run the latest version of the
+         * application or abort running
+         */
+        PROMPT_RUN,
+    }
+
+    private Check check;
+    private Policy policy;
+
+    public UpdateDesc(Check check, Policy policy) {
+        this.check = check;
+        this.policy = policy;
+    }
+
+    public Check getCheck() {
+        return this.check;
+    }
+
+    public Policy getPolicy() {
+        return this.policy;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Version.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Version.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/Version.java	(revision 403)
@@ -0,0 +1,348 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp;
+
+import java.util.*;
+
+/**
+ * A JNLP Version string in the form "1.2-3_abc" followed by an
+ * optional + (includes all later versions) or * (matches any
+ * suffixes on versions).  More than one version can be included
+ * in a string by separating them with spaces.<p>
+ *
+ * Version strings are divided by "._-" charecters into parts.
+ * These parts are compared numerically if they can be parsed as
+ * integers or lexographically as strings otherwise.  If the
+ * number of parts is different between two version strings then
+ * the smaller one is padded with zero or the empty string.  Note
+ * that the padding in this version means that 1.2+ matches
+ * 1.4.0-beta1, but may not in future versions.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public class Version {
+
+    // to do: web start does not match versions with a "-" like
+    // "1.4-beta1" using the + modifier, change to mimic that
+    // behavior.
+
+    // also refactor into Version and VersionID classes so that
+    // individual version ids can be easily modified to add/remove
+    // "*" and "+" modifiers.
+
+    /** separates parts of a version string */
+    private static String seperators = ".-_";
+
+    /** magic key for whether a version part was created due to normalization */
+    private static String emptyString = new String("<EMPTY>"); // not intern'ed
+
+    /** contains all the versions matched */
+    private String versionString;
+
+    /**
+     * Create a Version object based on a version string (ie,
+     * "1.2.3+ 4.56*").
+     */
+    public Version(String versions) {
+        versionString = versions;
+    }
+
+    /**
+     * Returns true if the version represents a <i>version-id</i> (a
+     * single version number such as 1.2) and false otherwise.
+     */
+    public boolean isVersionId() {
+        if (-1 != versionString.indexOf(" "))
+            return false;
+
+        return true;
+    }
+
+    /**
+     * Returns true if all of this version's version-ids match one
+     * or more of the specifed version's version-id.
+     *
+     * @param version a version string
+     */
+    public boolean matches(String version) {
+        return matches(new Version(version));
+    }
+
+    /**
+     * Returns true if all of this version's version-ids match one
+     * or more of the specifed version's version-id.
+     *
+     * @param version a Version object
+     */
+    public boolean matches(Version version) {
+        List<String> versionStrings = version.getVersionStrings();
+
+        for (int i = 0; i < versionStrings.size(); i++) {
+            if (!this.matchesSingle(versionStrings.get(i)))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true if any of this version's version-ids match one
+     * or more of the specifed version's version-id.
+     *
+     * @param version a version string
+     */
+    public boolean matchesAny(String version) {
+        return matches(new Version(version));
+    }
+
+    /**
+     * Returns true if any of this version's version-ids match one
+     * or more of the specifed version's version-id.
+     *
+     * @param version a Version object
+     */
+    public boolean matchesAny(Version version) {
+        List<String> versionStrings = version.getVersionStrings();
+
+        for (int i = 0; i < versionStrings.size(); i++) {
+            if (this.matchesSingle(versionStrings.get(i)))
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns whether a single version string is supported by this
+     * Version.
+     *
+     * @param version a non-compound version of the form "1.2.3[+*]"
+     */
+    private boolean matchesSingle(String version) {
+        List<String> versionStrings = this.getVersionStrings();
+        for (int i = 0; i < versionStrings.size(); i++) {
+            if (matches(version, versionStrings.get(i)))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether a single version string is supported by
+     * another single version string.
+     *
+     * @param subversion a non-compound version without "+" or "*"
+     * @param version a non-compound version optionally with "+" or "*"
+     */
+    private boolean matches(String subversion, String version) {
+        List<String> subparts = getParts(subversion);
+        List<String> parts = getParts(version);
+
+        int maxLength = Math.max(subversion.length(), version.length());
+        if (version.endsWith("*")) // star means rest of parts irrelevant: truncate them
+            maxLength = parts.size();
+
+        List<List<String>> versions = new ArrayList<List<String>>();
+        versions.add(subparts);
+        versions.add(parts);
+        normalize(versions, maxLength);
+
+        if (equal(subparts, parts))
+            return true;
+
+        if (version.endsWith("+") && greater(subparts, parts))
+            return true;
+
+        return false;
+    }
+
+    /**
+     * Returns whether the parts of one version are equal to the
+     * parts of another version.
+     *
+     * @param parts1 normalized version parts
+     * @param parts2 normalized version parts
+     */
+    protected boolean equal(List<String> parts1, List<String> parts2) {
+        for (int i = 0; i < parts1.size(); i++) {
+            if (0 != compare(parts1.get(i), parts2.get(i)))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns whether the parts of one version are greater than
+     * the parts of another version.
+     *
+     * @param parts1 normalized version parts
+     * @param parts2 normalized version parts
+     */
+    protected boolean greater(List<String> parts1, List<String> parts2) {
+        //if (true) return false;
+
+        for (int i = 0; i < parts1.size(); i++) {
+            // if part1 > part2 then it's a later version, so return true
+            if (compare(parts1.get(i), parts2.get(i)) > 0)
+                return true;
+
+            // if part1 < part2 then it's a ealier version, so return false
+            if (compare(parts1.get(i), parts2.get(i)) < 0)
+                return false;
+
+            // if equal go to next part
+        }
+
+        // all parts were equal
+        return false; // not greater than
+    }
+
+    /**
+     * Compares two parts of a version string, by value if both can
+     * be interpreted as integers or lexically otherwise.  If a part
+     * is the result of normalization then it can be the Integer
+     * zero or an empty string.
+     *
+     * Returns a value equivalent to part1.compareTo(part2);
+     *
+     * @param part1 a part of a version string
+     * @param part2 a part of a version string
+     * @return comparison of the two parts
+     */
+    protected int compare(String part1, String part2) {
+        Integer number1 = Integer.valueOf(0);
+        Integer number2 = Integer.valueOf(0);
+
+        // compare as integers
+        try {
+            if (!(part1 == emptyString)) // compare to magic normalization key
+                number1 = Integer.valueOf(part1);
+
+            if (!(part2 == emptyString)) // compare to magic normalization key
+                number2 = Integer.valueOf(part2);
+
+            return number1.compareTo(number2);
+        } catch (NumberFormatException ex) {
+            // means to compare as strings
+        }
+
+        if (part1 == emptyString)
+            part1 = "";
+        if (part2 == emptyString)
+            part2 = "";
+
+        return part1.compareTo(part2);
+    }
+
+    /**
+     * Normalize version strings so that they contain the same
+     * number of constituent parts.
+     *
+     * @param versions list array of parts of a version string
+     * @param maxLength truncate lists to this maximum length
+     */
+    protected void normalize(List<List<String>> versions, int maxLength) {
+        int length = 0;
+        for (List<String> vers : versions)
+            length = Math.max(length, vers.size());
+
+        if (length > maxLength)
+            length = maxLength;
+
+        for (List<String> vers : versions) {
+            // remove excess elements
+            while (vers.size() > length)
+                vers.remove(vers.size() - 1);
+
+            // add in empty pad elements
+            while (vers.size() < length)
+                vers.add(emptyString);
+        }
+    }
+
+    /**
+     * Return the individual version strings that make up a Version.
+     */
+    protected List<String> getVersionStrings() {
+        ArrayList<String> strings = new ArrayList<String>();
+
+        StringTokenizer st = new StringTokenizer(versionString, " ");
+        while (st.hasMoreTokens())
+            strings.add(st.nextToken());
+
+        return strings;
+    }
+
+    /**
+     * Return the constituent parts of a version string.
+     *
+     * @param oneVersion a single version id string (not compound)
+     */
+    protected List<String> getParts(String oneVersion) {
+        ArrayList<String> strings = new ArrayList<String>();
+
+        StringTokenizer st = new StringTokenizer(oneVersion, seperators + "+*");
+        while (st.hasMoreTokens()) {
+            strings.add(st.nextToken());
+        }
+
+        return strings;
+    }
+
+    public String toString() {
+        return versionString;
+    }
+
+    /**
+     * Test.
+     */
+    /*
+    public static void main(String args[]) {
+        Version jvms[] = {
+            new Version("1.1* 1.3*"),
+            new Version("1.2+"),
+        };
+
+        Version versions[] = {
+            new Version("1.1"),
+            new Version("1.1.8"),
+            new Version("1.2"),
+            new Version("1.3"),
+            new Version("2.0"),
+            new Version("1.3.1"),
+            new Version("1.2.1"),
+            new Version("1.3.1-beta"),
+            new Version("1.1 1.2"),
+            new Version("1.2 1.3"),
+        };
+
+        for (int j = 0; j < jvms.length; j++) {
+            for (int v = 0; v < versions.length; v++) {
+                System.out.print( jvms[j].toString() + " " );
+                if (!jvms[j].matches(versions[v]))
+                    System.out.print( "!" );
+                System.out.println( "matches " + versions[v].toString() );
+            }
+        }
+
+        System.out.println("Test completed");
+    }
+    */
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java	(revision 403)
@@ -0,0 +1,283 @@
+/* BrowserAwareProxySelector.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+package net.sourceforge.jnlp.browser;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URL;
+import java.net.Proxy.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.jnlp.runtime.JNLPProxySelector;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.runtime.PacEvaluator;
+import net.sourceforge.jnlp.runtime.PacEvaluatorFactory;
+
+/**
+ * A ProxySelector which can read proxy settings from a browser's
+ * configuration and use that.
+ *
+ * @see JNLPProxySelector
+ */
+public class BrowserAwareProxySelector extends JNLPProxySelector {
+
+    /* firefox's constants */
+    public static final int BROWSER_PROXY_TYPE_NONE = 0;
+    public static final int BROWSER_PROXY_TYPE_MANUAL = 1;
+    public static final int BROWSER_PROXY_TYPE_PAC = 2;
+    public static final int BROWSER_PROXY_TYPE_NONE2 = 3;
+    /** use gconf, WPAD and then env (and possibly others)*/
+    public static final int BROWSER_PROXY_TYPE_AUTO = 4;
+    /** use env variables */
+    public static final int BROWSER_PROXY_TYPE_SYSTEM = 5;
+
+    private int browserProxyType = BROWSER_PROXY_TYPE_NONE;
+    private URL browserAutoConfigUrl;
+    private Boolean browserUseSameProxy;
+    private String browserHttpProxyHost;
+    private int browserHttpProxyPort;
+    private String browserHttpsProxyHost;
+    private int browserHttpsProxyPort;
+    private String browserFtpProxyHost;
+    private int browserFtpProxyPort;
+    private String browserSocks4ProxyHost;
+    private int browserSocks4ProxyPort;
+
+    private PacEvaluator browserProxyAutoConfig = null;
+
+    /**
+     * Create a new instance of this class, reading configuration fropm the browser
+     */
+    public BrowserAwareProxySelector() {
+        super();
+        try {
+            initFromBrowserConfig();
+        } catch (IOException e) {
+            if (JNLPRuntime.isDebug()) {
+                e.printStackTrace();
+            }
+            System.err.println(R("RProxyFirefoxNotFound"));
+            browserProxyType = PROXY_TYPE_NONE;
+        }
+    }
+
+    /**
+     * Initialize configuration by reading preferences from the browser (firefox)
+     */
+    private void initFromBrowserConfig() throws IOException {
+
+        File preferencesFile = FirefoxPreferencesFinder.find();
+
+        FirefoxPreferencesParser parser = new FirefoxPreferencesParser(preferencesFile);
+        parser.parse();
+        Map<String, String> prefs = parser.getPreferences();
+
+        String type = prefs.get("network.proxy.type");
+        if (type != null) {
+            browserProxyType = Integer.valueOf(type);
+        } else {
+            browserProxyType = BROWSER_PROXY_TYPE_AUTO;
+        }
+
+        try {
+            String url = prefs.get("network.proxy.autoconfig_url");
+            if (url != null) {
+                browserAutoConfigUrl = new URL(url);
+            }
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+
+        if (browserProxyType == BROWSER_PROXY_TYPE_PAC) {
+            if (browserAutoConfigUrl != null) {
+                browserProxyAutoConfig = PacEvaluatorFactory.getPacEvaluator(browserAutoConfigUrl);
+            }
+        }
+
+        browserUseSameProxy = Boolean.valueOf(prefs.get("network.proxy.share_proxy_settings"));
+
+        browserHttpProxyHost = prefs.get("network.proxy.http");
+        browserHttpProxyPort = stringToPort(prefs.get("network.proxy.http_port"));
+        browserHttpsProxyHost = prefs.get("network.proxy.ssl");
+        browserHttpsProxyPort = stringToPort(prefs.get("network.proxy.ssl_port"));
+        browserFtpProxyHost = prefs.get("network.proxy.ftp");
+        browserFtpProxyPort = stringToPort(prefs.get("network.proxy.ftp_port"));
+        browserSocks4ProxyHost = prefs.get("networking.proxy.socks");
+        browserSocks4ProxyPort = stringToPort(prefs.get("network.proxy.socks_port"));
+    }
+
+    /**
+     * Returns port inside a string. Unlike {@link Integer#valueOf(String)},
+     * it will not throw exceptions.
+     *
+     * @param string the string containing the integer to parse
+     * @return the port inside the string, or Integer.MIN_VALUE
+     */
+    private int stringToPort(String string) {
+        try {
+            return Integer.valueOf(string);
+        } catch (NumberFormatException nfe) {
+            return Integer.MIN_VALUE;
+        }
+    }
+
+    /**
+     * The main entry point for {@link BrowserAwareProxySelector}. Based on
+     * the browser settings, determines proxy information for a given URI.
+     * <p>
+     * The appropriate proxy may be determined by reading static information
+     * from the browser's preferences file, or it may be computed dynamically,
+     * by, for example, running javascript code.
+     */
+    @Override
+    protected List<Proxy> getFromBrowser(URI uri) {
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        String optionDescription = null;
+
+        switch (browserProxyType) {
+            case BROWSER_PROXY_TYPE_PAC:
+                proxies.addAll(getFromBrowserPAC(uri));
+                break;
+            case BROWSER_PROXY_TYPE_MANUAL:
+                proxies.addAll(getFromBrowserConfiguration(uri));
+                break;
+            case BROWSER_PROXY_TYPE_NONE:
+                proxies.add(Proxy.NO_PROXY);
+                break;
+            case BROWSER_PROXY_TYPE_AUTO:
+                // firefox will do a whole lot of stuff to automagically
+                // figure out the right settings. gconf, WPAD, and ENV are used.
+                // https://bugzilla.mozilla.org/show_bug.cgi?id=66057#c32
+                // TODO this is probably not easy/quick to do. using libproxy might be
+                // the simpler workaround
+                if (optionDescription == null) {
+                    optionDescription = "Automatic";
+                }
+            case BROWSER_PROXY_TYPE_SYSTEM:
+                // means use $http_proxy, $ftp_proxy etc.
+                // TODO implement env vars if possible
+                if (optionDescription == null) {
+                    optionDescription = "System";
+                }
+            default:
+                if (optionDescription == null) {
+                    optionDescription = "Unknown";
+                }
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println(R("RProxyFirefoxOptionNotImplemented", browserProxyType, optionDescription));
+                }
+                proxies.add(Proxy.NO_PROXY);
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Browser selected proxies: " + proxies.toString());
+        }
+
+        return proxies;
+    }
+
+    /**
+     * Get an appropriate proxy for a given URI using a PAC specified in the
+     * browser.
+     */
+    private List<Proxy> getFromBrowserPAC(URI uri) {
+        if (browserAutoConfigUrl == null || uri.getScheme().equals("socket")) {
+            return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+        }
+
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        try {
+            String proxiesString = browserProxyAutoConfig.getProxies(uri.toURL());
+            proxies.addAll(getProxiesFromPacResult(proxiesString));
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+            proxies.add(Proxy.NO_PROXY);
+        }
+
+        return proxies;
+    }
+
+    /**
+     * Get an appropriate proxy for the given URI using static information from
+     * the browser's preferences file.
+     */
+    private List<Proxy> getFromBrowserConfiguration(URI uri) {
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        String scheme = uri.getScheme();
+
+        if (browserUseSameProxy) {
+            SocketAddress sa = new InetSocketAddress(browserHttpProxyHost, browserHttpProxyPort);
+            Proxy proxy;
+            if (scheme.equals("socket")) {
+                proxy = new Proxy(Type.SOCKS, sa);
+            } else {
+                proxy = new Proxy(Type.HTTP, sa);
+            }
+            proxies.add(proxy);
+        } else if (scheme.equals("http")) {
+            SocketAddress sa = new InetSocketAddress(browserHttpProxyHost, browserHttpProxyPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("https")) {
+            SocketAddress sa = new InetSocketAddress(browserHttpsProxyHost, browserHttpsProxyPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("ftp")) {
+            SocketAddress sa = new InetSocketAddress(browserFtpProxyHost, browserFtpProxyPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("socket")) {
+            SocketAddress sa = new InetSocketAddress(browserSocks4ProxyHost, browserSocks4ProxyPort);
+            proxies.add(new Proxy(Type.SOCKS, sa));
+        } else {
+            proxies.add(Proxy.NO_PROXY);
+        }
+
+        return proxies;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java	(revision 403)
@@ -0,0 +1,142 @@
+/* FirefoxPreferencesFinder.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.browser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.config.Defaults;
+
+/**
+ * Finds the file corresponding to firefox's (default) preferences file
+ */
+public class FirefoxPreferencesFinder {
+
+    /**
+     * Returns a file object representing firefox's preferences file
+     *
+     * @return a File object representing the preferences file.
+     * @throws FileNotFoundException if the preferences file could not be found
+     * @throws IOException if an exception occurs while trying to identify the
+     * location of the preferences file.
+     */
+    public static File find() throws IOException {
+
+        String configPath = System.getProperty("user.home") + File.separator
+                + (Defaults.OS_DOS_LIKE ? "Mozilla" : ".mozilla")
+                + File.separator + "firefox" + File.separator;
+
+        String profilesPath = configPath + "profiles.ini";
+
+        if (!(new File(profilesPath).isFile())) {
+            throw new FileNotFoundException(profilesPath);
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Using firefox's profiles file: " + profilesPath);
+        }
+        BufferedReader reader = new BufferedReader(new FileReader(profilesPath));
+
+        List<String> linesInSection = new ArrayList<String>();
+        boolean foundDefaultSection = false;
+
+        /*
+         * The profiles.ini file is an ini file. This is a quick hack to read
+         * it. It is very likely to break given anything strange.
+         */
+
+        // find the section with an entry Default=1
+        try {
+            while (true) {
+                String line = reader.readLine();
+                if (line == null) {
+                    break;
+                }
+
+                line = line.trim();
+                if (line.startsWith("[Profile") && line.endsWith("]")) {
+                    if (foundDefaultSection) {
+                        break;
+                    }
+                    // new section
+                    linesInSection = new ArrayList<String>();
+                } else {
+                    linesInSection.add(line);
+                    int equalSignPos = line.indexOf('=');
+                    if (equalSignPos > 0) {
+                        String key = line.substring(0, equalSignPos).trim();
+                        String value = line.substring(equalSignPos+1).trim();
+                        if (key.toLowerCase().equals("default") && value.equals("1")) {
+                            foundDefaultSection = true;
+                        }
+                    }
+                }
+            }
+        } finally {
+            reader.close();
+        }
+
+        if (!foundDefaultSection && linesInSection.size() == 0) {
+            throw new FileNotFoundException("preferences file");
+        }
+
+        String path = null;
+        for (String line : linesInSection) {
+            if (line.startsWith("Path=")) {
+                path = line.substring("Path=".length());
+            }
+        }
+
+        if (path == null) {
+            throw new FileNotFoundException("preferences file");
+        } else {
+            String fullPath = configPath + path + File.separator + "prefs.js";
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Found preferences file: " + fullPath);
+            }
+            return new File(fullPath);
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java	(revision 403)
@@ -0,0 +1,159 @@
+/* FirefoxPreferencesParser.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.browser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * A parser for Firefox's preferences file. It can 'parse' Firefox's
+ * preferences file and expose the prefrences in a simple to use format.
+ * <p>
+ * Sample usage:
+ * <pre>
+ * FirefoxPreferencesParser p = new FirefoxPreferencesParser(prefsFile);
+ * p.parse();
+ * Map&lt;String,String&gt; prefs = p.getPreferences();
+ * System.out.println("blink allowed: " + prefs.get("browser.blink_allowed"));
+ * </pre>
+ */
+public final class FirefoxPreferencesParser {
+
+    File prefsFile = null;
+    Map<String, String> prefs = null;
+
+    /**
+     * Creates a new FirefoxPreferencesParser
+     * @param preferencesFile
+     */
+    public FirefoxPreferencesParser(File preferencesFile) {
+        prefsFile = preferencesFile;
+    }
+
+    /**
+     * Parse the prefernces file
+     * @throws IOException if an exception ocurrs while reading the
+     * preferences file.
+     */
+    public void parse() throws IOException {
+        /*
+         * The Firefox preference file is actually in javascript. It does seem
+         * to be nicely formatted, so it should be possible to hack reading it.
+         * The correct way of course is to use a javascript library and extract
+         * the user_pref object
+         */
+        prefs = new HashMap<String, String>();
+
+        BufferedReader reader = new BufferedReader(new FileReader(prefsFile));
+
+        try {
+            while (true) {
+                String line = reader.readLine();
+                // end of stream
+                if (line == null) {
+                    break;
+                }
+
+                line = line.trim();
+                if (line.startsWith("user_pref")) {
+
+                    /*
+                     * each line is of the form: user_pref("key",value); where value
+                     * can be a string in double quotes or an integer or float or
+                     * boolean
+                     */
+
+                    boolean foundKey = false;
+                    boolean foundValue = false;
+
+                    // extract everything inside user_pref( and );
+                    String pref = line.substring("user_pref(".length(), line.length() - 2);
+                    // key and value are separated by a ,
+                    int firstCommaPos = pref.indexOf(',');
+                    if (firstCommaPos >= 1) {
+                        String key = pref.substring(0, firstCommaPos).trim();
+                        if (key.startsWith("\"") && key.endsWith("\"")) {
+                            key = key.substring(1, key.length() - 1);
+                            if (key.trim().length() > 0) {
+                                foundKey = true;
+                            }
+                        }
+
+                        if (pref.length() > firstCommaPos + 1) {
+                            String value = pref.substring(firstCommaPos + 1).trim();
+                            if (value.startsWith("\"") && value.endsWith("\"")) {
+                                value = value.substring(1, value.length() - 1).trim();
+                            }
+                            foundValue = true;
+
+                            if (foundKey && foundValue) {
+                                // System.out.println("added (\"" + key + "\", \"" + value + "\")");
+                                prefs.put(key, value);
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            reader.close();
+        }
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Read " + prefs.size() + " entries from Firefox's preferences");
+        }
+    }
+
+    /**
+     * Get the firefox preferences as a map (key,value pair). Note that
+     * all values (including integers and booleans) are stored as a string, so
+     * conversion to an appropriate type may be required.
+     *
+     * @return a map containing firefox' preferences
+     */
+    public Map<String, String> getPreferences() {
+        HashMap<String, String> newMap = new HashMap<String, String>();
+        newMap.putAll(prefs);
+        return newMap;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheDirectory.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheDirectory.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheDirectory.java	(revision 403)
@@ -0,0 +1,117 @@
+/* CacheDirectory.java -- Traverse the given directory and return the leafs.
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+package net.sourceforge.jnlp.cache;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import net.sourceforge.jnlp.util.FileUtils;
+
+public final class CacheDirectory {
+
+    /* Don't allow instantiation of this class */
+    private CacheDirectory(){}
+
+    /**
+     * Get the structure of directory for keeping track of the protocol and
+     * domain.
+     * 
+     * @param root Location of cache directory.
+     */
+    public static void getDirStructure(DirectoryNode root) {
+        for (File f : root.getFile().listFiles()) {
+            DirectoryNode node = new DirectoryNode(f.getName(), f, root);
+            if (f.isDirectory() || (!f.isDirectory() && !f.getName().endsWith(".info")))
+                root.addChild(node);
+            if (f.isDirectory())
+                getDirStructure(node);
+        }
+    }
+
+    /**
+     * Get all the leaf nodes.
+     * 
+     * @param root The point where we want to start getting the leafs.
+     * @return An ArrayList of DirectoryNode.
+     */
+    public static ArrayList<DirectoryNode> getLeafData(DirectoryNode root) {
+        ArrayList<DirectoryNode> temp = new ArrayList<DirectoryNode>();
+        for (DirectoryNode f : root.getChildren()) {
+            if (f.isDir())
+                temp.addAll(getLeafData(f));
+            else if (!f.getName().endsWith(".info"))
+                temp.add(f);
+        }
+        return temp;
+    }
+
+    /**
+     * Removes empty folders in the current directory.
+     * 
+     * @param root File pointing at the beginning of directory.
+     * @return True if something was deleted.
+     */
+    public static boolean cleanDir(File root) {
+        boolean delete = true;
+        for (File f : root.listFiles()) {
+            if (f.isDirectory())
+                cleanDir(f);
+            else
+                delete = false;
+        }
+        if (delete)
+            System.out.println("Delete -- " + root);
+        //            root.delete();
+        return true;
+    }
+
+    /**
+     * This will recursively remove the parent folders if they are empty. 
+     * 
+     * @param fileNode
+     */
+    public static void cleanParent(DirectoryNode fileNode) {
+        DirectoryNode parent = fileNode.getParent();
+        if (parent.getParent() == null)
+            return; // Don't delete the root.
+        if (parent.getChildren().size() == 0) {
+            FileUtils.deleteWithErrMesg(parent.getFile());
+            parent.getParent().removeChild(parent);
+            cleanParent(parent);
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheEntry.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheEntry.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheEntry.java	(revision 403)
@@ -0,0 +1,185 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.*;
+import java.net.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.util.*;
+
+/**
+ * Describes an entry in the cache.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.10 $
+ */
+public class CacheEntry {
+
+    /** the remote resource location */
+    private URL location;
+
+    /** the requested version */
+    private Version version;
+
+    /** info about the cached file */
+    private PropertiesFile properties;
+
+    /**
+     * Create a CacheEntry for the resources specified as a remote
+     * URL.
+     *
+     * @param location the remote resource location
+     * @param version the version of the resource
+     */
+    public CacheEntry(URL location, Version version) {
+        this.location = location;
+        this.version = version;
+
+        File infoFile = CacheUtil.getCacheFile(location, version);
+        infoFile = new File(infoFile.getPath() + ".info"); // replace with something that can't be clobbered
+
+        properties = new PropertiesFile(infoFile, R("CAutoGen"));
+    }
+
+    /**
+     * Initialize the cache entry data from a connection to the
+     * remote resource (does not store data).
+     */
+    void initialize(URLConnection connection) {
+        long modified = connection.getLastModified();
+        long length = connection.getContentLength(); // an int
+
+        properties.setProperty("content-length", Long.toString(length));
+        properties.setProperty("last-modified", Long.toString(modified));
+    }
+
+    /**
+     * Returns the remote location this entry caches.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the time in the local system clock that the file was
+     * most recently checked for an update.
+     */
+    public long getLastUpdated() {
+        try {
+            return Long.parseLong(properties.getProperty("last-updated"));
+        } catch (Exception ex) {
+            return 0;
+        }
+    }
+
+    /**
+     * Sets the time in the local system clock that the file was
+     * most recently checked for an update.
+     */
+    public void setLastUpdated(long updatedTime) {
+        properties.setProperty("last-updated", Long.toString(updatedTime));
+    }
+
+    /**
+     * Returns whether there is a version of the URL contents in
+     * the cache and it is up to date.  This method may not return
+     * immediately.
+     *
+     * @param connection a connection to the remote URL
+     * @return whether the cache contains the version
+     */
+    public boolean isCurrent(URLConnection connection) {
+        boolean cached = isCached();
+
+        if (!cached)
+            return false;
+
+        try {
+            long remoteModified = connection.getLastModified();
+            long cachedModified = Long.parseLong(properties.getProperty("last-modified"));
+
+            if (remoteModified > 0 && remoteModified <= cachedModified)
+                return true;
+            else
+                return false;
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            return cached; // if can't connect return whether already in cache
+        }
+    }
+
+    /**
+     * Returns true if the cache has a local copy of the contents
+     * of the URL matching the specified version string.
+     *
+     * @return true if the resource is in the cache
+     */
+    public boolean isCached() {
+        File localFile = CacheUtil.getCacheFile(location, version);
+        if (!localFile.exists())
+            return false;
+
+        try {
+            long cachedLength = localFile.length();
+            long remoteLength = Long.parseLong(properties.getProperty("content-length", "-1"));
+
+            if (remoteLength >= 0 && cachedLength != remoteLength)
+                return false;
+            else
+                return true;
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            return false; // should throw?
+        }
+    }
+
+    /**
+     * Save the current information for the cache entry.
+     */
+    protected void store() {
+        properties.store();
+    }
+
+    /**
+     * Mark this entry for deletion at shutdown.
+     */
+    public void markForDelete() { // once marked it should not be unmarked.
+        properties.setProperty("delete", Boolean.toString(true));
+    }
+
+    /**
+     * Lock cache item.
+     */
+    protected void lock() {
+        CacheUtil.lockFile(properties);
+    }
+
+    /**
+     * Unlock cache item.
+     */
+    protected void unlock() {
+        CacheUtil.unlockFile(properties);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java	(revision 403)
@@ -0,0 +1,252 @@
+/* CacheLRUWrapper -- Handle LRU for cache files.
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map.Entry;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.PropertiesFile;
+
+/**
+ * This class helps maintain the ordering of most recently use items across
+ * multiple jvm instances.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+enum CacheLRUWrapper {
+    INSTANCE;
+
+    private int lockCount = 0;
+
+    /* lock for the file RecentlyUsed */
+    private FileLock fl = null;
+
+    /* location of cache directory */
+    private final String cacheDir = new File(JNLPRuntime.getConfiguration()
+            .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR)).getPath();
+
+    /*
+     * back-end of how LRU is implemented This file is to keep track of the most
+     * recently used items. The items are to be kept with key = (current time
+     * accessed) followed by folder of item. value = path to file.
+     */
+    private PropertiesFile cacheOrder = new PropertiesFile(
+            new File(cacheDir + File.separator + "recently_used"));
+
+    private CacheLRUWrapper(){
+        File f = cacheOrder.getStoreFile();
+        if (!f.exists()) {
+            try {
+                FileUtils.createParentDir(f);
+                FileUtils.createRestrictedFile(f, true);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+    
+    /**
+     * Returns an instance of the policy.
+     * 
+     * @param propertiesFile
+     * @return
+     */
+    public static CacheLRUWrapper getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Update map for keeping track of recently used items.
+     */
+    public synchronized void load() {
+        cacheOrder.load();
+    }
+
+    /**
+     * Write file to disk.
+     */
+    public synchronized void store() {
+        cacheOrder.store();
+    }
+
+    /**
+     * This adds a new entry to file.
+     * 
+     * @param key key we want path to be associated with.
+     * @param path path to cache item.
+     * @return true if we successfully added to map, false otherwise.
+     */
+    public synchronized boolean addEntry(String key, String path) {
+        if (cacheOrder.containsKey(key)) return false;
+        cacheOrder.setProperty(key, path);
+        return true;
+    }
+
+    /**
+     * This removed an entry from our map.
+     * 
+     * @param key key we want to remove.
+     * @return true if we successfully removed key from map, false otherwise.
+     */
+    public synchronized boolean removeEntry(String key) {
+        if (!cacheOrder.containsKey(key)) return false;
+        cacheOrder.remove(key);
+        return true;
+    }
+
+    private String getIdForCacheFolder(String folder) {
+        int len = cacheDir.length();
+        int index = folder.indexOf(File.separatorChar, len + 1);
+        return folder.substring(len + 1, index);
+    }
+
+    /**
+     * This updates the given key to reflect it was recently accessed.
+     * 
+     * @param oldKey Key we wish to update.
+     * @return true if we successfully updated value, false otherwise.
+     */
+    public synchronized boolean updateEntry(String oldKey) {
+        if (!cacheOrder.containsKey(oldKey)) return false;
+        String value = cacheOrder.getProperty(oldKey);
+        String folder = getIdForCacheFolder(value);
+
+        cacheOrder.remove(oldKey);
+        cacheOrder.setProperty(Long.toString(System.currentTimeMillis()) + "," + folder, value);
+        return true;
+    }
+
+    /**
+     * Return a copy of the keys available.
+     * 
+     * @return List of Strings sorted by ascending order.
+     */
+    public synchronized List<Entry<String, String>> getLRUSortedEntries() {
+        ArrayList<Entry<String, String>> entries = new ArrayList(cacheOrder.entrySet());
+        // sort by keys in descending order.
+        Collections.sort(entries, new Comparator<Entry<String, String>>() {
+            @Override
+            public int compare(Entry<String, String> e1, Entry<String, String> e2) {
+                try {
+                    Long t1 = Long.parseLong(e1.getKey().split(",")[0]);
+                    Long t2 = Long.parseLong(e2.getKey().split(",")[0]);
+
+                    int c = t1.compareTo(t2);
+                    return c < 0 ? 1 : (c > 0 ? -1 : 0);
+                } catch (NumberFormatException e) {
+                    // Perhaps an error is too harsh. Maybe just somehow turn
+                    // caching off if this is the case.
+                    throw new InternalError("Corrupt LRU file entries");
+                }
+            }
+        });
+        return entries;
+    }
+
+    /**
+     * Lock the file to have exclusive access.
+     */
+    public synchronized void lock() {
+        try {
+            fl = FileUtils.getFileLock(cacheOrder.getStoreFile().getPath(), false, true);
+        } catch (OverlappingFileLockException e) { // if overlap we just increase the count.
+        } catch (Exception e) { // We didn't get a lock..
+            e.printStackTrace();
+        }
+        if (fl != null) lockCount++;
+    }
+
+    /**
+     * Unlock the file.
+     */
+    public synchronized void unlock() {
+        if (fl != null) {
+            lockCount--;
+            try {
+                if (lockCount == 0) {
+                    fl.release();
+                    fl.channel().close();
+                    fl = null;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Return the value of given key.
+     * 
+     * @param key
+     * @return value of given key, null otherwise.
+     */
+    public synchronized String getValue(String key) {
+        return cacheOrder.getProperty(key);
+    }
+
+    /**
+     * Test if we the key provided is in use.
+     * 
+     * @param key key to be tested.
+     * @return true if the key is in use.
+     */
+    public synchronized boolean contains(String key) {
+        return cacheOrder.contains(key);
+    }
+
+    /**
+     * Generate a key given the path to file. May or may not generate the same
+     * key given same path.
+     * 
+     * @param path Path to generate a key with.
+     * @return String representing the a key.
+     */
+    public String generateKey(String path) {
+        return System.currentTimeMillis() + "," + getIdForCacheFolder(path);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheUtil.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheUtil.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/CacheUtil.java	(revision 403)
@@ -0,0 +1,658 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.*;
+import java.net.*;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.security.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.PropertiesFile;
+
+/**
+ * Provides static methods to interact with the cache, download
+ * indicator, and other utility methods.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.17 $
+ */
+public class CacheUtil {
+
+    private static final String cacheDir = new File(JNLPRuntime.getConfiguration()
+            .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR)).getPath(); // Do this with file to standardize it.
+    private static final CacheLRUWrapper lruHandler = CacheLRUWrapper.getInstance();
+    private static final HashMap<String, FileLock> propertiesLockPool = new HashMap<String, FileLock>();
+
+    /**
+     * Compares a URL using string compare of its protocol, host,
+     * port, path, query, and anchor.  This method avoids the host
+     * name lookup that URL.equals does for http: protocol URLs.
+     * It may not return the same value as the URL.equals method
+     * (different hostnames that resolve to the same IP address,
+     * ie sourceforge.net and www.sourceforge.net).
+     */
+    public static boolean urlEquals(URL u1, URL u2) {
+        if (u1 == u2)
+            return true;
+        if (u1 == null || u2 == null)
+            return false;
+
+        if (!compare(u1.getProtocol(), u2.getProtocol(), true) ||
+                !compare(u1.getHost(), u2.getHost(), true) ||
+                //u1.getDefaultPort() != u2.getDefaultPort() || // only in 1.4
+                !compare(u1.getPath(), u2.getPath(), false) ||
+                !compare(u1.getQuery(), u2.getQuery(), false) ||
+                !compare(u1.getRef(), u2.getRef(), false))
+            return false;
+        else
+            return true;
+    }
+
+    /**
+     * Caches a resource and returns a URL for it in the cache;
+     * blocks until resource is cached.  If the resource location is
+     * not cacheable (points to a local file, etc) then the original
+     * URL is returned.<p>
+     *
+     * @param location location of the resource
+     * @param version the version, or null
+     * @return either the location in the cache or the original location
+     */
+    public static URL getCachedResource(URL location, Version version, UpdatePolicy policy) {
+        ResourceTracker rt = new ResourceTracker();
+        rt.addResource(location, version, null, policy);
+        try {
+            File f = rt.getCacheFile(location);
+            // TODO: Should be toURI().toURL()
+            return f.toURL();
+        } catch (MalformedURLException ex) {
+            return location;
+        }
+    }
+
+    /**
+     * Compare strings that can be null.
+     */
+    private static boolean compare(String s1, String s2, boolean ignore) {
+        if (s1 == s2)
+            return true;
+        if (s1 == null || s2 == null)
+            return false;
+
+        if (ignore)
+            return s1.equalsIgnoreCase(s2);
+        else
+            return s1.equals(s2);
+    }
+
+    /**
+     * Returns the Permission object necessary to access the
+     * resource, or null if no permission is needed.
+     */
+    public static Permission getReadPermission(URL location, Version version) {
+        if (CacheUtil.isCacheable(location, version)) {
+            File file = CacheUtil.getCacheFile(location, version);
+
+            return new FilePermission(file.getPath(), "read");
+        } else {
+            try {
+                // this is what URLClassLoader does
+                return location.openConnection().getPermission();
+            } catch (java.io.IOException ioe) {
+                // should try to figure out the permission
+                if (JNLPRuntime.isDebug())
+                    ioe.printStackTrace();
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Clears the cache by deleting all the Netx cache files
+     *
+     * Note: Because of how our caching system works, deleting jars of another javaws
+     * process is using them can be quite disasterous. Hence why Launcher creates lock files
+     * and we check for those by calling {@link #okToClearCache()}
+     */
+    public static void clearCache() {
+
+        if (!okToClearCache()) {
+            System.err.println(R("CCannotClearCache"));
+            return;
+        }
+
+        File cacheDir = new File(CacheUtil.cacheDir);
+        if (!(cacheDir.isDirectory())) {
+            return;
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("Clearing cache directory: " + cacheDir);
+        }
+        try {
+            cacheDir = cacheDir.getCanonicalFile();
+            FileUtils.recursiveDelete(cacheDir, cacheDir);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns a boolean indicating if it ok to clear the netx application cache at this point
+     * @return true if the cache can be cleared at this time without problems
+     */
+    private static boolean okToClearCache() {
+        File otherJavawsRunning = new File(JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE));
+        try {
+            if (otherJavawsRunning.isFile()) {
+                FileOutputStream fis = new FileOutputStream(otherJavawsRunning);
+                
+                FileChannel channel = fis.getChannel();
+                if (channel.tryLock() == null) {
+                    if (JNLPRuntime.isDebug()) {
+                        System.out.println("Other instances of netx are running");
+                    }
+                    return false;
+                }
+
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("No other instances of netx are running");
+                }
+                return true;
+
+            } else {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("No instance file found");
+                }
+                return true;
+            }
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns whether there is a version of the URL contents in the
+     * cache and it is up to date.  This method may not return
+     * immediately.
+     *
+     * @param source the source URL
+     * @param version the versions to check for
+     * @param connection a connection to the URL, or null
+     * @return whether the cache contains the version
+     * @throws IllegalArgumentException if the source is not cacheable
+     */
+    public static boolean isCurrent(URL source, Version version, URLConnection connection) {
+
+        if (!isCacheable(source, version))
+            throw new IllegalArgumentException(R("CNotCacheable", source));
+
+        try {
+            if (connection == null)
+                connection = source.openConnection();
+
+            connection.connect();
+
+            CacheEntry entry = new CacheEntry(source, version); // could pool this
+            boolean result = entry.isCurrent(connection);
+
+            if (JNLPRuntime.isDebug())
+                System.out.println("isCurrent: " + source + " = " + result);
+
+            return result;
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            return isCached(source, version); // if can't connect return whether already in cache
+        }
+    }
+
+    /**
+     * Returns true if the cache has a local copy of the contents of
+     * the URL matching the specified version string.
+     *
+     * @param source the source URL
+     * @param version the versions to check for
+     * @return true if the source is in the cache
+     * @throws IllegalArgumentException if the source is not cacheable
+     */
+    public static boolean isCached(URL source, Version version) {
+        if (!isCacheable(source, version))
+            throw new IllegalArgumentException(R("CNotCacheable", source));
+
+        CacheEntry entry = new CacheEntry(source, version); // could pool this
+        boolean result = entry.isCached();
+
+        if (JNLPRuntime.isDebug())
+            System.out.println("isCached: " + source + " = " + result);
+
+        return result;
+    }
+
+    /**
+     * Returns whether the resource can be cached as a local file;
+     * if not, then URLConnection.openStream can be used to obtain
+     * the contents.
+     */
+    public static boolean isCacheable(URL source, Version version) {
+        if (source == null)
+            return false;
+
+        if (source.getProtocol().equals("file"))
+            return false;
+
+        if (source.getProtocol().equals("jar"))
+            return false;
+
+        return true;
+    }
+
+    /**
+     * Returns the file for the locally cached contents of the
+     * source.  This method returns the file location only and does
+     * not download the resource.  The latest version of the
+     * resource that matches the specified version will be returned.
+     *
+     * @param source the source URL
+     * @param version the version id of the local file
+     * @return the file location in the cache, or null if no versions cached
+     * @throws IllegalArgumentException if the source is not cacheable
+     */
+    public static File getCacheFile(URL source, Version version) {
+        // ensure that version is an version id not version string
+
+        if (!isCacheable(source, version))
+            throw new IllegalArgumentException(R("CNotCacheable", source));
+
+        File cacheFile = null;
+        synchronized (lruHandler) {
+            lruHandler.lock();
+
+            // We need to reload the cacheOrder file each time
+            // since another plugin/javaws instance may have updated it.
+            lruHandler.load();
+            cacheFile = getCacheFileIfExist(urlToPath(source, ""));
+            if (cacheFile == null) { // We did not find a copy of it.
+                cacheFile = makeNewCacheFile(source, version);
+            }
+            lruHandler.store();
+            lruHandler.unlock();
+        }
+        return cacheFile;
+    }
+
+    /**
+     * This will return a File pointing to the location of cache item.
+     * 
+     * @param urlPath Path of cache item within cache directory.
+     * @return File if we have searched before, null otherwise.
+     */
+    private static File getCacheFileIfExist(File urlPath) {
+        synchronized (lruHandler) {
+            File cacheFile = null;
+            List<Entry<String, String>> entries = lruHandler.getLRUSortedEntries();
+            // Start searching from the most recent to least recent.
+            for (Entry<String, String> e : entries) {
+                final String key = e.getKey();
+                final String path = e.getValue();
+
+                if (path != null) {
+                    if (pathToURLPath(path).equals(urlPath.getPath())) { // Match found.
+                        cacheFile = new File(path);
+                        lruHandler.updateEntry(key);
+                        break; // Stop searching since we got newest one already.
+                    }
+                }
+            }
+            return cacheFile;
+        }
+    }
+
+    /**
+     * Get the path to file minus the cache directory and indexed folder.
+     */
+    private static String pathToURLPath(String path) {
+        int len = cacheDir.length();
+        int index = path.indexOf(File.separatorChar, len + 1);
+        return path.substring(index);
+    }
+
+    /**
+     * This will create a new entry for the cache item. It is however not
+     * initialized but any future calls to getCacheFile with the source and
+     * version given to here, will cause it to return this item.
+     * 
+     * @param source the source URL
+     * @param version the version id of the local file
+     * @return the file location in the cache.
+     */
+    public static File makeNewCacheFile(URL source, Version version) {
+        synchronized (lruHandler) {
+            lruHandler.lock();
+            lruHandler.load();
+
+            File cacheFile = null;
+            for (long i = 0; i < Long.MAX_VALUE; i++) {
+                String path = cacheDir + File.separator + i;
+                File cDir = new File(path);
+                if (!cDir.exists()) {
+                    // We can use this directory.
+                    try {
+                        cacheFile = urlToPath(source, path);
+                        FileUtils.createParentDir(cacheFile);
+                        File pf = new File(cacheFile.getPath() + ".info");
+                        FileUtils.createRestrictedFile(pf, true); // Create the info file for marking later.
+                        lruHandler.addEntry(lruHandler.generateKey(cacheFile.getPath()), cacheFile.getPath());
+                    } catch (IOException ioe) {
+                        ioe.printStackTrace();
+                    }
+
+                    break;
+                }
+            }
+
+            lruHandler.store();
+            lruHandler.unlock();
+            return cacheFile;
+        }
+    }
+
+    /**
+     * Returns a buffered output stream open for writing to the
+     * cache file.
+     *
+     * @param source the remote location
+     * @param version the file version to write to
+     */
+    public static OutputStream getOutputStream(URL source, Version version) throws IOException {
+        File localFile = getCacheFile(source, version);
+        OutputStream out = new FileOutputStream(localFile);
+
+        return new BufferedOutputStream(out);
+    }
+
+    /**
+     * Copies from an input stream to an output stream.  On
+     * completion, both streams will be closed.  Streams are
+     * buffered automatically.
+     */
+    public static void streamCopy(InputStream is, OutputStream os) throws IOException {
+        if (!(is instanceof BufferedInputStream))
+            is = new BufferedInputStream(is);
+
+        if (!(os instanceof BufferedOutputStream))
+            os = new BufferedOutputStream(os);
+
+        try {
+            byte b[] = new byte[4096];
+            while (true) {
+                int c = is.read(b, 0, b.length);
+                if (c == -1)
+                    break;
+
+                os.write(b, 0, c);
+            }
+        } finally {
+            is.close();
+            os.close();
+        }
+    }
+
+    /**
+     * Converts a URL into a local path string within the given directory. For
+     * example a url with subdirectory /tmp/ will
+     * result in a File that is located somewhere within /tmp/
+     *
+     * @param location the url
+     * @param subdir the subdirectory
+     * @return the file
+     */
+    public static File urlToPath(URL location, String subdir) {
+        if (subdir == null) {
+            throw new NullPointerException();
+        }
+
+        StringBuffer path = new StringBuffer();
+
+        path.append(location.getProtocol());
+        path.append(File.separatorChar);
+        path.append(location.getHost());
+        path.append(File.separatorChar);
+        path.append(location.getPath().replace('/', File.separatorChar));
+
+        return new File(subdir + File.separatorChar + FileUtils.sanitizePath(path.toString()));
+    }
+
+    /**
+     * Waits until the resources are downloaded, while showing a
+     * progress indicator.
+     *
+     * @param tracker the resource tracker
+     * @param resources the resources to wait for
+     * @param title name of the download
+     */
+    public static void waitForResources(ApplicationInstance app, ResourceTracker tracker, URL resources[], String title) {
+        DownloadIndicator indicator = JNLPRuntime.getDefaultDownloadIndicator();
+        DownloadServiceListener listener = null;
+
+        try {
+            if (indicator == null) {
+                tracker.waitForResources(resources, 0);
+                return;
+            }
+
+            // see if resources can be downloaded very quickly; avoids
+            // overhead of creating display components for the resources
+            if (tracker.waitForResources(resources, indicator.getInitialDelay()))
+                return;
+
+            // only resources not starting out downloaded are displayed
+            List<URL> urlList = new ArrayList<URL>();
+            for (int i = 0; i < resources.length; i++) {
+                if (!tracker.checkResource(resources[i]))
+                    urlList.add(resources[i]);
+            }
+            URL undownloaded[] = urlList.toArray(new URL[urlList.size()]);
+
+            listener = indicator.getListener(app, title, undownloaded);
+
+            do {
+                long read = 0;
+                long total = 0;
+
+                for (int i = 0; i < undownloaded.length; i++) {
+                    // add in any -1's; they're insignificant
+                    total += tracker.getTotalSize(undownloaded[i]);
+                    read += tracker.getAmountRead(undownloaded[i]);
+                }
+
+                int percent = (int) ((100 * read) / Math.max(1, total));
+
+                for (int i = 0; i < undownloaded.length; i++)
+                    listener.progress(undownloaded[i], "version",
+                                      tracker.getAmountRead(undownloaded[i]),
+                                      tracker.getTotalSize(undownloaded[i]),
+                                      percent);
+            } while (!tracker.waitForResources(resources, indicator.getUpdateRate()));
+
+            // make sure they read 100% until indicator closes
+            for (int i = 0; i < undownloaded.length; i++)
+                listener.progress(undownloaded[i], "version",
+                                  tracker.getTotalSize(undownloaded[i]),
+                                  tracker.getTotalSize(undownloaded[i]),
+                                  100);
+
+        } catch (InterruptedException ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+        } finally {
+            if (listener != null)
+                indicator.disposeListener(listener);
+        }
+    }
+
+    /**
+     * This will remove all old cache items.
+     */
+    public static void cleanCache() {
+        if (okToClearCache()) {
+            // First we want to figure out which stuff we need to delete.
+            HashSet<String> keep = new HashSet<String>();
+            HashSet<String> remove = new HashSet<String>();
+            lruHandler.load();
+            
+            long maxSize = -1; // Default
+            try {
+                maxSize = Long.parseLong(JNLPRuntime.getConfiguration().getProperty("deployment.cache.max.size"));
+            } catch (NumberFormatException nfe) {
+            }
+            
+            maxSize = maxSize << 20; // Convert from megabyte to byte (Negative values will be considered unlimited.)
+            long curSize = 0;
+
+            for (Entry<String, String> e : lruHandler.getLRUSortedEntries()) {
+                // Check if the item is contained in cacheOrder.
+                final String key = e.getKey();
+                final String value = e.getValue();
+
+                if (value != null) {
+                    File file = new File(value);
+                    PropertiesFile pf = new PropertiesFile(new File(value + ".info"));
+                    boolean delete = Boolean.parseBoolean(pf.getProperty("delete"));
+
+                    /*
+                     * This will get me the root directory specific to this cache item.
+                     * Example:
+                     *  cacheDir = /home/user1/.icedtea/cache
+                     *  file.getPath() = /home/user1/.icedtea/cache/0/http/www.example.com/subdir/a.jar
+                     *  rStr first becomes: /0/http/www.example.com/subdir/a.jar
+                     *  then rstr becomes: /home/user1/.icedtea/cache/0
+                     */
+                    String rStr = file.getPath().substring(cacheDir.length());
+                    rStr = cacheDir + rStr.substring(0, rStr.indexOf(File.separatorChar, 1));
+                    long len = file.length();
+
+                    if (keep.contains(file.getPath().substring(rStr.length()))) {
+                        lruHandler.removeEntry(key);
+                        continue;
+                    }
+                    
+                    /*
+                     * we remove entries from our lru if any of the following condition is met.
+                     * Conditions:
+                     *  - delete: file has been marked for deletion.
+                     *  - !file.isFile(): if someone tampered with the directory, file doesn't exist.
+                     *  - maxSize >= 0 && curSize + len > maxSize: If a limit was set and the new size
+                     *  on disk would exceed the maximum size.
+                     */
+                    if (delete || !file.isFile() || (maxSize >= 0 && curSize + len > maxSize)) {
+                        lruHandler.removeEntry(key);
+                        remove.add(rStr);
+                    } else {
+                        curSize += len;
+                        keep.add(file.getPath().substring(rStr.length()));
+
+                        for (File f : file.getParentFile().listFiles()) {
+                            if (!(f.equals(file) || f.equals(pf.getStoreFile()))){
+                                try {
+                                    FileUtils.recursiveDelete(f, f);
+                                } catch (IOException e1) {
+                                    e1.printStackTrace();
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    lruHandler.removeEntry(key);
+                }
+            }
+            lruHandler.store();
+
+            /*
+             * FIXME: if cacheDir is for example $USER_HOME and they have a folder called http
+             * and/or https. These would get removed.
+             */
+            remove.add(cacheDir + File.separator + "http");
+            remove.add(cacheDir + File.separator + "https");
+
+            removeSetOfDirectories(remove);
+
+        }
+    }
+
+    private static void removeSetOfDirectories(Set<String> remove) {
+        for (String s : remove) {
+            File f = new File(s);
+            try {
+                FileUtils.recursiveDelete(f, f);
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    /**
+     * Lock the property file and add it to our pool of locks.
+     * 
+     * @param properties Property file to lock.
+     */
+    public static void lockFile(PropertiesFile properties) {
+        String storeFilePath = properties.getStoreFile().getPath();
+        try {
+            propertiesLockPool.put(storeFilePath, FileUtils.getFileLock(storeFilePath, false, true));
+        } catch (OverlappingFileLockException e) {
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Unlock the property file and remove it from our pool. Nothing happens if
+     * it wasn't locked.
+     * 
+     * @param properties Property file to unlock.
+     */
+    public static void unlockFile(PropertiesFile properties) {
+        File storeFile = properties.getStoreFile();
+        FileLock fl = propertiesLockPool.get(storeFile.getPath());
+        try {
+            if (fl == null) return;
+            fl.release();
+            fl.channel().close();
+            propertiesLockPool.remove(storeFile.getPath());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java	(revision 403)
@@ -0,0 +1,316 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.net.*;
+import java.util.*;
+import java.util.List;
+import javax.swing.*;
+import javax.swing.Timer;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * Show the progress of downloads.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.3 $
+ */
+public class DefaultDownloadIndicator implements DownloadIndicator {
+
+    // todo: rewrite this to cut down on size/complexity; smarter
+    // panels (JList, renderer) understand resources instead of
+    // nested panels and grid-bag mess.
+
+    // todo: fix bug where user closes download box and it
+    // never(?) reappears.
+
+    // todo: UI for user to cancel/restart download
+
+    // todo: this should be synchronized at some point but conflicts
+    // aren't very likely.
+
+    private static String downloading = R("CDownloading");
+    private static String complete = R("CComplete");
+
+    /** time to wait after completing but before window closes */
+    private static final int CLOSE_DELAY = 750;
+
+    /** the display window */
+    private static JFrame frame;
+
+    /** shared constraint */
+    static GridBagConstraints vertical;
+    static GridBagConstraints verticalIndent;
+    static {
+        vertical = new GridBagConstraints();
+        vertical.gridwidth = GridBagConstraints.REMAINDER;
+        vertical.weightx = 1.0;
+        vertical.fill = GridBagConstraints.HORIZONTAL;
+        vertical.anchor = GridBagConstraints.WEST;
+
+        verticalIndent = (GridBagConstraints) vertical.clone();
+        verticalIndent.insets = new Insets(0, 10, 3, 0);
+    }
+
+    /**
+     * Return the update rate.
+     */
+    public int getUpdateRate() {
+        return 150; //ms
+    }
+
+    /**
+     * Return the initial delay before obtaining a listener.
+     */
+    public int getInitialDelay() {
+        return 300; //ms
+    }
+
+    /**
+     * Return a download service listener that displays the progress
+     * in a shared download info window.
+     *
+     * @param app the downloading application, or null if N/A
+     * @param downloadName name identifying the download to the user
+     * @param resources initial urls to display (not required)
+     */
+    public DownloadServiceListener getListener(ApplicationInstance app, String downloadName, URL resources[]) {
+        DownloadPanel result = new DownloadPanel(downloadName);
+
+        if (frame == null) {
+            frame = new JFrame(downloading + "...");
+            frame.getContentPane().setLayout(new GridBagLayout());
+        }
+
+        if (resources != null)
+            for (int i = 0; i < resources.length; i++)
+                result.addProgressPanel(resources[i], null);
+
+        frame.getContentPane().add(result, vertical);
+        frame.pack();
+
+        if (!frame.isVisible()) {
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration());
+            Dimension screen = new Dimension(screenSize.width - insets.left,
+                    screenSize.height - insets.top);
+            frame.setLocation(screen.width - frame.getWidth(),
+                              screen.height - frame.getHeight());
+        }
+
+        frame.setVisible(true);
+
+        return result;
+    }
+
+    /**
+     * Remove a download service listener that was obtained by
+     * calling the getDownloadListener method from the shared
+     * download info window.
+     */
+    public void disposeListener(final DownloadServiceListener listener) {
+        if (!(listener instanceof DownloadPanel))
+            return;
+
+        ActionListener hider = new ActionListener() {
+            public void actionPerformed(ActionEvent evt) {
+                if (frame.getContentPane().getComponentCount() == 1)
+                    frame.setVisible(false);
+
+                frame.getContentPane().remove((DownloadPanel) listener);
+                frame.pack();
+            }
+        };
+
+        Timer timer = new Timer(CLOSE_DELAY, hider);
+        timer.setRepeats(false);
+        timer.start();
+    }
+
+    /**
+     * Groups the url progress in a panel.
+     */
+    static class DownloadPanel extends JPanel implements DownloadServiceListener {
+
+        /** the download name */
+        private String downloadName;
+
+        /** Downloading part: */
+        private JLabel header = new JLabel();
+
+        /** list of URLs being downloaded */
+        private List<URL> urls = new ArrayList<URL>();
+
+        /** list of ProgressPanels */
+        private List<ProgressPanel> panels = new ArrayList<ProgressPanel>();
+
+        /**
+         * Create a new download panel for with the specified download
+         * name.
+         */
+        protected DownloadPanel(String downloadName) {
+            setLayout(new GridBagLayout());
+
+            this.downloadName = downloadName;
+            this.add(header, vertical);
+            header.setFont(header.getFont().deriveFont(Font.BOLD));
+
+            setOverallPercent(0);
+        }
+
+        /**
+         * Add a ProgressPanel for a URL.
+         */
+        protected void addProgressPanel(URL url, String version) {
+            if (!urls.contains(url)) {
+                ProgressPanel panel = new ProgressPanel(url, version);
+
+                add(panel, verticalIndent);
+                frame.pack();
+
+                urls.add(url);
+                panels.add(panel);
+            }
+        }
+
+        /**
+         * Update the download progress of a url.
+         */
+        protected void update(final URL url, final String version,
+                              final long readSoFar, final long total,
+                              final int overallPercent) {
+            Runnable r = new Runnable() {
+                public void run() {
+                    if (!urls.contains(url))
+                        addProgressPanel(url, version);
+
+                    setOverallPercent(overallPercent);
+
+                    ProgressPanel panel = panels.get(urls.indexOf(url));
+                    panel.setProgress(readSoFar, total);
+                    panel.repaint();
+                }
+            };
+            SwingUtilities.invokeLater(r);
+        }
+
+        /**
+         * Sets the overall percent completed.
+         */
+        public void setOverallPercent(int percent) {
+            // don't get whole string from resource and sub in
+            // values because it'll be doing a MessageFormat for
+            // each update.
+            header.setText(downloading + " " + downloadName + ": " + percent + "% " + complete + ".");
+        }
+
+        /**
+         * Called when a download failed.
+         */
+        public void downloadFailed(URL url, String version) {
+            update(url, version, -1, -1, -1);
+        }
+
+        /**
+         * Called when a download has progressed.
+         */
+        public void progress(URL url, String version, long readSoFar, long total, int overallPercent) {
+            update(url, version, readSoFar, total, overallPercent);
+        }
+
+        /**
+         * Called when an archive is patched.
+         */
+        public void upgradingArchive(URL url, String version, int patchPercent, int overallPercent) {
+            update(url, version, patchPercent, 100, overallPercent);
+        }
+
+        /**
+         * Called when a download is being validated.
+         */
+        public void validating(URL url, String version, long entry, long total, int overallPercent) {
+            update(url, version, entry, total, overallPercent);
+        }
+
+    };
+
+    /**
+     * A progress bar with the URL next to it.
+     */
+    static class ProgressPanel extends JPanel {
+        private JPanel bar = new JPanel();
+
+        private long total;
+        private long readSoFar;
+
+        ProgressPanel(URL url, String version) {
+            JLabel location = new JLabel(" " + url.getHost() + "/" + url.getFile());
+
+            bar.setMinimumSize(new Dimension(80, 15));
+            bar.setPreferredSize(new Dimension(80, 15));
+            bar.setOpaque(false);
+
+            setLayout(new GridBagLayout());
+
+            GridBagConstraints gbc = new GridBagConstraints();
+            gbc.weightx = 0.0;
+            gbc.fill = GridBagConstraints.NONE;
+            gbc.gridwidth = GridBagConstraints.RELATIVE;
+            add(bar, gbc);
+
+            gbc.insets = new Insets(0, 3, 0, 0);
+            gbc.weightx = 1.0;
+            gbc.fill = GridBagConstraints.HORIZONTAL;
+            gbc.gridwidth = GridBagConstraints.REMAINDER;
+            gbc.anchor = GridBagConstraints.WEST;
+            add(location, gbc);
+        }
+
+        public void setProgress(long readSoFar, long total) {
+            this.readSoFar = readSoFar;
+            this.total = total;
+        }
+
+        public void paintComponent(Graphics g) {
+            super.paintComponent(g);
+
+            int x = bar.getX();
+            int y = bar.getY();
+            int h = bar.getHeight();
+            int w = bar.getWidth();
+
+            if (readSoFar <= 0 || total <= 0) {
+                // make barber pole
+            } else {
+                double progress = (double) readSoFar / (double) total;
+                int divide = (int) (w * progress);
+
+                g.setColor(Color.white);
+                g.fillRect(x, y, w, h);
+                g.setColor(Color.blue);
+                g.fillRect(x + 1, y + 1, divide - 1, h - 1);
+            }
+        }
+    };
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DirectoryNode.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DirectoryNode.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DirectoryNode.java	(revision 403)
@@ -0,0 +1,167 @@
+/* DirectoryNode.java -- Structure for maintaining the cache directory tree.
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+package net.sourceforge.jnlp.cache;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class DirectoryNode {
+    private String name;
+    private File path;
+    private ArrayList<DirectoryNode> childNodes;
+    private DirectoryNode parent = null;
+    private File infoFile;
+
+    /**
+     * Create a new instance of DirectoryNode.
+     * 
+     * @param name Name representing this node.
+     * @param absPathToNode Absolute path to this node given as a String.
+     * @param parent The parent node.
+     */
+    public DirectoryNode(String name, String absPathToNode, DirectoryNode parent) {
+        this(name, new File(absPathToNode), parent);
+    }
+
+    /**
+     * Create a new instance of DirectoryNode.
+     * 
+     * @param name Name representing this node.
+     * @param absPathToNode Absolute path to this node as a File.
+     * @param parent The parent node.
+     */
+    public DirectoryNode(String name, File absPathToNode, DirectoryNode parent) {
+        this(name, absPathToNode, null, parent);
+    }
+
+    /**
+     * Create a new instance of DirectoryNode.
+     * 
+     * @param name Name representing this node.
+     * @param absPathToNode Absolute path to this node given as a File.
+     * @param childNodes List of children nodes.
+     * @param parent The parent node.
+     */
+    public DirectoryNode(String name, File absPathToNode, ArrayList<DirectoryNode> childNodes, DirectoryNode parent) {
+        this.name = name;
+        this.path = absPathToNode;
+        this.childNodes = childNodes;
+        if (this.childNodes == null)
+            this.childNodes = new ArrayList<DirectoryNode>();
+        this.parent = parent;
+        if (!isDir())
+            this.infoFile = new File(this.getFile().getAbsolutePath().concat(".info"));
+    }
+
+    /**
+     * Append the given node to the list of child nodes.
+     * 
+     * @param node Node to be appended.
+     */
+    public void addChild(DirectoryNode node) {
+        try {
+            childNodes.add(node);
+        } catch (NullPointerException e) {
+            this.childNodes = new ArrayList<DirectoryNode>();
+            this.childNodes.add(node);
+        }
+    }
+
+    /**
+     * Removes the node specified.
+     * 
+     * @param node Node to be removed from the list of children
+     * @return true if this list of children contained the specified element
+     */
+    public boolean removeChild(DirectoryNode node) {
+        return this.childNodes.remove(node);
+    }
+
+    /**
+     * Retrieve the name of this node.
+     * 
+     * @return Name of this node.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    public String toString() {
+        return this.name;
+    }
+
+    /**
+     * Retrieve the file associated with this node.
+     * 
+     * @return File that is associated with this node.
+     */
+    public File getFile() {
+        return path;
+    }
+
+    /**
+     * Retrieve the parent node.
+     * 
+     * @return DirectoryNode representing the parent of the current node.
+     */
+    public DirectoryNode getParent() {
+        return parent;
+    }
+
+    /**
+     * Retrieves the list of child nodes.
+     * 
+     * @return ArrayList of type DirectoryNode containing all the child nodes.
+     */
+    public ArrayList<DirectoryNode> getChildren() {
+        return this.childNodes;
+    }
+
+    /**
+     * Check if this node is a directory.
+     * 
+     * @return True if node is directory.
+     */
+    public boolean isDir() {
+        return path.isDirectory();
+    }
+
+    public File getInfoFile() {
+        return this.infoFile;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DownloadIndicator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DownloadIndicator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/DownloadIndicator.java	(revision 403)
@@ -0,0 +1,83 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import java.net.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * A DownloadIndicator creates DownloadServiceListeners that are
+ * notified of resources being transferred and their progress.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.8 $
+ */
+public interface DownloadIndicator {
+
+    /**
+     * Return a download service listener that displays the progress
+     * of downloading resources.  Update messages may be reported
+     * for URLs that are not included initially.<p>
+     *
+     * Progress messages are sent as if the DownloadServiceListener
+     * were listening to a DownloadService request.  The listener
+     * will receive progress messages from time to time during the
+     * download. <p>
+     *
+     * @param app JNLP application downloading the files, or null if not applicable
+     * @param downloadName name identifying the download to the user
+     * @param resources initial urls to display, empty if none known at start
+     */
+    public DownloadServiceListener getListener(ApplicationInstance app,
+                                               String downloadName,
+                                               URL resources[]);
+
+    /**
+     * Indicates that a download service listener that was obtained
+     * from the getDownloadListener method will no longer be used.
+     * This method can be used to ensure that progress dialogs are
+     * properly removed once a particular download is finished.
+     *
+     * @param listener the listener that is no longer in use
+     */
+    public void disposeListener(DownloadServiceListener listener);
+
+    /**
+     * Return the desired time in milliseconds between updates.
+     * Updates are not guarenteed to occur based on this value; for
+     * example, they may occur based on the download percent or some
+     * other factor.
+     *
+     * @return rate in milliseconds, must be &gt;= 0
+     */
+    public int getUpdateRate();
+
+    /**
+     * Return a time in milliseconds to wait for a download to
+     * complete before obtaining a listener for the download.  This
+     * value can be used to skip lengthy operations, such as
+     * initializing a GUI, for downloads that complete quickly.  The
+     * getListener method is not called if the download completes
+     * in less time than the returned delay.
+     *
+     * @return delay in milliseconds, must be &gt;= 0
+     */
+    public int getInitialDelay();
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/Resource.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/Resource.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/Resource.java	(revision 403)
@@ -0,0 +1,297 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.util.*;
+
+/**
+ * Information about a single resource to download.
+ * This class tracks the downloading of various resources of a
+ * JNLP file to local files.  It can be used to download icons,
+ * jnlp and extension files, jars, and jardiff files using the
+ * version based protocol or any file using the basic download
+ * protocol.<p>
+ *
+ * Resources can be put into download groups by specifying a part
+ * name for the resource.  The resource tracker can also be
+ * configured to prefetch resources, which are downloaded in the
+ * order added to the media tracker.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.9 $
+ */
+public class Resource {
+
+    // todo: fix resources to handle different versions
+
+    // todo: IIRC, any resource is checked for being up-to-date
+    // only once, regardless of UpdatePolicy.  verify and fix.
+
+    /** status bits */
+    public static final int UNINITIALIZED = 0;
+    public static final int CONNECT = 1;
+    public static final int CONNECTING = 2;
+    public static final int CONNECTED = 4;
+    public static final int DOWNLOAD = 8;
+    public static final int DOWNLOADING = 16;
+    public static final int DOWNLOADED = 32;
+    public static final int ERROR = 64;
+    public static final int STARTED = 128; // enqueued or being worked on
+
+    /** list of weak references of resources currently in use */
+    private static WeakList<Resource> resources = new WeakList<Resource>();
+
+    /** weak list of trackers monitoring this resource */
+    private WeakList<ResourceTracker> trackers = new WeakList<ResourceTracker>();
+
+    /** the remote location of the resource */
+    URL location;
+
+    /** the location to use when downloading */
+    private URL downloadLocation;
+
+    /** the local file downloaded to */
+    File localFile;
+
+    /** the requested version */
+    Version requestVersion;
+
+    /** the version downloaded from server */
+    Version downloadVersion;
+
+    /** amount in bytes transferred */
+    long transferred = 0;
+
+    /** total size of the resource, or -1 if unknown */
+    long size = -1;
+
+    /** the status of the resource */
+    int status = UNINITIALIZED;
+
+    /** Update policy for this resource */
+    UpdatePolicy updatePolicy;
+
+    /**
+     * Create a resource.
+     */
+    private Resource(URL location, Version requestVersion, UpdatePolicy updatePolicy) {
+        this.location = location;
+        this.downloadLocation = location;
+        this.requestVersion = requestVersion;
+        this.updatePolicy = updatePolicy;
+    }
+
+    /**
+     * Return a shared Resource object representing the given
+     * location and version.
+     */
+    public static Resource getResource(URL location, Version requestVersion, UpdatePolicy updatePolicy) {
+        synchronized (resources) {
+            Resource resource = new Resource(location, requestVersion, updatePolicy);
+
+            int index = resources.indexOf(resource);
+            if (index >= 0) { // return existing object
+                Resource result = resources.get(index);
+                if (result != null)
+                    return result;
+            }
+
+            resources.add(resource);
+            resources.trimToSize();
+
+            return resource;
+        }
+    }
+
+    /**
+     * Returns the remote location of the resource.
+     */
+    public URL getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the URL to use for downloading the resource. This can be
+     * different from the original location since it may use a different
+     * file name to support versioning and compression
+     * @return the url to use when downloading
+     */
+    public URL getDownloadLocation() {
+        return downloadLocation;
+    }
+
+    /**
+     * Set the url to use for downloading the resource
+     * @param location
+     */
+    public void setDownloadLocation(URL location) {
+        downloadLocation = location;
+    }
+
+    /**
+     * Returns the tracker that first created or monitored the
+     * resource, or null if no trackers are monitoring the resource.
+     */
+    ResourceTracker getTracker() {
+        synchronized (trackers) {
+            List<ResourceTracker> t = trackers.hardList();
+            if (t.size() > 0)
+                return t.get(0);
+
+            return null;
+        }
+    }
+
+    /**
+     * Returns true if any of the specified flags are set.
+     */
+    public boolean isSet(int flag) {
+        if (flag == UNINITIALIZED)
+            return status == UNINITIALIZED;
+        else
+            return (status & flag) != 0;
+    }
+
+    /**
+     * Returns the update policy for this resource
+     *
+     * @return The update policy
+     */
+    public UpdatePolicy getUpdatePolicy() {
+        return this.updatePolicy;
+    }
+
+    /**
+     * Returns a human-readable status string.
+     */
+    private String getStatusString(int flag) {
+        StringBuffer result = new StringBuffer();
+
+        if (flag == 0)
+            result.append("<> ");
+        if ((flag & CONNECT) != 0)
+            result.append("CONNECT ");
+        if ((flag & CONNECTING) != 0)
+            result.append("CONNECTING ");
+        if ((flag & CONNECTED) != 0)
+            result.append("CONNECTED ");
+        if ((flag & DOWNLOAD) != 0)
+            result.append("DOWNLOAD ");
+        if ((flag & DOWNLOADING) != 0)
+            result.append("DOWNLOADING ");
+        if ((flag & DOWNLOADED) != 0)
+            result.append("DOWNLOADED ");
+        if ((flag & ERROR) != 0)
+            result.append("ERROR ");
+        if ((flag & STARTED) != 0)
+            result.append("STARTED ");
+
+        return result.deleteCharAt(result.length() - 1).toString();
+    }
+
+    /**
+     * Changes the status by clearing the flags in the first
+     * parameter and setting the flags in the second.  This method
+     * is synchronized on this resource.
+     */
+    public void changeStatus(int clear, int add) {
+        int orig = 0;
+
+        synchronized (this) {
+            orig = status;
+
+            this.status &= ~clear;
+            this.status |= add;
+        }
+
+        if (JNLPRuntime.isDebug())
+            if (status != orig) {
+                System.out.print("Status: " + getStatusString(status));
+                if ((status & ~orig) != 0)
+                    System.out.print(" +(" + getStatusString(status & ~orig) + ")");
+                if ((~status & orig) != 0)
+                    System.out.print(" -(" + getStatusString(~status & orig) + ")");
+                System.out.println(" @ " + location.getPath());
+            }
+    }
+
+    /**
+     * Removes the tracker to the list of trackers monitoring this
+     * resource.
+     */
+    public void removeTracker(ResourceTracker tracker) {
+        synchronized (trackers) {
+            trackers.remove(tracker);
+            trackers.trimToSize();
+        }
+    }
+
+    /**
+     * Adds the tracker to the list of trackers monitoring this
+     * resource.
+     */
+    public void addTracker(ResourceTracker tracker) {
+        synchronized (trackers) {
+            // prevent GC between contains and add
+            List<ResourceTracker> t = trackers.hardList();
+            if (!t.contains(tracker))
+                trackers.add(tracker);
+
+            trackers.trimToSize();
+        }
+    }
+
+    /**
+     * Instructs the trackers monitoring this resource to fire a
+     * download event.
+     */
+    protected void fireDownloadEvent() {
+        List<ResourceTracker> send;
+
+        synchronized (trackers) {
+            send = trackers.hardList();
+        }
+
+        for (int i = 0; i < send.size(); i++) {
+            ResourceTracker rt = send.get(i);
+            rt.fireDownloadEvent(this);
+        }
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof Resource) {
+            // this prevents the URL handler from looking up the IP
+            // address and doing name resolution; much faster so less
+            // time spent in synchronized addResource determining if
+            // Resource is already in a tracker, and better for offline
+            // mode on some OS.
+            return CacheUtil.urlEquals(location, ((Resource) other).location);
+        }
+        return false;
+    }
+
+    public String toString() {
+        return "location=" + location.toString() + " state=" + getStatusString(status);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceTracker.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceTracker.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceTracker.java	(revision 403)
@@ -0,0 +1,1130 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Pack200;
+import java.util.jar.Pack200.Unpacker;
+import java.util.zip.GZIPInputStream;
+
+import net.sourceforge.jnlp.DownloadOptions;
+import net.sourceforge.jnlp.Version;
+import net.sourceforge.jnlp.event.DownloadEvent;
+import net.sourceforge.jnlp.event.DownloadListener;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.WeakList;
+
+/**
+ * This class tracks the downloading of various resources of a
+ * JNLP file to local files in the cache.  It can be used to
+ * download icons, jnlp and extension files, jars, and jardiff
+ * files using the version based protocol or any file using the
+ * basic download protocol (jardiff and version not implemented
+ * yet).<p>
+ *
+ * The resource tracker can be configured to prefetch resources,
+ * which are downloaded in the order added to the media
+ * tracker.<p>
+ *
+ * Multiple threads are used to download and cache resources that
+ * are actively being waited for (blocking a caller) or those that
+ * have been started downloading by calling the startDownload
+ * method.  Resources that are prefetched are downloaded one at a
+ * time and only if no other trackers have requested downloads.
+ * This allows the tracker to start downloading many items without
+ * using many system resources, but still quickly download items
+ * as needed.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.22 $
+ */
+public class ResourceTracker {
+
+    // todo: use event listener arrays instead of lists
+
+    // todo: see if there is a way to set the socket options just
+    // for use by the tracker so checks for updates don't hang for
+    // a long time.
+
+    // todo: ability to restart/retry a hung download
+
+    // todo: move resource downloading/processing code into Resource
+    // class, threading stays in ResourceTracker
+
+    // todo: get status method? and some way to convey error status
+    // to the caller.
+
+    // todo: might make a tracker be able to download more than one
+    // version of a resource, but probably not very useful.
+
+    // defines
+    //    ResourceTracker.Downloader (download threads)
+
+    // separately locks on (in order of aquire order, ie, sync on prefetch never syncs on lock):
+    //   lock, prefetch, this.resources, each resource, listeners
+
+    /** notified on initialization or download of a resource */
+    private static final Object lock = new Object(); // used to lock static structures
+
+    // shortcuts
+    private static final int UNINITIALIZED = Resource.UNINITIALIZED;
+    private static final int CONNECT = Resource.CONNECT;
+    private static final int CONNECTING = Resource.CONNECTING;
+    private static final int CONNECTED = Resource.CONNECTED;
+    private static final int DOWNLOAD = Resource.DOWNLOAD;
+    private static final int DOWNLOADING = Resource.DOWNLOADING;
+    private static final int DOWNLOADED = Resource.DOWNLOADED;
+    private static final int ERROR = Resource.ERROR;
+    private static final int STARTED = Resource.STARTED;
+
+    /** max threads */
+    private static final int maxThreads = 5;
+
+    /** running threads */
+    private static int threads = 0;
+
+    /** weak list of resource trackers with resources to prefetch */
+    private static WeakList<ResourceTracker> prefetchTrackers =
+            new WeakList<ResourceTracker>();
+
+    /** resources requested to be downloaded */
+    private static ArrayList<Resource> queue = new ArrayList<Resource>();
+
+    private static ConcurrentHashMap<Resource, DownloadOptions> downloadOptions =
+        new ConcurrentHashMap<Resource, DownloadOptions>();
+
+    /** resource trackers threads are working for (used for load balancing across multi-tracker downloads) */
+    private static ArrayList<ResourceTracker> active =
+            new ArrayList<ResourceTracker>(); //
+
+    /** the resources known about by this resource tracker */
+    private List<Resource> resources = new ArrayList<Resource>();
+
+    /** download listeners for this tracker */
+    private List<DownloadListener> listeners = new ArrayList<DownloadListener>();
+
+    /** whether to download parts before requested */
+    private boolean prefetch;
+
+    /**
+     * Creates a resource tracker that does not prefetch resources.
+     */
+    public ResourceTracker() {
+        this(false);
+    }
+
+    /**
+     * Creates a resource tracker.
+     *
+     * @param prefetch whether to download resources before requested.
+     */
+    public ResourceTracker(boolean prefetch) {
+        this.prefetch = prefetch;
+
+        if (prefetch) {
+            synchronized (prefetchTrackers) {
+                prefetchTrackers.add(this);
+                prefetchTrackers.trimToSize();
+            }
+        }
+    }
+
+    /**
+     * Add a resource identified by the specified location and
+     * version.  The tracker only downloads one version of a given
+     * resource per instance (ie cannot download both versions 1 and
+     * 2 of a resource in the same tracker).
+     *
+     * @param location the location of the resource
+     * @param version the resource version
+     * @param updatePolicy whether to check for updates if already in cache
+     */
+    public void addResource(URL location, Version version, DownloadOptions options, UpdatePolicy updatePolicy) {
+        if (location == null)
+            throw new IllegalArgumentException("location==null");
+
+        Resource resource = Resource.getResource(location, version, updatePolicy);
+        boolean downloaded = false;
+
+        synchronized (resources) {
+            if (resources.contains(resource))
+                return;
+            resource.addTracker(this);
+            resources.add(resource);
+        }
+
+        if (options == null) {
+            options = new DownloadOptions(false, false);
+        }
+        downloadOptions.put(resource, options);
+
+        // checkCache may take a while (loads properties file).  this
+        // should really be synchronized on resources, but the worst
+        // case should be that the resource will be updated once even
+        // if unnecessary.
+        downloaded = checkCache(resource, updatePolicy);
+
+        synchronized (lock) {
+            if (!downloaded)
+                if (prefetch && threads == 0) // existing threads do pre-fetch when queue empty
+                    startThread();
+        }
+    }
+
+    /**
+     * Removes a resource from the tracker.  This method is useful
+     * to allow memory to be reclaimed, but calling this method is
+     * not required as resources are reclaimed when the tracker is
+     * collected.
+     *
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public void removeResource(URL location) {
+        synchronized (resources) {
+            Resource resource = getResource(location);
+
+            if (resource != null) {
+                resources.remove(resource);
+                resource.removeTracker(this);
+            }
+
+            // should remove from queue? probably doesn't matter
+        }
+    }
+
+    /**
+     * Check the cache for a resource, and initialize the resource
+     * as already downloaded if found. <p>
+     *
+     * @param updatePolicy whether to check for updates if already in cache
+     * @return whether the resource are already downloaded
+     */
+    private boolean checkCache(Resource resource, UpdatePolicy updatePolicy) {
+        if (!CacheUtil.isCacheable(resource.location, resource.downloadVersion)) {
+            // pretend that they are already downloaded; essentially
+            // they will just 'pass through' the tracker as if they were
+            // never added (for example, not affecting the total download size).
+            synchronized (resource) {
+                resource.changeStatus(0, DOWNLOADED | CONNECTED | STARTED);
+            }
+            fireDownloadEvent(resource);
+            return true;
+        }
+
+        if (updatePolicy != UpdatePolicy.ALWAYS && updatePolicy != UpdatePolicy.FORCE) { // save loading entry props file
+            CacheEntry entry = new CacheEntry(resource.location, resource.downloadVersion);
+
+            if (entry.isCached() && !updatePolicy.shouldUpdate(entry)) {
+                if (JNLPRuntime.isDebug())
+                    System.out.println("not updating: " + resource.location);
+
+                synchronized (resource) {
+                    resource.localFile = CacheUtil.getCacheFile(resource.location, resource.downloadVersion);
+                    resource.size = resource.localFile.length();
+                    resource.transferred = resource.localFile.length();
+                    resource.changeStatus(0, DOWNLOADED | CONNECTED | STARTED);
+                }
+                fireDownloadEvent(resource);
+                return true;
+            }
+        }
+
+        if (updatePolicy == UpdatePolicy.FORCE) { // ALWAYS update
+            // When we are "always" updating, we update for each instance. Reset resource status.
+            resource.changeStatus(Integer.MAX_VALUE, 0);
+        }
+
+        // may or may not be cached, but check update when connection
+        // is open to possibly save network communication time if it
+        // has to be downloaded, and allow this call to return quickly
+        return false;
+    }
+
+    /**
+     * Adds the listener to the list of objects interested in
+     * receivind DownloadEvents.<p>
+     *
+     * @param listener the listener to add.
+     */
+    public void addDownloadListener(DownloadListener listener) {
+        synchronized (listeners) {
+            if (!listeners.contains(listener))
+                listeners.add(listener);
+        }
+    }
+
+    /**
+     * Removes a download listener.
+     *
+     * @param listener the listener to remove.
+     */
+    public void removeDownloadListener(DownloadListener listener) {
+        synchronized (listeners) {
+            listeners.remove(listener);
+        }
+    }
+
+    /**
+     * Fires the download event corresponding to the resource's
+     * state.  This method is typicall called by the Resource itself
+     * on each tracker that is monitoring the resource.  Do not call
+     * this method with any locks because the listeners may call
+     * back to this ResourceTracker.
+     */
+    protected void fireDownloadEvent(Resource resource) {
+        DownloadListener l[] = null;
+        synchronized (listeners) {
+            l = listeners.toArray(new DownloadListener[0]);
+        }
+
+        int status;
+        synchronized (resource) {
+            status = resource.status;
+        }
+
+        DownloadEvent event = new DownloadEvent(this, resource);
+        for (int i = 0; i < l.length; i++) {
+            if (0 != ((ERROR | DOWNLOADED) & status))
+                l[i].downloadCompleted(event);
+            else if (0 != (DOWNLOADING & status))
+                l[i].downloadStarted(event);
+            else if (0 != (CONNECTING & status))
+                l[i].updateStarted(event);
+        }
+    }
+
+    /**
+     * Returns a URL pointing to the cached location of the
+     * resource, or the resource itself if it is a non-cacheable
+     * resource.<p>
+     *
+     * If the resource has not downloaded yet, the method will block
+     * until it has been transferred to the cache.<p>
+     *
+     * @param location the resource location
+     * @return the resource, or null if it could not be downloaded
+     * @throws IllegalArgumentException if the resource is not being tracked
+     * @see CacheUtil#isCacheable
+     */
+    public URL getCacheURL(URL location) {
+        try {
+            File f = getCacheFile(location);
+            if (f != null)
+                // TODO: Should be toURI().toURL()
+                return f.toURL();
+        } catch (MalformedURLException ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+        }
+
+        return location;
+    }
+
+    /**
+     * Returns a file containing the downloaded resource.  If the
+     * resource is non-cacheable then null is returned unless the
+     * resource is a local file (the original file is returned).<p>
+     *
+     * If the resource has not downloaded yet, the method will block
+     * until it has been transferred to the cache.<p>
+     *
+     * @param location the resource location
+     * @return a local file containing the resource, or null
+     * @throws IllegalArgumentException if the resource is not being tracked
+     * @see CacheUtil#isCacheable
+     */
+    public File getCacheFile(URL location) {
+        try {
+            Resource resource = getResource(location);
+            if (!resource.isSet(DOWNLOADED | ERROR))
+                waitForResource(location, 0);
+
+            if (resource.isSet(ERROR))
+                return null;
+
+            if (resource.localFile != null)
+                return resource.localFile;
+
+            if (location.getProtocol().equalsIgnoreCase("file")) {
+                File file = new File(location.getFile());
+                if (file.exists())
+                    return file;
+            }
+
+            return null;
+        } catch (InterruptedException ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            return null; // need an error exception to throw
+        }
+    }
+
+    /**
+     * Returns an input stream that reads the contents of the
+     * resource.  For non-cacheable resources, an InputStream that
+     * reads from the source location is returned.  Otherwise the
+     * InputStream reads the cached resource.<p>
+     *
+     * This method will block while the resource is downloaded to
+     * the cache.
+     *
+     * @throws IOException if there was an error opening the stream
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public InputStream getInputStream(URL location) throws IOException {
+        try {
+            Resource resource = getResource(location);
+            if (!resource.isSet(DOWNLOADED | ERROR))
+                waitForResource(location, 0);
+
+            if (resource.localFile != null)
+                return new FileInputStream(resource.localFile);
+
+            return resource.location.openStream();
+        } catch (InterruptedException ex) {
+            throw new IOException("wait was interrupted");
+        }
+    }
+
+    /**
+     * Wait for a group of resources to be downloaded and made
+     * available locally.
+     *
+     * @param urls the resources to wait for
+     * @param timeout the time in ms to wait before returning, 0 for no timeout
+     * @return whether the resources downloaded before the timeout
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public boolean waitForResources(URL urls[], long timeout) throws InterruptedException {
+        Resource resources[] = new Resource[urls.length];
+
+        synchronized (resources) {
+            // keep the lock so getResource doesn't have to aquire it each time
+            for (int i = 0; i < urls.length; i++)
+                resources[i] = getResource(urls[i]);
+        }
+
+        if (resources.length > 0)
+            return wait(resources, timeout);
+
+        return true;
+    }
+
+    /**
+     * Wait for a particular resource to be downloaded and made
+     * available.
+     *
+     * @param location the resource to wait for
+     * @param timeout the timeout, or 0 to wait until completed
+     * @return whether the resource downloaded before the timeout
+     * @throws InterruptedException if another thread interrupted the wait
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public boolean waitForResource(URL location, long timeout) throws InterruptedException {
+        return wait(new Resource[] { getResource(location) }, timeout);
+    }
+
+    /**
+     * Returns the number of bytes downloaded for a resource.
+     *
+     * @param location the resource location
+     * @return the number of bytes transferred
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public long getAmountRead(URL location) {
+        // not atomic b/c transferred is a long, but so what (each
+        // byte atomic? so probably won't affect anything...)
+        return getResource(location).transferred;
+    }
+
+    /**
+     * Returns whether a resource is available for use (ie, can be
+     * accessed with the getCacheFile method).
+     *
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public boolean checkResource(URL location) {
+        return getResource(location).isSet(DOWNLOADED | ERROR); // isSet atomic
+    }
+
+    /**
+     * Starts loading the resource if it is not already being
+     * downloaded or already cached.  Resources started downloading
+     * using this method may download faster than those prefetched
+     * by the tracker because the tracker will only prefetch one
+     * resource at a time to conserve system resources.
+     *
+     * @return true if the resource is already downloaded (or an error occurred)
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public boolean startResource(URL location) {
+        Resource resource = getResource(location);
+
+        return startResource(resource);
+    }
+
+    /**
+     * Sets the resource status to connect and download, and
+     * enqueues the resource if not already started.
+     *
+     * @return true if the resource is already downloaded (or an error occurred)
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    private boolean startResource(Resource resource) {
+        boolean enqueue = false;
+
+        synchronized (resource) {
+            if (resource.isSet(ERROR))
+                return true;
+
+            enqueue = !resource.isSet(STARTED);
+
+            if (!resource.isSet(CONNECTED | CONNECTING))
+                resource.changeStatus(0, CONNECT | STARTED);
+            if (!resource.isSet(DOWNLOADED | DOWNLOADING))
+                resource.changeStatus(0, DOWNLOAD | STARTED);
+
+            if (!resource.isSet(DOWNLOAD | CONNECT))
+                enqueue = false;
+        }
+
+        if (enqueue)
+            queueResource(resource);
+
+        return !enqueue;
+    }
+
+    /**
+     * Returns the number of total size in bytes of a resource, or
+     * -1 it the size is not known.
+     *
+     * @param location the resource location
+     * @return the number of bytes, or -1
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    public long getTotalSize(URL location) {
+        return getResource(location).size; // atomic
+    }
+
+    /**
+     * Start a new download thread if there are not too many threads
+     * already running.<p>
+     *
+     * Calls to this method should be synchronized on lock.
+     */
+    protected void startThread() {
+        if (threads < maxThreads) {
+            threads++;
+
+            Thread thread = new Thread(new Downloader());
+            thread.start();
+        }
+    }
+
+    /**
+     * A thread is ending, called by the thread itself.<p>
+     *
+     * Calls to this method should be synchronized.
+     */
+    private void endThread() {
+        threads--;
+
+        if (threads < 0) {
+            // this should never happen but try to recover
+            threads = 0;
+
+            if (queue.size() > 0) // if any on queue make sure a thread is running
+                startThread(); // look into whether this could create a loop
+
+            throw new RuntimeException("tracker threads < 0");
+        }
+
+        if (threads == 0) {
+            synchronized (prefetchTrackers) {
+                queue.trimToSize(); // these only accessed by threads so no sync needed
+                active.clear(); // no threads so no trackers actively downloading
+                active.trimToSize();
+                prefetchTrackers.trimToSize();
+            }
+        }
+    }
+
+    /**
+     * Add a resource to the queue and start a thread to download or
+     * initialize it.
+     */
+    private void queueResource(Resource resource) {
+        synchronized (lock) {
+            if (!resource.isSet(CONNECT | DOWNLOAD))
+                throw new IllegalArgumentException("Invalid resource state (resource: " + resource + ")");
+
+            queue.add(resource);
+            startThread();
+        }
+    }
+
+    /**
+     * Process the resource by either downloading it or initializing
+     * it.
+     */
+    private void processResource(Resource resource) {
+        boolean doConnect = false;
+        boolean doDownload = false;
+
+        synchronized (resource) {
+            if (resource.isSet(CONNECTING))
+                doConnect = true;
+        }
+        if (doConnect)
+            initializeResource(resource);
+
+        synchronized (resource) {
+            // return to queue if we just initalized but it still needs
+            // to download (not cached locally / out of date)
+            if (resource.isSet(DOWNLOAD)) // would be DOWNLOADING if connected before this method
+                queueResource(resource);
+
+            if (resource.isSet(DOWNLOADING))
+                doDownload = true;
+        }
+        if (doDownload)
+            downloadResource(resource);
+    }
+
+    /**
+     * Downloads a resource to a file, uncompressing it if required
+     *
+     * @param resource the resource to download
+     */
+    private void downloadResource(Resource resource) {
+        resource.fireDownloadEvent(); // fire DOWNLOADING
+
+        CacheEntry origEntry = new CacheEntry(resource.location, resource.downloadVersion); // This is where the jar file will be.
+        origEntry.lock();
+
+        try {
+            // create out second in case in does not exist
+            URL realLocation = resource.getDownloadLocation();
+            URLConnection con = realLocation.openConnection();
+            con.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip");
+
+            con.connect();
+
+            /*
+             * We dont really know what we are downloading. If we ask for
+             * foo.jar, the server might send us foo.jar.pack.gz or foo.jar.gz
+             * instead. So we save the file with the appropriate extension
+             */
+            URL downloadLocation = resource.location;
+
+            String contentEncoding = con.getContentEncoding();
+
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Downloading" + resource.location + " using " +
+                        realLocation + " (encoding : " + contentEncoding + ")");
+
+            }
+
+            boolean packgz = "pack200-gzip".equals(contentEncoding) ||
+                                realLocation.getPath().endsWith(".pack.gz");
+            boolean gzip = "gzip".equals(contentEncoding);
+
+            // It's important to check packgz first. If a stream is both
+            // pack200 and gz encoded, then con.getContentEncoding() could
+            // return ".gz", so if we check gzip first, we would end up
+            // treating a pack200 file as a jar file.
+            if (packgz) {
+                downloadLocation = new URL(downloadLocation.toString() + ".pack.gz");
+            } else if (gzip) {
+                downloadLocation = new URL(downloadLocation.toString() + ".gz");
+            }
+
+            File downloadLocationFile = CacheUtil.getCacheFile(downloadLocation, resource.downloadVersion);
+            CacheEntry downloadEntry = new CacheEntry(downloadLocation, resource.downloadVersion);
+            File finalFile = CacheUtil.getCacheFile(resource.location, resource.downloadVersion); // This is where extracted version will be, or downloaded file if not compressed.
+
+            if (!downloadEntry.isCurrent(con)) {
+                // Make sure we don't re-download the file. however it will wait as if it was downloading.
+                // (This is fine because file is not ready yet anyways)
+                byte buf[] = new byte[1024];
+                int rlen;
+
+                InputStream in = new BufferedInputStream(con.getInputStream());
+                OutputStream out = CacheUtil.getOutputStream(downloadLocation, resource.downloadVersion);
+
+                while (-1 != (rlen = in.read(buf))) {
+                    resource.transferred += rlen;
+                    out.write(buf, 0, rlen);
+                }
+
+                in.close();
+                out.close();
+
+                // explicitly close the URLConnection.
+                if (con instanceof HttpURLConnection)
+                    ((HttpURLConnection) con).disconnect();
+
+                /*
+                 * If the file was compressed, uncompress it.
+                 */
+                if (packgz) {
+                    downloadEntry.initialize(con);
+                    GZIPInputStream gzInputStream = new GZIPInputStream(new FileInputStream(CacheUtil
+                            .getCacheFile(downloadLocation, resource.downloadVersion)));
+                    InputStream inputStream = new BufferedInputStream(gzInputStream);
+
+                    JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(CacheUtil
+                            .getCacheFile(resource.location, resource.downloadVersion)));
+
+                    Unpacker unpacker = Pack200.newUnpacker();
+                    unpacker.unpack(inputStream, outputStream);
+
+                    outputStream.close();
+                    inputStream.close();
+                    gzInputStream.close();
+                } else if (gzip) {
+                    downloadEntry.initialize(con);
+                    GZIPInputStream gzInputStream = new GZIPInputStream(new FileInputStream(CacheUtil
+                            .getCacheFile(downloadLocation, resource.downloadVersion)));
+                    InputStream inputStream = new BufferedInputStream(gzInputStream);
+
+                    BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(CacheUtil
+                            .getCacheFile(resource.location, resource.downloadVersion)));
+
+                    while (-1 != (rlen = inputStream.read(buf))) {
+                        outputStream.write(buf, 0, rlen);
+                    }
+
+                    outputStream.close();
+                    inputStream.close();
+                    gzInputStream.close();
+                }
+            } else {
+                resource.transferred = downloadLocationFile.length();
+            }
+
+            if (!downloadLocationFile.getPath().equals(finalFile.getPath())) {
+                downloadEntry.markForDelete();
+                downloadEntry.store();
+            }
+
+            resource.changeStatus(DOWNLOADING, DOWNLOADED);
+            synchronized (lock) {
+                lock.notifyAll(); // wake up wait's to check for completion
+            }
+            resource.fireDownloadEvent(); // fire DOWNLOADED
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            resource.changeStatus(0, ERROR);
+            synchronized (lock) {
+                lock.notifyAll(); // wake up wait's to check for completion
+            }
+            resource.fireDownloadEvent(); // fire ERROR
+        } finally {
+            origEntry.unlock();
+        }
+    }
+
+    /**
+     * Open a URL connection and get the content length and other
+     * fields.
+     */
+    private void initializeResource(Resource resource) {
+        resource.fireDownloadEvent(); // fire CONNECTING
+
+        CacheEntry entry = new CacheEntry(resource.location, resource.requestVersion);
+        entry.lock();
+
+        try {
+            File localFile = CacheUtil.getCacheFile(resource.location, resource.downloadVersion);
+
+            // connect
+            URL finalLocation = findBestUrl(resource);
+            resource.setDownloadLocation(finalLocation);
+            URLConnection connection = finalLocation.openConnection(); // this won't change so should be okay unsynchronized
+            connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip");
+
+            int size = connection.getContentLength();
+            boolean current = CacheUtil.isCurrent(resource.location, resource.requestVersion, connection) && resource.getUpdatePolicy() != UpdatePolicy.FORCE;
+            if (!current) {
+                if (entry.isCached()) {
+                    entry.markForDelete();
+                    entry.store();
+                    // Old entry will still exist. (but removed at cleanup)
+                    localFile = CacheUtil.makeNewCacheFile(resource.location, resource.downloadVersion);
+                    CacheEntry newEntry = new CacheEntry(resource.location, resource.requestVersion);
+                    newEntry.lock();
+                    entry.unlock();
+                    entry = newEntry;
+                }
+            }
+
+            synchronized (resource) {
+                resource.localFile = localFile;
+                // resource.connection = connection;
+                resource.size = size;
+                resource.changeStatus(CONNECT | CONNECTING, CONNECTED);
+
+                // check if up-to-date; if so set as downloaded
+                if (current)
+                    resource.changeStatus(DOWNLOAD | DOWNLOADING, DOWNLOADED);
+            }
+
+            // update cache entry
+            if (!current)
+                entry.initialize(connection);
+
+            entry.setLastUpdated(System.currentTimeMillis());
+            entry.store();
+
+            synchronized (lock) {
+                lock.notifyAll(); // wake up wait's to check for completion
+            }
+            resource.fireDownloadEvent(); // fire CONNECTED
+
+            // explicitly close the URLConnection.
+            if (connection instanceof HttpURLConnection)
+                ((HttpURLConnection) connection).disconnect();
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            resource.changeStatus(0, ERROR);
+            synchronized (lock) {
+                lock.notifyAll(); // wake up wait's to check for completion
+            }
+            resource.fireDownloadEvent(); // fire ERROR
+        } finally {
+            entry.unlock();
+        }
+    }
+
+    /**
+     * Returns the best URL to use for downloading the resource
+     *
+     * @param resource the resource
+     * @return a URL or null
+     */
+    private URL findBestUrl(Resource resource) {
+        DownloadOptions options = downloadOptions.get(resource);
+        if (options == null) {
+            options = new DownloadOptions(false, false);
+        }
+
+        List<URL> urls = new ResourceUrlCreator(resource, options).getUrls();
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("All possible urls for " +
+                    resource.toString() + " : " + urls);
+        }
+        URL bestUrl = null;
+        for (int i = 0; i < urls.size(); i++) {
+            URL url = urls.get(i);
+            try {
+                URLConnection connection = url.openConnection();
+                connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip");
+                if (connection instanceof HttpURLConnection) {
+                    HttpURLConnection con = (HttpURLConnection)connection;
+                    int responseCode = con.getResponseCode();
+                    if (responseCode == -1 || responseCode < 200 || responseCode >= 300) {
+                        continue;
+                    }
+                }
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("best url for " + resource.toString() + " is " + url.toString());
+                }
+                bestUrl = url;
+                break;
+            } catch (IOException e) {
+                // continue
+            }
+        }
+
+        return bestUrl;
+    }
+
+    /**
+     * Pick the next resource to download or initialize.  If there
+     * are no more resources requested then one is taken from a
+     * resource tracker with prefetch enabled.<p>
+     *
+     * The resource state is advanced before it is returned
+     * (CONNECT-&gt;CONNECTING).<p>
+     *
+     * Calls to this method should be synchronized on lock.<p>
+     *
+     * @return the resource to initialize or download, or null
+     */
+    private static Resource selectNextResource() {
+        Resource result;
+
+        // pick from queue
+        result = selectByFlag(queue, CONNECT, ERROR); // connect but not error
+        if (result == null)
+            result = selectByFlag(queue, DOWNLOAD, ERROR | CONNECT | CONNECTING);
+
+        // remove from queue if found
+        if (result != null)
+            queue.remove(result);
+
+        // prefetch if nothing found so far and this is the last thread
+        if (result == null && threads == 1)
+            result = getPrefetch();
+
+        if (result == null)
+            return null;
+
+        synchronized (result) {
+            if (result.isSet(CONNECT)) {
+                result.changeStatus(CONNECT, CONNECTING);
+            } else if (result.isSet(DOWNLOAD)) {
+                // only download if *not* connecting, when done connecting
+                // select next will pick up the download part.  This makes
+                // all requested connects happen before any downloads, so
+                // the size is known as early as possible.
+                result.changeStatus(DOWNLOAD, DOWNLOADING);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns the next resource to be prefetched before
+     * requested.<p>
+     *
+     * Calls to this method should be synchronized on lock.<p>
+     */
+    private static Resource getPrefetch() {
+        Resource result = null;
+        Resource alternate = null;
+
+        // first find one to initialize
+        synchronized (prefetchTrackers) {
+            for (int i = 0; i < prefetchTrackers.size() && result == null; i++) {
+                ResourceTracker tracker = prefetchTrackers.get(i);
+                if (tracker == null)
+                    continue;
+
+                synchronized (tracker.resources) {
+                    result = selectByFlag(tracker.resources, UNINITIALIZED, ERROR);
+
+                    if (result == null && alternate == null)
+                        alternate = selectByFlag(tracker.resources, CONNECTED, ERROR | DOWNLOADED | DOWNLOADING | DOWNLOAD);
+                }
+            }
+        }
+
+        // if none to initialize, switch to download
+        if (result == null)
+            result = alternate;
+
+        if (result == null)
+            return null;
+
+        synchronized (result) {
+            ResourceTracker tracker = result.getTracker();
+            if (tracker == null)
+                return null; // GC of tracker happened between above code and here
+
+            // prevents startResource from putting it on queue since
+            // we're going to return it.
+            result.changeStatus(0, STARTED);
+
+            tracker.startResource(result);
+        }
+
+        return result;
+    }
+
+    /**
+     * Selects a resource from the source list that has the
+     * specified flag set.<p>
+     *
+     * Calls to this method should be synchronized on lock and
+     * source list.<p>
+     */
+    private static Resource selectByFlag(List<Resource> source, int flag,
+                                         int notflag) {
+        Resource result = null;
+        int score = Integer.MAX_VALUE;
+
+        for (int i = 0; i < source.size(); i++) {
+            Resource resource = source.get(i);
+            boolean selectable = false;
+
+            synchronized (resource) {
+                if (resource.isSet(flag) && !resource.isSet(notflag))
+                    selectable = true;
+            }
+
+            if (selectable) {
+                int activeCount = 0;
+
+                for (int j = 0; j < active.size(); j++)
+                    if (active.get(j) == resource.getTracker())
+                        activeCount++;
+
+                // try to spread out the downloads so that a slow host
+                // won't monopolize the downloads
+                if (activeCount < score) {
+                    result = resource;
+                    score = activeCount;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Return the resource matching the specified URL.
+     *
+     * @throws IllegalArgumentException if the resource is not being tracked
+     */
+    private Resource getResource(URL location) {
+        synchronized (resources) {
+            for (int i = 0; i < resources.size(); i++) {
+                Resource resource = resources.get(i);
+
+                if (CacheUtil.urlEquals(resource.location, location))
+                    return resource;
+            }
+        }
+
+        throw new IllegalArgumentException("Location does not specify a resource being tracked.");
+    }
+
+    /**
+     * Wait for some resources.
+     *
+     * @param resources the resources to wait for
+     * @param timeout the timeout, or 0 to wait until completed
+     * @returns true if the resources were downloaded or had errors,
+     * false if the timeout was reached
+     * @throws InterruptedException if another thread interrupted the wait
+     */
+    private boolean wait(Resource resources[], long timeout) throws InterruptedException {
+        long startTime = System.currentTimeMillis();
+
+        // start them downloading / connecting in background
+        for (int i = 0; i < resources.length; i++)
+            startResource(resources[i]);
+
+        // wait for completion
+        while (true) {
+            boolean finished = true;
+
+            synchronized (lock) {
+                // check for completion
+                for (int i = 0; i < resources.length; i++) {
+                    //NetX Deadlocking may be solved by removing this
+                    //synch block.
+                    synchronized (resources[i]) {
+                        if (!resources[i].isSet(DOWNLOADED | ERROR)) {
+                            finished = false;
+                            break;
+                        }
+                    }
+                }
+                if (finished)
+                    return true;
+
+                // wait
+                long waitTime = 0;
+
+                if (timeout > 0) {
+                    waitTime = timeout - (System.currentTimeMillis() - startTime);
+                    if (waitTime <= 0)
+                        return false;
+                }
+
+                lock.wait(waitTime);
+            }
+        }
+    }
+
+    // inner classes
+
+    /**
+     * This class downloads and initializes the queued resources.
+     */
+    private class Downloader implements Runnable {
+        Resource resource = null;
+
+        public void run() {
+            while (true) {
+                synchronized (lock) {
+                    // remove from active list, used for load balancing
+                    if (resource != null)
+                        active.remove(resource.getTracker());
+
+                    resource = selectNextResource();
+
+                    if (resource == null) {
+                        endThread();
+                        break;
+                    }
+
+                    // add to active list, used for load balancing
+                    active.add(resource.getTracker());
+                }
+
+                try {
+
+                    // Resource processing involves writing to files 
+                    // (cache entry trackers, the files themselves, etc.)
+                    // and it therefore needs to be privileged
+
+                    final Resource fResource = resource;
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                        public Void run() {
+                            processResource(fResource);                            
+                            return null;
+                        }
+                    });
+
+                } catch (Exception ex) {
+                    if (JNLPRuntime.isDebug())
+                        ex.printStackTrace();
+                }
+            }
+            // should have a finally in case some exception is thrown by
+            // selectNextResource();
+        }
+    };
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java	(revision 403)
@@ -0,0 +1,163 @@
+/* ResourceUrlCreator.java
+   Copyright (C) 2011 Red Hat, Inc
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.cache;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.sourceforge.jnlp.DownloadOptions;
+
+public class ResourceUrlCreator {
+
+    protected final Resource resource;
+    protected final DownloadOptions downloadOptions;
+
+    public ResourceUrlCreator(Resource resource, DownloadOptions downloadOptions) {
+        this.resource = resource;
+        this.downloadOptions = downloadOptions;
+    }
+
+    /**
+     * Returns a list of URLs that the resources might be downloadable from.
+     * The Resources may not be downloadable from any of them. The returned order is the order
+     * the urls should be attempted in.
+     * @return
+     */
+    public List<URL> getUrls() {
+        List<URL> urls = new LinkedList<URL>();
+        URL url = null;
+
+        if (downloadOptions.useExplicitPack() && downloadOptions.useExplicitVersion()) {
+            url = getUrl(resource, true, true);
+            if (url != null) {
+                urls.add(url);
+            }
+            url = getUrl(resource, false, true);
+            if (url != null) {
+                urls.add(url);
+            }
+            url = getUrl(resource, true, false);
+            if (url != null) {
+                urls.add(url);
+            }
+        } else if (downloadOptions.useExplicitPack()) {
+            url = getUrl(resource, true, false);
+            if (url != null) {
+                urls.add(url);
+            }
+        } else if (downloadOptions.useExplicitVersion()) {
+            url = getUrl(resource, false, true);
+            if (url != null) {
+                urls.add(url);
+            }
+        }
+
+        url = getVersionedUrlUsingQuery(resource);
+        urls.add(url);
+
+        urls.add(resource.getLocation());
+
+        return urls;
+    }
+
+    /**
+     * Returns a url for the resource.
+     * @param resource the resource
+     * @param usePack whether the URL should point to the pack200 file
+     * @param useVersion whether the URL should be modified to include the version
+     * @return a URL for the resource or null if an appropraite URL can not be found
+     */
+    protected URL getUrl(Resource resource, boolean usePack, boolean useVersion) {
+        if (!(usePack || useVersion)) {
+            throw new IllegalArgumentException("either pack200 or version required");
+        }
+
+        String location = resource.getLocation().toString();
+        int lastSlash = resource.getLocation().toString().lastIndexOf('/');
+        if (lastSlash == -1) {
+            return resource.getLocation();
+        }
+        String filename = location.substring(lastSlash + 1);
+        if (useVersion && resource.requestVersion != null) {
+            String parts[] = filename.split("\\.", 2);
+            String name = parts[0];
+            String extension = parts[1];
+            filename = name + "__V" + resource.requestVersion + "." + extension;
+        }
+        if (usePack) {
+            filename = filename + ".pack.gz";
+        }
+
+        location = location.substring(0, lastSlash + 1) + filename;
+        try {
+            URL newUrl = new URL(location);
+            return newUrl;
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the URL for a resource, relying on HTTP query for getting the
+     * right version
+     *
+     * @param resource the resource to get the url for
+     */
+    protected URL getVersionedUrlUsingQuery(Resource resource) {
+        String actualLocation = resource.getLocation().getProtocol() + "://"
+                + resource.getLocation().getHost();
+        if (resource.getLocation().getPort() != -1) {
+            actualLocation += ":" + resource.getLocation().getPort();
+        }
+        actualLocation += resource.getLocation().getPath();
+        if (resource.requestVersion != null
+                && resource.requestVersion.isVersionId()) {
+            actualLocation += "?version-id=" + resource.requestVersion;
+        }
+        URL versionedURL;
+        try {
+            versionedURL = new URL(actualLocation);
+        } catch (MalformedURLException e) {
+            return resource.getLocation();
+        }
+        return versionedURL;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/UpdatePolicy.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/UpdatePolicy.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/UpdatePolicy.java	(revision 403)
@@ -0,0 +1,76 @@
+// Copyright (C) 2002 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.cache;
+
+/**
+ * A policy that determines when a resource should be checked for
+ * an updated version.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.3 $
+ */
+public class UpdatePolicy {
+
+    // todo: implement session updating
+
+    // todo: doesn't seem to work in the same JVM, probably because
+    // Resource is being held by a tracker so it isn't collected;
+    // then next time a tracker adds the resource even if
+    // shouldUpdate==true it's state is already marked
+    // CONNECTED|DOWNLOADED.  Let the resource be collected or reset
+    // to UNINITIALIZED.
+
+    public static UpdatePolicy ALWAYS = new UpdatePolicy(0);
+    public static UpdatePolicy SESSION = new UpdatePolicy(-1);
+    public static UpdatePolicy FORCE = new UpdatePolicy(Long.MIN_VALUE);
+    public static UpdatePolicy NEVER = new UpdatePolicy(Long.MAX_VALUE);
+
+    private long timeDiff = -1;
+
+    /**
+     * Create a new update policy; this policy always updates the
+     * entry unless the shouldUpdate method is overridden.
+     */
+    public UpdatePolicy() {
+    }
+
+    /**
+     * Create an update policy that only checks a file for being
+     * updated if it has not been checked for longer than the
+     * specified time.
+     *
+     * @param timeDiff how long in ms until update needed
+     */
+    public UpdatePolicy(long timeDiff) {
+        this.timeDiff = timeDiff;
+    }
+
+    /**
+     * Returns whether the resource should be checked for being
+     * up-to-date.
+     */
+    public boolean shouldUpdate(CacheEntry entry) {
+        long updated = entry.getLastUpdated();
+        long current = System.currentTimeMillis();
+
+        if (current - updated >= timeDiff)
+            return true;
+        else
+            return false;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/package.html
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/package.html	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/cache/package.html	(revision 403)
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the JNLP cache.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/BasicValueValidators.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/BasicValueValidators.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/BasicValueValidators.java	(revision 403)
@@ -0,0 +1,278 @@
+/* BasicValueCheckers.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.config;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * Provides {@link ValueValidator} implementations for some common value types
+ *
+ * @see #getBooleanValidator()
+ * @see #getFilePathValidator()
+ * @see #getRangedIntegerValidator(int, int)
+ * @see #getStringValidator(String[])
+ * @see #getUrlValidator()
+ */
+public class BasicValueValidators {
+
+    /**
+     * Checks if a value is a valid boolean
+     */
+    private static class BooleanValidator implements ValueValidator {
+
+        @Override
+        public void validate(Object value) throws IllegalArgumentException {
+            Object possibleValue = value;
+
+            if (possibleValue instanceof String) {
+                String lower = ((String) possibleValue).toLowerCase(Locale.ENGLISH);
+                if (lower.equals(Boolean.TRUE.toString())
+                        || (lower.equals(Boolean.FALSE.toString()))) {
+                    possibleValue = Boolean.valueOf(lower);
+                }
+            }
+
+            if (!(possibleValue instanceof Boolean)) {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public String getPossibleValues() {
+            return R("VVPossibleBooleanValues", Boolean.TRUE.toString(), Boolean.FALSE.toString());
+        }
+    };
+
+    /**
+     * Checks if a value is a valid file path (not a valid file!). The actual
+     * file may or may not exist
+     */
+    private static class FilePathValidator implements ValueValidator {
+
+        @Override
+        public void validate(Object value) throws IllegalArgumentException {
+            if (value == null) {
+                return;
+            }
+
+            Object possibleValue = value;
+
+            if (!(possibleValue instanceof String)) {
+                throw new IllegalArgumentException();
+            }
+
+            String possibleFile = (String) possibleValue;
+            if (Defaults.OS_DOS_LIKE) {
+                if (!(Character.isLetter(possibleFile.charAt(0)) &&
+                      possibleFile.charAt(1) == ':' &&
+                      (possibleFile.charAt(2) == File.separatorChar ||
+                       possibleFile.charAt(2) == '/'))) {
+                    throw new IllegalArgumentException();
+                }
+            }
+            else
+            if (!(possibleFile.startsWith("/"))) {
+                throw new IllegalArgumentException();
+            }
+
+        }
+
+        @Override
+        public String getPossibleValues() {
+            return Defaults.OS_DOS_LIKE ? R("VVPossibleFileValuesDOS") : R("VVPossibleFileValues");
+        }
+
+    }
+
+    /**
+     * Checks that the value is an Integer or Long (or a String representation
+     * of one) that is within a desired range).
+     */
+    private static class RangedIntegerValidator implements ValueValidator {
+        private int low = 0;
+        private int high = 0;
+
+        public RangedIntegerValidator(int low, int high) {
+            this.low = low;
+            this.high = high;
+        }
+
+        @Override
+        public void validate(Object value) throws IllegalArgumentException {
+            Object possibleValue = value;
+
+            long actualValue = 0;
+            try {
+                if (possibleValue instanceof String) {
+                    actualValue = Long.valueOf((String) possibleValue);
+                } else if (possibleValue instanceof Integer) {
+                    actualValue = (Integer) possibleValue;
+                } else if (possibleValue instanceof Long) {
+                    actualValue = (Long) possibleValue;
+                } else {
+                    throw new IllegalArgumentException("Must be an integer");
+                }
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Must be an integer");
+
+            }
+
+            if (actualValue < low || actualValue > high) {
+                throw new IllegalArgumentException("Not in range from " + low + " to " + high);
+            }
+        }
+
+        @Override
+        public String getPossibleValues() {
+            return R("VVPossibleRangedIntegerValues", low, high);
+        }
+
+    };
+
+    /**
+     * Checks that the value is one of the acceptable String values
+     */
+    private static class StringValueValidator implements ValueValidator {
+        String[] options = null;
+
+        public StringValueValidator(String[] acceptableOptions) {
+            options = acceptableOptions;
+        }
+
+        @Override
+        public void validate(Object value) throws IllegalArgumentException {
+            Object possibleValue = value;
+            if (!(possibleValue instanceof String)) {
+                throw new IllegalArgumentException("Must be a string");
+            }
+
+            String stringVal = (String) possibleValue;
+            boolean found = false;
+            for (String knownVal : options) {
+                if (knownVal.equals(stringVal)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public String getPossibleValues() {
+            return Arrays.toString(options);
+        }
+
+    }
+
+    /**
+     * Checks that the value is a URL
+     */
+    private static class UrlValidator implements ValueValidator {
+
+        @Override
+        public void validate(Object value) throws IllegalArgumentException {
+            if (value == null) {
+                return;
+            }
+            try {
+                new URL((String) value);
+            } catch (Exception e) {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public String getPossibleValues() {
+            return R("VVPossibleUrlValues");
+        }
+
+    }
+
+    /**
+     * @return a {@link ValueValidator} that can be used to check if an object is
+     * a valid Boolean
+     */
+    public static ValueValidator getBooleanValidator() {
+        return new BooleanValidator();
+    }
+
+    /**
+     * @return a {@link ValueValidator} that can be used to check if an object is
+     * a String containing a valid file path or not
+     */
+    public static ValueValidator getFilePathValidator() {
+        return new FilePathValidator();
+    }
+
+    /**
+     * Returns a {@link ValueValidator} that checks if an object represents a
+     * valid integer (it is a Integer or Long or a String representation of
+     * one), within the given range. The values are inclusive.
+     * @param low the lowest valid value
+     * @param high the highest valid value
+     */
+    public static ValueValidator getRangedIntegerValidator(int low, int high) {
+        return new RangedIntegerValidator(low, high);
+    }
+
+    /**
+     * Returns a {@link ValueValidator} that checks if an object is a string from
+     * one of the provided Strings.
+     * @param validValues an array of Strings which are considered valid
+     */
+    public static ValueValidator getStringValidator(String[] validValues) {
+        return new StringValueValidator(validValues);
+    }
+
+    /**
+     * @return a {@link ValueValidator} that checks if an object represents a
+     * valid url
+     */
+    public static ValueValidator getUrlValidator() {
+        return new UrlValidator();
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ConfiguratonValidator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ConfiguratonValidator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ConfiguratonValidator.java	(revision 403)
@@ -0,0 +1,120 @@
+/* Validator.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Validates a DeploymentConfiguration by identifying settings with
+ * unrecognized names or incorrect values.
+ */
+public class ConfiguratonValidator {
+
+    private List<Setting<String>> incorrectEntries;
+    private List<Setting<String>> unrecognizedEntries;
+    private Map<String, Setting<String>> toValidate = null;
+
+    private boolean validated = false;
+
+    /**
+     * @param toValidate the settings to validate
+     */
+    public ConfiguratonValidator(Map<String, Setting<String>> toValidate) {
+        this.toValidate = toValidate;
+    }
+
+    /**
+     * Validates the settings used in the constructor. Use
+     * {@link #getIncorrectSetting()} and {@link #getUnrecognizedSetting()} to
+     * get the list of incorrect or unrecognized settings.
+     */
+    public void validate() {
+        incorrectEntries = new ArrayList<Setting<String>>();
+        unrecognizedEntries = new ArrayList<Setting<String>>();
+
+        Map<String, Setting<String>> knownGood = Defaults.getDefaults();
+
+        for (String key : toValidate.keySet()) {
+            // check for known incorrect settings
+            if (knownGood.containsKey(key)) {
+                Setting<String> good = knownGood.get(key);
+                Setting<String> unknown = toValidate.get(key);
+                ValueValidator checker = good.getValidator();
+                if (checker != null) {
+                    try {
+                        checker.validate(unknown.getValue());
+                    } catch (IllegalArgumentException e) {
+                        Setting<String> strange = new Setting<String>(unknown);
+                        strange.setValue(unknown.getValue());
+                        incorrectEntries.add(strange);
+                    }
+                }
+            } else {
+                // check for unknown settings
+                Setting<String> strange = new Setting<String>(toValidate.get(key));
+                unrecognizedEntries.add(strange);
+            }
+        }
+
+        validated = true;
+    }
+
+    /**
+     * @return a list of settings which have incorrect values
+     */
+    public List<Setting<String>> getIncorrectSetting() {
+        if (!validated) {
+            throw new IllegalStateException();
+        }
+
+        return new ArrayList<Setting<String>>(incorrectEntries);
+    }
+
+    /**
+     * @return a list of settings which are not recognized
+     */
+    public List<Setting<String>> getUnrecognizedSetting() {
+        if (!validated) {
+            throw new IllegalStateException();
+        }
+        return new ArrayList<Setting<String>>(unrecognizedEntries);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Defaults.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Defaults.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Defaults.java	(revision 403)
@@ -0,0 +1,403 @@
+/* Defaults.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.config;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.jnlp.ShortcutDesc;
+import net.sourceforge.jnlp.runtime.JNLPProxySelector;
+
+/**
+ * This class stores the default configuration
+ */
+public class Defaults {
+
+    /**
+     * Whether the OS is a DOS-like (Windows, OS/2) or not.
+     */
+    public static final boolean OS_DOS_LIKE =
+        System.getProperty("os.name").startsWith("OS/2") ||
+        System.getProperty("os.name").contains("Windows");
+
+    /**
+     * Get the default settings for deployment
+     */
+    public static Map<String, Setting<String>> getDefaults() {
+        File userFile = new File(System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_DIR
+                + File.separator + DeploymentConfiguration.DEPLOYMENT_PROPERTIES);
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkRead(userFile.toString());
+        }
+
+        final String SYSTEM_HOME = System.getProperty("java.home");
+        final String SYSTEM_SECURITY = SYSTEM_HOME + File.separator + "lib" + File.separator + "security";
+
+        final String USER_HOME = System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_DIR;
+        final String USER_SECURITY = USER_HOME + File.separator + "security";
+
+        final String LOCKS_DIR = System.getProperty("java.io.tmpdir") + File.separator
+                + System.getProperty("user.name") + File.separator + "netx" + File.separator
+                + "locks";
+
+        /*
+         * This is more or less a straight copy from the deployment
+         * configuration page, with occasional replacements of "" or no-defaults
+         * with null
+         *
+         * The format of this is:
+         * name
+         * checker (can be null or a ValueChecker)
+         * value (can be null or a String)
+         */
+
+        Object[][] defaults = new Object[][] {
+                /* infrastructure */
+                {
+                        DeploymentConfiguration.KEY_USER_CACHE_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_HOME + File.separator + "cache"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_PERSISTENCE_CACHE_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_HOME + File.separator + "pcache"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_CACHE_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_LOG_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_HOME + File.separator + "log"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TMP_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_HOME + File.separator + "tmp"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_LOCKS_DIR,
+                        BasicValueValidators.getFilePathValidator(),
+                        LOCKS_DIR
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE,
+                        BasicValueValidators.getFilePathValidator(),
+                        LOCKS_DIR + File.separator + "netx_running"
+                },
+                /* certificates and policy files */
+                {
+                        DeploymentConfiguration.KEY_USER_SECURITY_POLICY,
+                        BasicValueValidators.getUrlValidator(),
+                        new File(USER_SECURITY + File.separator + "java.policy").toURI().toString()
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TRUSTED_CA_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_SECURITY + File.separator + "trusted.cacerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CA_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_SECURITY + File.separator + "trusted.jssecacerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TRUSTED_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_SECURITY + File.separator + "trusted.certs"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_SECURITY + File.separator + "trusted.jssecerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_USER_TRUSTED_CLIENT_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        USER_SECURITY + File.separator + "trusted.clientcerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_SECURITY_POLICY,
+                        BasicValueValidators.getUrlValidator(),
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CA_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        SYSTEM_SECURITY + File.separator + "cacerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        SYSTEM_SECURITY + File.separator + "jssecacerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        SYSTEM_SECURITY + File.separator + "trusted.certs"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        SYSTEM_SECURITY + File.separator + "trusted.jssecerts"
+                },
+                {
+                        DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CLIENT_CERTS,
+                        BasicValueValidators.getFilePathValidator(),
+                        SYSTEM_SECURITY + File.separator + "trusted.clientcerts"
+                },
+                /* security access and control */
+                {
+                        DeploymentConfiguration.KEY_SECURITY_PROMPT_USER,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        "deployment.security.askgrantdialog.notinca",
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        "deployment.security.notinca.warning",
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        "deployment.security.expired.warning",
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        "deployment.security.jsse.hostmismatch.warning",
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        DeploymentConfiguration.KEY_SECURITY_TRUSTED_POLICY,
+                        BasicValueValidators.getFilePathValidator(),
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_SECURITY_ALLOW_HIDE_WINDOW_WARNING,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        DeploymentConfiguration.KEY_SECURITY_PROMPT_USER_FOR_JNLP,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                {
+                        DeploymentConfiguration.KEY_SECURITY_INSTALL_AUTHENTICATOR,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
+                /* networking */
+                {
+                        DeploymentConfiguration.KEY_PROXY_TYPE,
+                        BasicValueValidators.getRangedIntegerValidator(JNLPProxySelector.PROXY_TYPE_UNKNOWN, JNLPProxySelector.PROXY_TYPE_BROWSER),
+                        String.valueOf(JNLPProxySelector.PROXY_TYPE_BROWSER)
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_SAME,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(false)
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL,
+                        BasicValueValidators.getUrlValidator(),
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_BYPASS_LIST,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_BYPASS_LOCAL,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_HTTP_HOST,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_HTTP_PORT,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_HTTPS_HOST,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_HTTPS_PORT,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_FTP_HOST,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_FTP_PORT,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_SOCKS4_HOST,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_SOCKS4_PORT,
+                        null,
+                        null
+                },
+                {
+                        DeploymentConfiguration.KEY_PROXY_OVERRIDE_HOSTS,
+                        null,
+                        null
+                },
+                /* cache and optional package repository */
+                {
+                        "deployment.cache.max.size",
+                        BasicValueValidators.getRangedIntegerValidator(-1, Integer.MAX_VALUE),
+                        String.valueOf("-1")
+                },
+                {
+                        "deployment.cache.jarcompression",
+                        BasicValueValidators.getRangedIntegerValidator(0, 10),
+                        String.valueOf(0)
+                },
+                {
+                        "deployment.javapi.cache.enabled",
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(false)
+                },
+                /* java console */
+                {
+                        DeploymentConfiguration.KEY_CONSOLE_STARTUP_MODE,
+                        BasicValueValidators.getStringValidator(new String[] {
+                                DeploymentConfiguration.CONSOLE_DISABLE,
+                                DeploymentConfiguration.CONSOLE_HIDE,
+                                DeploymentConfiguration.CONSOLE_SHOW
+                        }),
+                        DeploymentConfiguration.CONSOLE_HIDE
+                },
+                /* tracing and logging */
+                {
+                        DeploymentConfiguration.KEY_ENABLE_TRACING,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(false)
+                },
+                {
+                        DeploymentConfiguration.KEY_ENABLE_LOGGING,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(false)
+                },
+                /* JNLP association */
+                {
+                        DeploymentConfiguration.KEY_JNLP_ASSOCIATIONS,
+                        BasicValueValidators.getRangedIntegerValidator(DeploymentConfiguration.JNLP_ASSOCIATION_NEVER,
+                                DeploymentConfiguration.JNLP_ASSOCIATION_REPLACE_ASK),
+                        String.valueOf(DeploymentConfiguration.JNLP_ASSOCIATION_ASK_USER)
+                },
+                /* desktop integration */
+                {
+                        DeploymentConfiguration.KEY_CREATE_DESKTOP_SHORTCUT,
+                        BasicValueValidators.getStringValidator(new String[] {
+                                ShortcutDesc.CREATE_ALWAYS,
+                                ShortcutDesc.CREATE_ALWAYS_IF_HINTED,
+                                ShortcutDesc.CREATE_ASK_USER,
+                                ShortcutDesc.CREATE_ASK_USER_IF_HINTED,
+                                ShortcutDesc.CREATE_NEVER
+                        }),
+                        ShortcutDesc.CREATE_ASK_USER_IF_HINTED
+                },
+                /* jre selection */
+                {
+                        DeploymentConfiguration.KEY_JRE_INTSTALL_URL,
+                        BasicValueValidators.getUrlValidator(),
+                        null
+                },
+                /* jre management */
+                {
+                        DeploymentConfiguration.KEY_AUTO_DOWNLOAD_JRE,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(false)
+                },
+                /* browser selection */
+                {
+                        DeploymentConfiguration.KEY_BROWSER_PATH,
+                        BasicValueValidators.getFilePathValidator(),
+                        null
+                },
+                /* check for update timeout */
+                {
+                        DeploymentConfiguration.KEY_UPDATE_TIMEOUT,
+                        BasicValueValidators.getRangedIntegerValidator(0, 10000),
+                        String.valueOf(500)
+                }
+        };
+
+        HashMap<String, Setting<String>> result = new HashMap<String, Setting<String>>();
+        for (int i = 0; i < defaults.length; i++) {
+            String name = (String) defaults[i][0];
+            ValueValidator checker = (ValueValidator) defaults[i][1];
+            String actualValue = (String) defaults[i][2];
+            boolean locked = false;
+            Setting<String> value = new Setting<String>(name, R("Unknown"), locked, checker, actualValue, actualValue, R("DCSourceInternal"));
+            result.put(name, value);
+        }
+
+        return result;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java	(revision 403)
@@ -0,0 +1,618 @@
+// Copyright (C) 2010 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.config;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.channels.FileLock;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.ConfigurationException;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * Manages the various properties and configuration related to deployment.
+ *
+ * See:
+ * http://download.oracle.com/javase/1.5.0/docs/guide/deployment/deployment-guide/properties.html
+ */
+public final class DeploymentConfiguration {
+
+    public static final String DEPLOYMENT_DIR = ".icedtea";
+    public static final String DEPLOYMENT_CONFIG = "deployment.config";
+    public static final String DEPLOYMENT_PROPERTIES = "deployment.properties";
+
+    public static final String DEPLOYMENT_COMMENT = "Netx deployment configuration";
+
+    public static final int JNLP_ASSOCIATION_NEVER = 0;
+    public static final int JNLP_ASSOCIATION_NEW_ONLY = 1;
+    public static final int JNLP_ASSOCIATION_ASK_USER = 2;
+    public static final int JNLP_ASSOCIATION_REPLACE_ASK = 3;
+
+    /*
+     * FIXME these should be moved into JavaConsole, but there is a strange
+     * dependency in the build system. First all of netx is built. Then the
+     * plugin is built. So we cannot refer to plugin code in here :(
+     */
+    public static final String CONSOLE_HIDE = "HIDE";
+    public static final String CONSOLE_SHOW = "SHOW";
+    public static final String CONSOLE_DISABLE = "DISABLE";
+
+    public static final String KEY_USER_CACHE_DIR = "deployment.user.cachedir";
+    public static final String KEY_USER_PERSISTENCE_CACHE_DIR = "deployment.user.pcachedir";
+    public static final String KEY_SYSTEM_CACHE_DIR = "deployment.system.cachedir";
+    public static final String KEY_USER_LOG_DIR = "deployment.user.logdir";
+    public static final String KEY_USER_TMP_DIR = "deployment.user.tmp";
+    /** the directory containing locks for single instance applications */
+    public static final String KEY_USER_LOCKS_DIR = "deployment.user.locksdir";
+    /**
+     * The netx_running file is used to indicate if any instances of netx are
+     * running (this file may exist even if no instances are running). All netx
+     * instances acquire a shared lock on this file. If this file can be locked
+     * (using a {@link FileLock}) in exclusive mode, then other netx instances
+     * are not running
+     */
+    public static final String KEY_USER_NETX_RUNNING_FILE = "deployment.user.runningfile";
+
+    public static final String KEY_USER_SECURITY_POLICY = "deployment.user.security.policy";
+    public static final String KEY_USER_TRUSTED_CA_CERTS = "deployment.user.security.trusted.cacerts";
+    public static final String KEY_USER_TRUSTED_JSSE_CA_CERTS = "deployment.user.security.trusted.jssecacerts";
+    public static final String KEY_USER_TRUSTED_CERTS = "deployment.user.security.trusted.certs";
+    public static final String KEY_USER_TRUSTED_JSSE_CERTS = "deployment.user.security.trusted.jssecerts";
+    public static final String KEY_USER_TRUSTED_CLIENT_CERTS = "deployment.user.security.trusted.clientauthcerts";
+
+    public static final String KEY_SYSTEM_SECURITY_POLICY = "deployment.system.security.policy";
+    public static final String KEY_SYSTEM_TRUSTED_CA_CERTS = "deployment.system.security.cacerts";
+    public static final String KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS = "deployment.system.security.jssecacerts";
+    public static final String KEY_SYSTEM_TRUSTED_CERTS = "deployment.system.security.trusted.certs";
+    public static final String KEY_SYSTEM_TRUSTED_JSSE_CERTS = "deployment.system.security.trusted.jssecerts";
+    public static final String KEY_SYSTEM_TRUSTED_CLIENT_CERTS = "deployment.system.security.trusted.clientautcerts";
+
+    /*
+     * Security and access control
+     */
+
+    /** Boolean. Only show security prompts to user if true */
+    public static final String KEY_SECURITY_PROMPT_USER = "deployment.security.askgrantdialog.show";
+
+    public static final String KEY_SECURITY_TRUSTED_POLICY = "deployment.security.trusted.policy";
+
+    /** Boolean. Only give AWTPermission("showWindowWithoutWarningBanner") if true */
+    public static final String KEY_SECURITY_ALLOW_HIDE_WINDOW_WARNING = "deployment.security.sandbox.awtwarningwindow";
+
+    /** Boolean. Only prompt user for granting any JNLP permissions if true */
+    public static final String KEY_SECURITY_PROMPT_USER_FOR_JNLP = "deployment.security.sandbox.jnlp.enhanced";
+
+    /** Boolean. Only install the custom authenticator if true */
+    public static final String KEY_SECURITY_INSTALL_AUTHENTICATOR = "deployment.security.authenticator";
+
+    /*
+     * Networking
+     */
+    public static final String KEY_PROXY_TYPE = "deployment.proxy.type";
+    public static final String KEY_PROXY_SAME = "deployment.proxy.same";
+    public static final String KEY_PROXY_AUTO_CONFIG_URL = "deployment.proxy.auto.config.url";
+    public static final String KEY_PROXY_BYPASS_LIST = "deployment.proxy.bypass.list";
+    public static final String KEY_PROXY_BYPASS_LOCAL = "deployment.proxy.bypass.local";
+    public static final String KEY_PROXY_HTTP_HOST = "deployment.proxy.http.host";
+    public static final String KEY_PROXY_HTTP_PORT = "deployment.proxy.http.port";
+    public static final String KEY_PROXY_HTTPS_HOST = "deployment.proxy.https.host";
+    public static final String KEY_PROXY_HTTPS_PORT = "deployment.proxy.https.port";
+    public static final String KEY_PROXY_FTP_HOST = "deployment.proxy.ftp.host";
+    public static final String KEY_PROXY_FTP_PORT = "deployment.proxy.ftp.port";
+    public static final String KEY_PROXY_SOCKS4_HOST = "deployment.proxy.socks.host";
+    public static final String KEY_PROXY_SOCKS4_PORT = "deployment.proxy.socks.port";
+    public static final String KEY_PROXY_OVERRIDE_HOSTS = "deployment.proxy.override.hosts";
+
+    /*
+     * Tracing and Logging
+     */
+    public static final String KEY_ENABLE_TRACING = "deployment.trace";
+    public static final String KEY_ENABLE_LOGGING = "deployment.log";
+
+    /*
+     * Console
+     */
+    public static final String KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode";
+
+    /*
+     * Desktop Integration
+     */
+
+    public static final String KEY_JNLP_ASSOCIATIONS = "deployment.javaws.associations";
+    public static final String KEY_CREATE_DESKTOP_SHORTCUT = "deployment.javaws.shortcut";
+
+    public static final String KEY_JRE_INTSTALL_URL = "deployment.javaws.installURL";
+    public static final String KEY_AUTO_DOWNLOAD_JRE = "deployment.javaws.autodownload";
+
+    public static final String KEY_BROWSER_PATH = "deployment.browser.path";
+    public static final String KEY_UPDATE_TIMEOUT = "deployment.javaws.update.timeout";
+
+    public enum ConfigType {
+        System, User
+    }
+
+    /** is it mandatory to load the system properties? */
+    private boolean systemPropertiesMandatory = false;
+
+    /** The system's deployment.config file */
+    private File systemPropertiesFile = null;
+    /** The user's deployment.config file */
+    private File userPropertiesFile = null;
+
+    /** the current deployment properties */
+    private Map<String, Setting<String>> currentConfiguration;
+
+    /** the deployment properties that cannot be changed */
+    private Map<String, Setting<String>> unchangeableConfiguration;
+
+    public DeploymentConfiguration() {
+        currentConfiguration = new HashMap<String, Setting<String>>();
+        unchangeableConfiguration = new HashMap<String, Setting<String>>();
+    }
+
+    /**
+     * Initialize this deployment configuration by reading configuration files.
+     * Generally, it will try to continue and ignore errors it finds (such as file not found).
+     *
+     * @throws DeploymentException if it encounters a fatal error.
+     */
+    public void load() throws ConfigurationException {
+        load(true);
+    }
+
+    /**
+     * Initialize this deployment configuration by reading configuration files.
+     * Generally, it will try to continue and ignore errors it finds (such as file not found).
+     *
+     * @param fixIssues If true, fix issues that are discovered when reading configuration by
+     * resorting to the default values
+     * @throws DeploymentException if it encounters a fatal error.
+     */
+    public void load(boolean fixIssues) throws ConfigurationException {
+        // make sure no state leaks if security check fails later on
+        File userFile = new File(System.getProperty("user.home") + File.separator + DEPLOYMENT_DIR
+                + File.separator + DEPLOYMENT_PROPERTIES);
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkRead(userFile.toString());
+        }
+
+        Map<String, Setting<String>> initialProperties = Defaults.getDefaults();
+
+        Map<String, Setting<String>> systemProperties = null;
+
+        /*
+         * First, try to read the system's deployment.config file to find if
+         * there is a system-level deployment.poperties file
+         */
+
+        File systemConfigFile = findSystemConfigFile();
+        if (systemConfigFile != null) {
+            if (loadSystemConfiguration(systemConfigFile)) {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("System level " + DEPLOYMENT_CONFIG + " is mandatory: " + systemPropertiesMandatory);
+                }
+                /* Second, read the System level deployment.properties file */
+                systemProperties = loadProperties(ConfigType.System, systemPropertiesFile,
+                        systemPropertiesMandatory);
+            }
+            if (systemProperties != null) {
+                mergeMaps(initialProperties, systemProperties);
+            }
+        }
+
+        /* need a copy of the original when we have to save */
+        unchangeableConfiguration = new HashMap<String, Setting<String>>();
+        Set<String> keys = initialProperties.keySet();
+        for (String key : keys) {
+            unchangeableConfiguration.put(key, new Setting<String>(initialProperties.get(key)));
+        }
+
+        /*
+         * Third, read the user's deployment.properties file
+         */
+        userPropertiesFile = userFile;
+        Map<String, Setting<String>> userProperties = loadProperties(ConfigType.User, userPropertiesFile, false);
+        if (userProperties != null) {
+            mergeMaps(initialProperties, userProperties);
+        }
+
+        if (fixIssues) {
+            checkAndFixConfiguration(initialProperties);
+        }
+
+        currentConfiguration = initialProperties;
+    }
+
+    /**
+     * Get the value for the given key
+     *
+     * @param key the property key
+     * @return the value for the key, or null if it can not be found
+     */
+    public String getProperty(String key) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (userPropertiesFile != null) {
+                sm.checkRead(userPropertiesFile.toString());
+            }
+        }
+
+        String value = null;
+        if (currentConfiguration.get(key) != null) {
+            value = currentConfiguration.get(key).getValue();
+        }
+        return value;
+    }
+
+    /**
+     * @return a Set containing all the property names
+     */
+    public Set<String> getAllPropertyNames() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (userPropertiesFile != null) {
+                sm.checkRead(userPropertiesFile.toString());
+            }
+        }
+
+        return currentConfiguration.keySet();
+    }
+
+    /**
+     * @return a map containing property names and the corresponding settings
+     */
+    public Map<String, Setting<String>> getRaw() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (userPropertiesFile != null) {
+                sm.checkRead(userPropertiesFile.toString());
+            }
+        }
+
+        return currentConfiguration;
+    }
+
+    /**
+     * Sets the value of corresponding to the key. If the value has been marked
+     * as locked, it is not changed
+     *
+     * @param key the key
+     * @param value the value to be associated with the key
+     */
+    public void setProperty(String key, String value) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (userPropertiesFile != null) {
+                sm.checkWrite(userPropertiesFile.toString());
+            }
+        }
+
+        Setting<String> currentValue = currentConfiguration.get(key);
+        if (currentValue != null) {
+            if (!currentValue.isLocked()) {
+                currentValue.setValue(value);
+            }
+        } else {
+            currentValue = new Setting<String>(key, R("Unknown"), false, null, null, value, R("Unknown"));
+            currentConfiguration.put(key, currentValue);
+        }
+    }
+
+    /**
+     * Check that the configuration is valid. If there are invalid values,set
+     * those values to the default values. This is done by using check()
+     * method of the ValueCheker for each setting on the actual value. Fixes
+     * are made in-place.
+     *
+     * @param initial a map representing the initial configuration
+     */
+    public void checkAndFixConfiguration(Map<String, Setting<String>> initial) {
+
+        Map<String, Setting<String>> defaults = Defaults.getDefaults();
+
+        for (String key : initial.keySet()) {
+            Setting<String> s = initial.get(key);
+            if (!(s.getName().equals(key))) {
+                System.out.println(R("DCInternal", "key " + key + " does not match setting name " + s.getName()));
+            } else if (!defaults.containsKey(key)) {
+                System.out.println(R("DCUnknownSettingWithName", key));
+            } else {
+                ValueValidator checker = defaults.get(key).getValidator();
+                if (checker == null) {
+                    continue;
+                }
+
+                try {
+                    checker.validate(s.getValue());
+                } catch (IllegalArgumentException e) {
+                    System.out.println(R("DCIncorrectValue", key, s.getValue(), checker.getPossibleValues()));
+                    s.setValue(s.getDefaultValue());
+                }
+            }
+        }
+    }
+
+    /**
+     * @return the location of system-level deployment.config file, or null if none can be found
+     */
+    private File findSystemConfigFile() {
+        File etcFile = new File(File.separator + "etc" + File.separator + ".java" + File.separator
+                + "deployment" + File.separator + DEPLOYMENT_CONFIG);
+        if (etcFile.isFile()) {
+            return etcFile;
+        }
+
+        File jreFile = new File(System.getProperty("java.home") + File.separator + "lib"
+                + File.separator + DEPLOYMENT_CONFIG);
+        if (jreFile.isFile()) {
+            return jreFile;
+        }
+
+        return null;
+    }
+
+    /**
+     * Reads the system configuration file and sets the relevant
+     * system-properties related variables
+     */
+    private boolean loadSystemConfiguration(File configFile) {
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Loading system configuation from: " + configFile);
+        }
+
+        Map<String, Setting<String>> systemConfiguration = new HashMap<String, Setting<String>>();
+        try {
+            systemConfiguration = parsePropertiesFile(configFile);
+        } catch (IOException e) {
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("No System level " + DEPLOYMENT_PROPERTIES + " found.");
+            }
+            return false;
+        }
+
+        /*
+         * at this point, we have read the system deployment.config file
+         * completely
+         */
+
+        try {
+            String urlString = systemConfiguration.get("deployment.system.config").getValue();
+            if (urlString == null) {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("No System level " + DEPLOYMENT_PROPERTIES + " found.");
+                }
+                return false;
+            }
+            URL url = new URL(urlString);
+            if (url.getProtocol().equals("file")) {
+                systemPropertiesFile = new File(url.getFile());
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("Using System level" + DEPLOYMENT_PROPERTIES + ": "
+                            + systemPropertiesFile);
+                }
+                Setting<String> mandatory = systemConfiguration.get("deployment.system.config.mandatory");
+                systemPropertiesMandatory = Boolean.valueOf(mandatory == null ? null : (String) mandatory.getValue());
+                return true;
+            } else {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("Remote + " + DEPLOYMENT_PROPERTIES + " not supported");
+                }
+                return false;
+            }
+        } catch (MalformedURLException e) {
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Invalid url for " + DEPLOYMENT_PROPERTIES);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Loads the properties file, if one exists
+     *
+     * @param type the ConfigType to load
+     * @param file the File to load Properties from
+     * @param mandatory indicates if reading this file is mandatory
+     *
+     * @throws ConfigurationException if the file is mandatory but cannot be read
+     */
+    private Map<String, Setting<String>> loadProperties(ConfigType type, File file, boolean mandatory)
+            throws ConfigurationException {
+        if (file == null || !file.isFile()) {
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("No " + type.toString() + " level " + DEPLOYMENT_PROPERTIES + " found.");
+            }
+            if (!mandatory) {
+                return null;
+            } else {
+                throw new ConfigurationException();
+            }
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Loading " + type.toString() + " level properties from: " + file);
+        }
+        try {
+            return parsePropertiesFile(file);
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Saves all properties that are not part of default or system properties
+     *
+     * @throws IOException if unable to save the file
+     * @throws IllegalStateException if save() is called before load()
+     */
+    public void save() throws IOException {
+        if (userPropertiesFile == null) {
+            throw new IllegalStateException("must load() before save()");
+        }
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkWrite(userPropertiesFile.toString());
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Saving properties into " + userPropertiesFile.toString());
+        }
+        Properties toSave = new Properties();
+
+        for (String key : currentConfiguration.keySet()) {
+            String oldValue = unchangeableConfiguration.get(key) == null ? null
+                    : (String) unchangeableConfiguration.get(key).getValue();
+            String newValue = currentConfiguration.get(key) == null ? null : (String) currentConfiguration
+                    .get(key).getValue();
+            if (oldValue == null && newValue == null) {
+                continue;
+            } else if (oldValue == null && newValue != null) {
+                toSave.setProperty(key, newValue);
+            } else if (oldValue != null && newValue == null) {
+                toSave.setProperty(key, newValue);
+            } else { // oldValue != null && newValue != null
+                if (!oldValue.equals(newValue)) {
+                    toSave.setProperty(key, newValue);
+                }
+            }
+        }
+
+        File backupPropertiesFile = new File(userPropertiesFile.toString() + ".old");
+        if (userPropertiesFile.isFile()) {
+            if (!userPropertiesFile.renameTo(backupPropertiesFile)) {
+                throw new IOException("Error saving backup copy of " + userPropertiesFile);
+            }
+        }
+
+        FileUtils.createParentDir(userPropertiesFile);
+        OutputStream out = new BufferedOutputStream(new FileOutputStream(userPropertiesFile));
+        try {
+            toSave.store(out, DEPLOYMENT_COMMENT);
+        } finally {
+            out.close();
+        }
+    }
+
+    /**
+     * Reads a properties file and returns a map representing the properties
+     *
+     * @param propertiesFile the file to read Properties from
+     * @param destination the map to which all the properties should be added
+     * @throws IOException if an IO problem occurs
+     */
+    private Map<String, Setting<String>> parsePropertiesFile(File propertiesFile) throws IOException {
+        Map<String, Setting<String>> result = new HashMap<String, Setting<String>>();
+
+        Properties properties = new Properties();
+
+        Reader reader = new BufferedReader(new FileReader(propertiesFile));
+        try {
+            properties.load(reader);
+        } finally {
+            reader.close();
+        }
+
+        Set<String> keys = properties.stringPropertyNames();
+        for (String key : keys) {
+            if (key.endsWith(".locked")) {
+                String realKey = key.substring(0, key.length() - ".locked".length());
+                Setting<String> configValue = result.get(realKey);
+                if (configValue == null) {
+                    configValue = new Setting<String>(realKey, R("Unknown"), true, null, null, null, propertiesFile.toString());
+                    result.put(realKey, configValue);
+                } else {
+                    configValue.setLocked(true);
+                }
+            } else {
+                /* when parsing a properties we set value without checking if it is locked or not */
+                String newValue = properties.getProperty(key);
+                Setting<String> configValue = result.get(key);
+                if (configValue == null) {
+                    configValue = new Setting<String>(key, R("Unknown"), false, null, null, newValue, propertiesFile.toString());
+                    result.put(key, configValue);
+                } else {
+                    configValue.setValue(newValue);
+                    configValue.setSource(propertiesFile.toString());
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Merges two maps while respecting whether the values have been locked or
+     * not. All values from srcMap are put into finalMap, replacing values in
+     * finalMap if necessary, unless the value is present and marked as locked
+     * in finalMap
+     *
+     * @param finalMap the destination for putting values
+     * @param srcMap the source for reading key value pairs
+     */
+    private void mergeMaps(Map<String, Setting<String>> finalMap, Map<String, Setting<String>> srcMap) {
+        for (String key : srcMap.keySet()) {
+            Setting<String> destValue = finalMap.get(key);
+            Setting<String> srcValue = srcMap.get(key);
+            if (destValue == null) {
+                finalMap.put(key, srcValue);
+            } else {
+                if (!destValue.isLocked()) {
+                    destValue.setSource(srcValue.getSource());
+                    destValue.setValue(srcValue.getValue());
+                }
+            }
+        }
+    }
+
+    /**
+     * Dumps the configuration to the PrintStream
+     *
+     * @param config a map of key,value pairs representing the configuration to
+     * dump
+     * @param out the PrintStream to write data to
+     */
+    @SuppressWarnings("unused")
+    private static void dumpConfiguration(Map<String, Setting<String>> config, PrintStream out) {
+        System.out.println("KEY: VALUE [Locked]");
+
+        for (String key : config.keySet()) {
+            Setting<String> value = config.get(key);
+            out.println("'" + key + "': '" + value.getValue() + "'"
+                    + (value.isLocked() ? " [LOCKED]" : ""));
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Setting.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Setting.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/Setting.java	(revision 403)
@@ -0,0 +1,176 @@
+/* Setting.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.config;
+
+/**
+ * Represents a value for a configuration. Provides methods to get the value
+ * as well as marking the value as locked.
+ *
+ * Each instance of this class has an associated ValueChecker. This checker
+ * can be used to check if the current value is valid. The default value
+ * _must_ be valid. Null values can not originate externally so are (mostly)
+ * considered valid.
+ */
+public class Setting<T> {
+
+    private String name = null;
+    private String description = null;
+    private boolean locked = false;
+    private ValueValidator validator = null;
+    private T defaultValue = null;
+    private T value = null;
+    private String source = null;
+
+    /**
+     * Creates a new Settings object
+     *
+     * @param name the name of this setting
+     * @param description a human readable description of this setting
+     * @param locked whether this setting is currently locked
+     * @param validator the {@link ValueValidator} that can be used to validate
+     * the value
+     * @param defaultValue the default value of this setting. If this is not a
+     * recognized setting, use null.
+     * @param value the initial value of this setting
+     * @param source the origin of the value (a file, or perhaps "<internal>")
+     */
+    public Setting(String name, String description, boolean locked,
+            ValueValidator validator, T defaultValue, T value, String source) {
+        this.name = name;
+        this.description = description;
+        this.locked = locked;
+        this.validator = validator;
+        this.source = source;
+        this.defaultValue = defaultValue;
+        this.value = value;
+    }
+
+    /**
+     * Creates a new Settings object by cloning the values from another
+     * Settings object
+     * @param other a Settings object to initialize settings from
+     */
+    public Setting(Setting<T> other) {
+        this(other.name, other.description, other.locked, other.validator,
+                other.defaultValue, other.value, other.source);
+    }
+
+    /**
+     * @return the {@link ValueValidator} that can be used to check if
+     * the current value is valid
+     */
+    public ValueValidator getValidator() {
+        return validator;
+    }
+
+    /**
+     * @return the default value for this setting. May be null if this is not
+     * one of the supported settings
+     */
+    public T getDefaultValue() {
+        return defaultValue;
+    }
+
+    /**
+     * @return a human readable description of this setting
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the name (like foo.bar.baz) of this setting
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the source of the current value of this setting. May be a string
+     * like "internal" or it may be the location of the properties file
+     */
+    public String getSource() {
+        return source;
+    }
+
+    /**
+     * @return the current value of this setting
+     */
+    public T getValue() {
+        return value;
+    }
+
+    /**
+     * @return true if this setting is locked
+     */
+    public boolean isLocked() {
+        return locked;
+    }
+
+    /**
+     * Marks this setting as locked or unlocked. Setting the value is not
+     * enforced by this class.
+     *
+     * @param locked whether to mark this setting as locked or not locked.
+     */
+    public void setLocked(boolean locked) {
+        this.locked = locked;
+    }
+
+    /**
+     * Sets the source of the current value of this Setting. Maybe a string
+     * like "internal" or the location of the properties file
+     *
+     * @param source the source of the value
+     */
+    public void setSource(String source) {
+        this.source = source;
+    }
+
+    /**
+     * Note that setting the value is not enforced - it is the caller's
+     * responsibility to check if a value is locked or not before setting a
+     * new value
+     *
+     * @param value the new value
+     */
+    public void setValue(T value) {
+        this.value = value;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ValueValidator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ValueValidator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/config/ValueValidator.java	(revision 403)
@@ -0,0 +1,66 @@
+/* ValueChecker.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.config;
+
+/**
+ * A class implements the ValueValidator interface to indicate that it can validate
+ * values.
+ *
+ * @see BasicValueValidators
+ */
+public interface ValueValidator {
+
+    /**
+     * This method checks if the given object is a valid value for this 
+     * specific {@link ValueValidator}. Any arbitrary operation can be
+     * performed to ensure that the value is valid.
+     *
+     * @param value The object to validate
+     * @throws IllegalArgumentException if the value is invalid
+     */
+    public void validate(Object value) throws IllegalArgumentException;
+
+    /**
+     * Returns a string describing possible values in human-readable form that
+     * this {@link ValueValidator} accepts
+     *
+     * @return a string describing possible values that this
+     * {@link ValueValidator} accepts
+     */
+    public String getPossibleValues();
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AboutPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AboutPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AboutPanel.java	(revision 403)
@@ -0,0 +1,63 @@
+/* AboutPanel.java -- Display information about the control panel and icedtea-web.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This class provides a GUI interface which shows some basic information on
+ * this project.
+ *
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ *
+ */
+public class AboutPanel extends NamedBorderPanel {
+
+    public AboutPanel() {
+        super(Translator.R("CPHeadAbout"), new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+
+        JLabel logo = new JLabel();
+        JLabel aboutLabel = new JLabel("<html>" + Translator.R("CPAboutInfo") + "</html>");
+
+        c.fill = GridBagConstraints.BOTH;
+        c.gridy = 0;
+        c.gridx = 0;
+        c.weighty = 0;
+        c.weightx = 0;
+        add(logo, c);
+        c.gridx = 1;
+        c.weightx = 1;
+        add(aboutLabel, c);
+
+        /* Keep all the elements at the top of the panel (Extra padding) */
+        Component filler = Box.createRigidArea(new Dimension(1, 1));
+        c.weighty = 1;
+        c.gridy++;
+        add(filler, c);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java	(revision 403)
@@ -0,0 +1,125 @@
+/* AdvancedProxySettingsDialog.java -- Display the dialog for modifying proxy settings.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JDialog;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This dialog provides a means for user to edit more of the proxy settings.
+ * 
+ * @author Andrew Su <asu@redhat.com, andrew.su@utoronto.ca>
+ * 
+ */
+public class AdvancedProxySettingsDialog extends JDialog {
+
+    private boolean initialized = false;
+    private static final String dialogTitle = Translator.R("APSDialogTitle");
+    private DeploymentConfiguration config; // Configuration file which contains all the settings.
+
+    AdvancedProxySettingsPane topPanel;
+
+    /**
+     * Creates a new instance of the proxy settings dialog.
+     * 
+     * @param config
+     *            Loaded DeploymentConfiguration file.
+     */
+    public AdvancedProxySettingsDialog(DeploymentConfiguration config) {
+        super((Frame) null, dialogTitle, true); // Don't need a parent.
+        this.config = config;
+
+        /* Prepare for adding components to dialog box */
+        Container contentPane = getContentPane();
+        contentPane.setLayout(new GridBagLayout());
+        setMinimumSize(new Dimension(456, 404));
+        setPreferredSize(new Dimension(456, 404));
+
+        GridBagConstraints c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+        c.weightx = 1;
+        c.weighty = 1;
+        c.gridx = 0;
+        c.gridy = 0;
+        topPanel = new AdvancedProxySettingsPane(this, this.config);
+        contentPane.add(topPanel, c);
+
+        pack();
+
+        /* Set focus to default button when first activated */
+        WindowAdapter adapter = new WindowAdapter() {
+            private boolean gotFocus = false;
+
+            public void windowGainedFocus(WindowEvent we) {
+                // Once window gets focus, set initial focus
+                if (!gotFocus) {
+                    topPanel.focusOnDefaultButton();
+                    gotFocus = true;
+                }
+            }
+        };
+        addWindowFocusListener(adapter);
+
+        initialized = true;
+    }
+
+    /**
+     * Check whether the dialog has finished being created.
+     * 
+     * @return True if dialog is ready to be displayed.
+     */
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * Center the dialog box.
+     */
+    private void centerDialog() {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = getSize();
+
+        setLocation((screen.width - dialogSize.width) / 2, (screen.height - dialogSize.height) / 2);
+    }
+
+    /**
+     * Display the Proxy Settings Dialog.
+     * 
+     * @param config
+     *            A loaded DeploymentConfiguration file.
+     */
+    public static void showAdvancedProxySettingsDialog(final DeploymentConfiguration config) {
+        AdvancedProxySettingsDialog psd = new AdvancedProxySettingsDialog(config);
+        psd.setResizable(false);
+        psd.centerDialog();
+        psd.setVisible(true);
+        psd.dispose();
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java	(revision 403)
@@ -0,0 +1,296 @@
+/* AdvancedProxySettingsPane.java -- Provides the panel which can modify proxy settings.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This is the pane that modifies the proxy settings in more detail.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class AdvancedProxySettingsPane extends JPanel {
+
+    private JDialog parent;
+    private DeploymentConfiguration config;
+
+    /** List of properties used by this panel */
+    public static String[] properties = { "deployment.proxy.http.host",
+            "deployment.proxy.http.port",
+            "deployment.proxy.https.host",
+            "deployment.proxy.https.port",
+            "deployment.proxy.ftp.host",
+            "deployment.proxy.ftp.port",
+            "deployment.proxy.socks.host",
+            "deployment.proxy.socks.port",
+            "deployment.proxy.same",
+            "deployment.proxy.override.hosts" };
+    private String[] fields = new String[properties.length];
+
+    private JComponent defaultFocusComponent = null;
+
+    /**
+     * Creates a new instance of the proxy settings panel.
+     * 
+     * @param parent
+     *            JDialog this is associated with.
+     * @param config
+     *            Loaded DeploymentConfiguration file.
+     */
+    public AdvancedProxySettingsPane(JDialog parent, DeploymentConfiguration config) {
+        super(new BorderLayout());
+        this.parent = parent;
+        this.config = config;
+
+        getProperties();
+        addComponents();
+    }
+
+    /**
+     * Place properties into an array, this is so when cancel is hit. We don't
+     * overwrite the original values.
+     */
+    private void getProperties() {
+        for (int i = 0; i < fields.length; i++) {
+            fields[i] = this.config.getProperty(properties[i]);
+        }
+    }
+
+    /**
+     * Add the components to the panel.
+     */
+    private void addComponents() {
+        JPanel topPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+
+        JPanel servers = new NamedBorderPanel(Translator.R("APSServersPanel"));
+        servers.setLayout(new GridBagLayout());
+
+        JLabel type = new JLabel(Translator.R("APSProxyTypeLabel"));
+        JLabel proxyAddress = new JLabel(Translator.R("APSProxyAddressLabel"));
+        JLabel port = new JLabel(Translator.R("APSProxyPortLabel"));
+
+        // This addresses the HTTP proxy settings.
+        JLabel http = new JLabel(Translator.R("APSLabelHTTP") + ":");
+        final JTextField httpAddressField = new JTextField(fields[0]);
+        final JTextField httpPortField = new JTextField();
+        httpPortField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
+        httpAddressField.getDocument().addDocumentListener(new DocumentAdapter(fields, 0));
+        httpPortField.getDocument().addDocumentListener(new DocumentAdapter(fields, 1));
+        httpPortField.setText(fields[1]);
+
+        // This addresses the HTTPS proxy settings.
+        JLabel secure = new JLabel(Translator.R("APSLabelSecure") + ":");
+        final JTextField secureAddressField = new JTextField(fields[2]);
+        final JTextField securePortField = new JTextField();
+        securePortField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
+        secureAddressField.getDocument().addDocumentListener(new DocumentAdapter(fields, 2));
+        securePortField.getDocument().addDocumentListener(new DocumentAdapter(fields, 3));
+        securePortField.setText(fields[3]);
+
+        // This addresses the FTP proxy settings.
+        JLabel ftp = new JLabel(Translator.R("APSLabelFTP") + ":");
+        final JTextField ftpAddressField = new JTextField(fields[4]);
+        final JTextField ftpPortField = new JTextField();
+        ftpPortField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
+        ftpAddressField.getDocument().addDocumentListener(new DocumentAdapter(fields, 4));
+        ftpPortField.getDocument().addDocumentListener(new DocumentAdapter(fields, 5));
+        ftpPortField.setText(fields[5]);
+
+        // This addresses the Socks proxy settings.
+        JLabel socks = new JLabel(Translator.R("APSLabelSocks") + ":");
+        final JTextField socksAddressField = new JTextField(fields[6]);
+        final JTextField socksPortField = new JTextField();
+        socksPortField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
+        socksAddressField.getDocument().addDocumentListener(new DocumentAdapter(fields, 6));
+        socksPortField.getDocument().addDocumentListener(new DocumentAdapter(fields, 7));
+        socksPortField.setText(fields[7]);
+
+        JCheckBox sameProxyForAll = new JCheckBox(Translator.R("APSSameProxyForAllProtocols"), Boolean.parseBoolean(fields[8]));
+        sameProxyForAll.addItemListener(new ItemListener() {
+            @Override
+            public void itemStateChanged(ItemEvent e) {
+                fields[8] = String.valueOf(e.getStateChange() == ItemEvent.SELECTED);
+            }
+        });
+
+        JPanel p = new JPanel();
+        BoxLayout bl = new BoxLayout(p, BoxLayout.Y_AXIS);
+        p.setLayout(bl);
+        p.add(sameProxyForAll);
+
+        c.fill = GridBagConstraints.BOTH;
+        c.gridheight = 1;
+        c.gridy = 0;
+        c.gridwidth = 1;
+        c.weightx = 0;
+        c.gridx = 0;
+        servers.add(type, c);
+        c.gridwidth = 2;
+        c.weightx = 1;
+        c.gridx = 1;
+        servers.add(proxyAddress, c);
+        c.gridwidth = 1;
+        c.weightx = 1;
+        c.gridx = 4;
+        servers.add(port, c);
+
+        plant(1, http, httpAddressField, httpPortField, servers, c);
+        plant(2, secure, secureAddressField, securePortField, servers, c);
+        plant(3, ftp, ftpAddressField, ftpPortField, servers, c);
+        plant(4, socks, socksAddressField, socksPortField, servers, c);
+        c.gridwidth = 5;
+        c.gridx = 0;
+        c.gridy = 5;
+        servers.add(p, c);
+
+        JPanel exceptions = new NamedBorderPanel(Translator.R("APSExceptionsLabel"));
+        exceptions.setLayout(new BorderLayout());
+        JLabel exceptionDescription = new JLabel(Translator.R("APSExceptionsDescription"));
+        final JTextArea exceptionListArea = new JTextArea();
+        exceptionListArea.setLineWrap(true);
+        exceptionListArea.setText(fields[9]);
+        exceptionListArea.getDocument().addDocumentListener(new DocumentAdapter(fields, 9));
+
+        JLabel exceptionFormat = new JLabel(Translator.R("APSExceptionInstruction"));
+        JScrollPane exceptionScroll = new JScrollPane(exceptionListArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        exceptions.add(exceptionDescription, BorderLayout.NORTH);
+        exceptions.add(exceptionScroll, BorderLayout.CENTER);
+        exceptions.add(exceptionFormat, BorderLayout.SOUTH);
+
+        c.gridx = 0;
+        c.weightx = 1;
+        c.weighty = 0;
+        c.gridy = 0;
+        topPanel.add(servers, c);
+        c.weighty = 1;
+        c.gridy = 1;
+        topPanel.add(exceptions, c);
+
+        this.add(topPanel);
+        this.add(createButtonPanel(), BorderLayout.SOUTH);
+
+    }
+
+    /**
+     * Helper method to help make adding component shorter.
+     */
+    private void plant(int y, JLabel label, JTextField addr, JTextField port, JPanel addTo, GridBagConstraints c) {
+        c.gridy = y;
+
+        c.gridwidth = 1;
+        c.weightx = 0;
+        c.gridx = 0;
+        addTo.add(label, c);
+        c.gridwidth = 2;
+        c.weightx = 1;
+        c.gridx = 1;
+        addTo.add(addr, c);
+        c.gridwidth = 1;
+        c.weightx = 0;
+        c.gridx = 3;
+        addTo.add(new JLabel(":"), c);
+        c.gridwidth = 1;
+        c.weightx = 0.3;
+        c.gridx = 4;
+        addTo.add(port, c);
+    }
+
+    /**
+     * Make the button panel.
+     * 
+     * @return
+     */
+    private JPanel createButtonPanel() {
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
+
+        List<JButton> buttons = new ArrayList<JButton>();
+
+        JButton okButton = new JButton(Translator.R("ButOk"));
+        okButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                for (int i = 0; i < fields.length; i++)
+                    config.setProperty(properties[i], fields[i]);
+
+                parent.dispose();
+            }
+        });
+        buttons.add(okButton);
+
+        JButton cancelButton = new JButton(Translator.R("ButCancel"));
+        cancelButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                parent.dispose();
+            }
+        });
+        buttons.add(cancelButton);
+
+        int maxWidth = 0;
+        int maxHeight = 0;
+        for (JButton button : buttons) {
+            maxWidth = Math.max(button.getMinimumSize().width, maxWidth);
+            maxHeight = Math.max(button.getMinimumSize().height, maxHeight);
+        }
+
+        int wantedWidth = maxWidth + 10;
+        int wantedHeight = maxHeight;
+        for (JButton button : buttons) {
+            button.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
+            buttonPanel.add(button);
+        }
+
+        return buttonPanel;
+    }
+
+    /**
+     * Put focus onto default button.
+     */
+    public void focusOnDefaultButton() {
+        if (defaultFocusComponent != null) {
+            defaultFocusComponent.requestFocusInWindow();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CachePane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CachePane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CachePane.java	(revision 403)
@@ -0,0 +1,307 @@
+/* CachePane.java -- Displays the specified folder and allows modification to its content.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.channels.FileLock;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableRowSorter;
+
+import net.sourceforge.jnlp.cache.CacheDirectory;
+import net.sourceforge.jnlp.cache.DirectoryNode;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.PropertiesFile;
+
+public class CachePane extends JPanel {
+
+    JDialog parent;
+    DeploymentConfiguration config;
+    private String location;
+    private JComponent defaultFocusComponent;
+    DirectoryNode root;
+    String[] columns = { Translator.R("CVCPColName"),
+            Translator.R("CVCPColPath"),
+            Translator.R("CVCPColType"),
+            Translator.R("CVCPColDomain"),
+            Translator.R("CVCPColSize"),
+            Translator.R("CVCPColLastModified") };
+    JTable cacheTable;
+
+    /**
+     * Creates a new instance of the CachePane.
+     * 
+     * @param parent The parent dialog that uses this pane.
+     * @param config The DeploymentConfiguration file.
+     */
+    public CachePane(JDialog parent, DeploymentConfiguration config) {
+        super(new BorderLayout());
+        this.parent = parent;
+        this.config = config;
+        location = config.getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR);
+
+        addComponents();
+    }
+
+    /**
+     * Add components to the pane.
+     */
+    private void addComponents() {
+        JPanel topPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+
+        DefaultTableModel model = new DefaultTableModel(columns, 0) {
+            public boolean isCellEditable(int row, int column) {
+                return false;
+            }
+        };
+
+        cacheTable = new JTable(model);
+        cacheTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        cacheTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
+        cacheTable.setPreferredScrollableViewportSize(new Dimension(600, 200));
+        cacheTable.setFillsViewportHeight(true);
+        JScrollPane scrollPane = new JScrollPane(cacheTable);
+
+        populateTable();
+
+        TableRowSorter<DefaultTableModel> tableSorter = new TableRowSorter<DefaultTableModel>(model);
+        tableSorter.setComparator(4, new Comparator<Long>() { // Comparator for size column.
+            @Override
+            public int compare(Long o1, Long o2) {
+                return o1.compareTo(o2);
+            }
+        });
+        tableSorter.setComparator(5, new Comparator<String>() { // Comparator for date column.
+            @Override
+            public int compare(String o1, String o2) {
+                DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
+                try {
+                    Long time1 = format.parse(o1).getTime();
+                    Long time2 = format.parse(o2).getTime();
+                    return time1.compareTo(time2);
+                } catch (ParseException e) {
+                    return 0;
+                }
+            }
+        });
+        cacheTable.setRowSorter(tableSorter);
+
+        c.weightx = 1;
+        c.weighty = 1;
+        c.gridx = 0;
+        c.gridy = 0;
+        topPanel.add(scrollPane, c);
+        this.add(topPanel, BorderLayout.CENTER);
+        this.add(createButtonPanel(), BorderLayout.SOUTH);
+
+    }
+
+    /**
+     * Create the buttons panel.
+     * 
+     * @return JPanel containing the buttons.
+     */
+    private Component createButtonPanel() {
+        JPanel buttonPanel = new JPanel(new GridLayout(1, 0));
+        JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
+        JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
+
+        List<JButton> buttons = new ArrayList<JButton>();
+
+        JButton deleteButton = new JButton(Translator.R("CVCPButDelete"));
+        deleteButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                FileLock fl = null;
+                File netxRunningFile = new File(config.getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE));
+                if (!netxRunningFile.exists()) {
+                    try {
+                        FileUtils.createParentDir(netxRunningFile);
+                        FileUtils.createRestrictedFile(netxRunningFile, true);
+                    } catch (IOException e1) {
+                        e1.printStackTrace();
+                    }
+                }
+
+                try {
+                    fl = FileUtils.getFileLock(netxRunningFile.getPath(), false, false);
+                } catch (FileNotFoundException e1) {
+                }
+
+                int row = cacheTable.getSelectedRow();
+                try {
+                    if (fl == null) return;
+                    if (row == -1 || row > cacheTable.getRowCount() - 1)
+                        return;
+                    int modelRow = cacheTable.convertRowIndexToModel(row);
+                    DirectoryNode fileNode = ((DirectoryNode) cacheTable.getModel().getValueAt(modelRow, 0));
+                    if (fileNode.getFile().delete()) {
+                        updateRecentlyUsed(fileNode.getFile());
+                        fileNode.getParent().removeChild(fileNode);
+                        FileUtils.deleteWithErrMesg(fileNode.getInfoFile());
+                        ((DefaultTableModel) cacheTable.getModel()).removeRow(modelRow);
+                        cacheTable.getSelectionModel().setSelectionInterval(row, row);
+                        CacheDirectory.cleanParent(fileNode);
+                    }
+                } catch (Exception exception) {
+                    //ignore
+                }
+
+                if (fl != null) {
+                    try {
+                        fl.release();
+                        fl.channel().close();
+                    } catch (IOException e1) {
+                        e1.printStackTrace();
+                    }
+                }
+            }
+
+            private void updateRecentlyUsed(File f) {
+                File recentlyUsedFile = new File(location + File.separator + "recently_used");
+                PropertiesFile pf = new PropertiesFile(recentlyUsedFile);
+                pf.load();
+                Enumeration<Object> en = pf.keys();
+                while (en.hasMoreElements()) {
+                    String key = (String) en.nextElement();
+                    if (pf.get(key).equals(f.getAbsolutePath())) {
+                        pf.remove(key);
+                    }
+                }
+                pf.store();
+            }
+        });
+        buttons.add(deleteButton);
+
+        JButton refreshButton = new JButton(Translator.R("CVCPButRefresh"));
+        refreshButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                populateTable();
+            }
+        });
+        buttons.add(refreshButton);
+
+        JButton doneButton = new JButton(Translator.R("ButDone"));
+        doneButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                parent.dispose();
+            }
+        });
+
+        int maxWidth = 0;
+        int maxHeight = 0;
+        for (JButton button : buttons) {
+            maxWidth = Math.max(button.getMinimumSize().width, maxWidth);
+            maxHeight = Math.max(button.getMinimumSize().height, maxHeight);
+        }
+
+        int wantedWidth = maxWidth + 10;
+        int wantedHeight = maxHeight;
+        for (JButton button : buttons) {
+            button.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
+            leftPanel.add(button);
+        }
+
+        doneButton.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
+        rightPanel.add(doneButton);
+        buttonPanel.add(leftPanel);
+        buttonPanel.add(rightPanel);
+
+        return buttonPanel;
+    }
+
+    /**
+     * Populate the table with fresh data. Any manual updates to the cache
+     * directory will be updated in the table.
+     */
+    private void populateTable() {
+        ((DefaultTableModel) cacheTable.getModel()).setRowCount(0); //Clears the table
+        for (Object[] v : generateData(root))
+            ((DefaultTableModel) cacheTable.getModel()).addRow(v);
+    }
+
+    /**
+     * This creates the data for the table.
+     * 
+     * @param root The location of cache data.
+     * @return ArrayList containing an Object array of data for each row in the table.
+     */
+    private ArrayList<Object[]> generateData(DirectoryNode root) {
+        root = new DirectoryNode("Root", location, null);
+        CacheDirectory.getDirStructure(root);
+        ArrayList<Object[]> data = new ArrayList<Object[]>();
+
+        for (DirectoryNode identifier : root.getChildren()) {
+            for (DirectoryNode type : identifier.getChildren()) {
+                for (DirectoryNode domain : type.getChildren()) {
+                    for (DirectoryNode leaf : CacheDirectory.getLeafData(domain)) {
+                        Object[] o = { leaf,
+                                leaf.getFile().getAbsolutePath(),
+                                type,
+                                domain,
+                                leaf.getFile().length(),
+                                new SimpleDateFormat("MM/dd/yyyy").format(leaf.getFile().lastModified()) };
+                        data.add(o);
+                    }
+                }
+            }
+        }
+
+        return data;
+    }
+
+    /**
+     * Put focus onto default button.
+     */
+    public void focusOnDefaultButton() {
+        if (defaultFocusComponent != null) {
+            defaultFocusComponent.requestFocusInWindow();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java	(revision 403)
@@ -0,0 +1,119 @@
+/* CacheViewer.java -- Display the GUI for viewing and deleting cache files.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JDialog;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This class will provide a visual way of viewing cache.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class CacheViewer extends JDialog {
+
+    private boolean initialized = false;
+    private static final String dialogTitle = Translator.R("CVCPDialogTitle");
+    private DeploymentConfiguration config; // Configuration file which contains all the settings.
+    CachePane topPanel;
+
+    /**
+     * Creates a new instance of the cache viewer.
+     * 
+     * @param config Deployment configuration file.
+     */
+    public CacheViewer(DeploymentConfiguration config) {
+        super((Frame) null, dialogTitle, true); // Don't need a parent.
+        this.config = config;
+
+        /* Prepare for adding components to dialog box */
+        Container contentPane = getContentPane();
+        contentPane.setLayout(new GridBagLayout());
+
+        GridBagConstraints c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+        c.weightx = 1;
+        c.weighty = 1;
+        c.gridx = 0;
+        c.gridy = 0;
+        topPanel = new CachePane(this, this.config);
+        contentPane.add(topPanel, c);
+
+        pack();
+
+        /* Set focus to default button when first activated */
+        WindowAdapter adapter = new WindowAdapter() {
+            private boolean gotFocus = false;
+
+            public void windowGainedFocus(WindowEvent we) {
+                // Once window gets focus, set initial focus
+                if (!gotFocus) {
+                    topPanel.focusOnDefaultButton();
+                    gotFocus = true;
+                }
+            }
+        };
+        addWindowFocusListener(adapter);
+
+        initialized = true;
+    }
+
+    /**
+     * Display the cache viewer.
+     * 
+     * @param config Configuration file.
+     */
+    public static void showCacheDialog(final DeploymentConfiguration config) {
+        CacheViewer psd = new CacheViewer(config);
+        psd.setResizable(true);
+        psd.centerDialog();
+        psd.setVisible(true);
+        psd.dispose();
+    }
+
+    /**
+     * Check whether the dialog has finished being created.
+     * 
+     * @return True if dialog is ready to be displayed.
+     */
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * Center the dialog box.
+     */
+    private void centerDialog() {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = getSize();
+
+        setLocation((screen.width - dialogSize.width) / 2, (screen.height - dialogSize.height) / 2);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ComboItem.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ComboItem.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ComboItem.java	(revision 403)
@@ -0,0 +1,57 @@
+/* ComboItem.java -- Allow storage of an item whose name differs from its value.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+/**
+ * This is to be used with combobox items. Allows storing a value which differs
+ * from the key.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class ComboItem {
+    String text = null;
+    private String value; // Value to be compared with.
+
+    /**
+     * Create a new instance of combobox items.
+     * 
+     * @param text
+     *            Text to be displayed by JComboBox
+     * @param value
+     *            Value associated with this item.
+     */
+    public ComboItem(String text, String value) {
+        this.text = text;
+        this.value = value;
+    }
+
+    public String toString() {
+        return this.text;
+    }
+
+    /**
+     * Get the value associated with this item.
+     * 
+     * @return Associated value.
+     */
+    public String getValue() {
+        return this.value;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java	(revision 403)
@@ -0,0 +1,468 @@
+/* CommandLine.java -- command line interface to icedtea-web's deployment settings.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+package net.sourceforge.jnlp.controlpanel;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import net.sourceforge.jnlp.config.ConfiguratonValidator;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.config.Setting;
+
+/**
+ * Encapsulates a command line interface to the deployment configuration.
+ * <p>
+ * The central method is {@link #handle(String[])}, which calls one of the
+ * various 'handle' methods. The commands listed in {@link #allCommands} are
+ * supported. For each supported command, a method handleCOMMANDCommand exists.
+ * This method actually takes action based on the command. Generally, a
+ * printCOMMANDHelp method also exists, and prints out the help message for
+ * that specific command. For example, see {@link #handleListCommand(List)}
+ * and {@link #printListHelp()}.
+ * <p>
+ * Sample usage:
+ * <pre>
+ * CommandLine cli = new CommandLine();
+ * // the string array represents input using the command line
+ * int retVal = cli.handle(new String[] { "help" });
+ * if (retVal == CommandLine.SUCCESS) {
+ *    // good!
+ * } else {
+ *    // bad!
+ * }
+ * </pre>
+ *
+ * @author Omair Majid (omajid@redhat.com)
+ */
+public class CommandLine {
+
+    public static final int ERROR = 1;
+    public static final int SUCCESS = 0;
+
+    public final String PROGRAM_NAME;
+
+    private static final List<String> allCommands = Arrays.asList(new String[] {
+            "list", "get", "set", "reset", "info", "check"
+    });
+
+    DeploymentConfiguration config = null;
+
+    /**
+     * Creates a new instance
+     */
+    public CommandLine() {
+        PROGRAM_NAME = System.getProperty("icedtea-web.bin.name");
+
+        config = new DeploymentConfiguration();
+        try {
+            config.load(false);
+        } catch (ConfigurationException e) {
+            System.out.println(R("RConfigurationFatal"));
+        }
+    }
+
+    /**
+     * Handle the 'help' command
+     *
+     * @param args optional
+     * @return the result of handling the help command. SUCCESS if no errors occurred.
+     */
+    public int handleHelpCommand(List<String> args) {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " "
+                + allCommands.toString().replace(',', '|').replaceAll(" ", "") + " [help]");
+        System.out.println(R("CLHelpDescription", PROGRAM_NAME));
+        return SUCCESS;
+    }
+
+    /**
+     * Prints help message for the list command
+     */
+    public void printListHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " list [--details]");
+        System.out.println(R("CLListDescription"));
+    }
+
+    /**
+     * Handles the 'list' command
+     *
+     * @param args the arguments to the list command
+     * @return result of handling the command. SUCCESS if no errors occurred.
+     */
+    public int handleListCommand(List<String> args) {
+        if (args.contains("help")) {
+            printListHelp();
+            return SUCCESS;
+        }
+
+        boolean verbose = false;
+
+        if (args.contains("--details")) {
+            verbose = true;
+            args.remove("--details");
+        }
+
+        if (args.size() != 0) {
+            printListHelp();
+            return ERROR;
+        }
+
+        Map<String, Setting<String>> all = config.getRaw();
+        for (String key : all.keySet()) {
+            Setting<String> value = all.get(key);
+            System.out.println(key + ": " + value.getValue());
+            if (verbose) {
+                System.out.println("\t" + R("CLDescription", value.getDescription()));
+            }
+        }
+        return SUCCESS;
+    }
+
+    /**
+     * Prints help message for the get command
+     */
+    public void printGetHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " get property-name");
+        System.out.println(R("CLGetDescription"));
+    }
+
+    /**
+     * Handles the 'get' command.
+     *
+     * @param args the arguments to the get command
+     * @return an integer representing success (SUCCESS) or error handling the
+     * get command.
+     */
+    public int handleGetCommand(List<String> args) {
+        if (args.contains("help")) {
+            printGetHelp();
+            return SUCCESS;
+        }
+
+        if (args.size() != 1) {
+            printGetHelp();
+            return ERROR;
+        }
+
+        Map<String, Setting<String>> all = config.getRaw();
+
+        String key = args.get(0);
+        String value = null;
+        if (all.containsKey(key)) {
+            value = all.get(key).getValue();
+            System.out.println(value);
+            return SUCCESS;
+        } else {
+            System.out.println(R("CLUnknownProperty", key));
+            return ERROR;
+        }
+    }
+
+    /**
+     * Prints the help message for the 'set' command
+     */
+    public void printSetHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " set property-name value");
+        System.out.println(R("CLSetDescription"));
+    }
+
+    /**
+     * Handles the 'set' command
+     *
+     * @param args the arguments to the set command
+     * @return an integer indicating success (SUCCESS) or error in handling
+     * the command
+     */
+    public int handleSetCommand(List<String> args) {
+        if (args.contains("help")) {
+            printSetHelp();
+            return SUCCESS;
+        }
+
+        if (args.size() != 2) {
+            printSetHelp();
+            return ERROR;
+        }
+
+        String key = args.get(0);
+        String value = args.get(1);
+
+        if (config.getRaw().containsKey(key)) {
+            Setting<String> old = config.getRaw().get(key);
+            if (old.getValidator() != null) {
+                try {
+                    old.getValidator().validate(value);
+                } catch (IllegalArgumentException e) {
+                    System.out.println(R("CLIncorrectValue", old.getName(), value, old.getValidator().getPossibleValues()));
+                    return ERROR;
+                }
+            }
+            config.setProperty(key, value);
+        } else {
+            System.out.println(R("CLWarningUnknownProperty", key));
+            config.setProperty(key, value);
+        }
+
+        try {
+            config.save();
+        } catch (IOException e) {
+            e.printStackTrace();
+            return ERROR;
+        }
+
+        return SUCCESS;
+    }
+
+    /**
+     * Prints a help message for the reset command
+     */
+    public void printResetHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " reset [all|property-name]");
+        System.out.println(R("CLResetDescription"));
+    }
+
+    /**
+     * Handles the 'reset' command
+     *
+     * @param args the arguments to the reset command
+     * @return an integer indicating success (SUCCESS) or error in handling
+     * the command
+     */
+    public int handleResetCommand(List<String> args) {
+        if (args.contains("help")) {
+            printResetHelp();
+            return SUCCESS;
+        }
+
+        if (args.size() != 1) {
+            printResetHelp();
+            return ERROR;
+        }
+
+        String key = args.get(0);
+
+        boolean resetAll = false;
+        if (key.equals("all")) {
+            resetAll = true;
+        }
+
+        Map<String, Setting<String>> all = config.getRaw();
+        if (!resetAll && !all.containsKey(key)) {
+            System.out.println(R("CLUnknownProperty", key));
+            return ERROR;
+        }
+
+        if (resetAll) {
+            for (String aKey: all.keySet()) {
+                Setting<String> setting = all.get(aKey);
+                setting.setValue(setting.getDefaultValue());
+            }
+        } else {
+            Setting<String> setting = all.get(key);
+            setting.setValue(setting.getDefaultValue());
+        }
+
+        try {
+            config.save();
+        } catch (IOException e) {
+            e.printStackTrace();
+            return ERROR;
+        }
+
+        return SUCCESS;
+    }
+
+    /**
+     * Print a help message for the 'info' command
+     */
+    public void printInfoHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " info property-name");
+        System.out.println(R("CLInfoDescription"));
+    }
+
+    /**
+     * Handles the 'info' command
+     *
+     * @param args the arguments to the info command
+     * @return an integer indicating success (SUCCESS) or error in handling
+     * the command
+     */
+    public int handleInfoCommand(List<String> args) {
+        if (args.contains("help")) {
+            printInfoHelp();
+            return SUCCESS;
+        }
+
+        if (args.size() != 1) {
+            printInfoHelp();
+            return ERROR;
+        }
+
+        Map<String, Setting<String>> all = config.getRaw();
+
+        String key = args.get(0);
+        Setting<String> value = all.get(key);
+        if (value == null) {
+            System.out.println(R("CLNoInfo"));
+            return ERROR;
+        } else {
+            System.out.println(R("CLDescription", value.getDescription()));
+            System.out.println(R("CLValue", value.getValue()));
+            if (value.getValidator() != null) {
+                System.out.println("\t" + R("VVPossibleValues", value.getValidator().getPossibleValues()));
+            }
+            System.out.println(R("CLValueSource", value.getSource()));
+            return SUCCESS;
+        }
+    }
+
+    /**
+     * Prints a help message for the 'check' command
+     */
+    public void printCheckHelp() {
+        System.out.println(R("Usage"));
+        System.out.println("  " + PROGRAM_NAME + " check");
+        System.out.println(R("CLCheckDescription"));
+    }
+
+    /**
+     * Handles the 'check' command
+     *
+     * @param args the arguments to the check command.
+     * @return an integer indicating success (SUCCESS) or error in handling
+     * the command
+     */
+    public int handleCheckCommand(List<String> args) {
+        if (args.contains("help")) {
+            printCheckHelp();
+            return SUCCESS;
+        }
+
+        if (args.size() != 0) {
+            printCheckHelp();
+            return ERROR;
+        }
+
+        Map<String, Setting<String>> all = config.getRaw();
+
+        ConfiguratonValidator validator = new ConfiguratonValidator(all);
+        validator.validate();
+
+        boolean allValid = true;
+        for (Setting<String> setting : validator.getIncorrectSetting()) {
+            System.out.println(R("CLIncorrectValue", setting.getName(), setting.getValue(), setting.getValidator().getPossibleValues()));
+            allValid = false;
+        }
+
+        for (Setting<String> setting : validator.getUnrecognizedSetting()) {
+            System.out.println(R("CLUnknownProperty", setting.getName()));
+            allValid = false;
+        }
+
+        if (allValid) {
+            System.out.println(R("CLNoIssuesFound"));
+            return SUCCESS;
+        } else {
+            return ERROR;
+        }
+    }
+
+    /**
+     * Handles overall command line arguments. The argument array is split
+     * into two pieces: the first element is assumend to be the command, and
+     * everything after is taken to be the argument to the command.
+     *
+     * @param commandAndArgs A string array representing the command and
+     * arguments to take action on
+     * @return an integer representing an error code or SUCCESS if no problems
+     * occurred.
+     */
+    public int handle(String[] commandAndArgs) {
+
+        if (commandAndArgs == null) {
+            throw new NullPointerException("command is null");
+        }
+
+        if (commandAndArgs.length == 0) {
+            handleHelpCommand(new ArrayList<String>());
+            return ERROR;
+        }
+
+        String command = commandAndArgs[0];
+        String[] argsArray = new String[commandAndArgs.length - 1];
+        System.arraycopy(commandAndArgs, 1, argsArray, 0, commandAndArgs.length - 1);
+        List<String> arguments = new ArrayList<String>(Arrays.asList(argsArray));
+
+        int val;
+        if (command.equals("help")) {
+            val = handleHelpCommand(arguments);
+        } else if (command.equals("list")) {
+            val = handleListCommand(arguments);
+        } else if (command.equals("set")) {
+            val = handleSetCommand(arguments);
+        } else if (command.equals("reset")) {
+            val = handleResetCommand(arguments);
+        } else if (command.equals("get")) {
+            val = handleGetCommand(arguments);
+        } else if (command.equals("info")) {
+            val = handleInfoCommand(arguments);
+        } else if (command.equals("check")) {
+            val = handleCheckCommand(arguments);
+        } else if (allCommands.contains(command)) {
+            System.out.println("INTERNAL ERROR: " + command + " should have been implemented");
+            val = ERROR;
+        } else {
+            System.out.println(R("CLUnknownCommand", command));
+            handleHelpCommand(new ArrayList<String>());
+            val = ERROR;
+        }
+
+        return val;
+    }
+
+    /**
+     * The starting point of the program
+     * @param args the command line arguments to this program
+     */
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            ControlPanel.main(new String[] {});
+        } else {
+            CommandLine cli = new CommandLine();
+            int result = cli.handle(args);
+
+            // instead of returning, use System.exit() so we can pass back
+            // error codes indicating success or failure. Otherwise using
+            // this program for scripting will become much more challenging
+            System.exit(result);
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java	(revision 403)
@@ -0,0 +1,389 @@
+/* ControlPanel.java -- Display the control panel for modifying deployment settings.
+Copyright (C) 2011 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.naming.ConfigurationException;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.WindowConstants;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+import net.sourceforge.jnlp.security.KeyStores;
+import net.sourceforge.jnlp.security.viewer.CertificatePane;
+
+/**
+ * This is the control panel for Java. It provides a GUI for modifying the
+ * deployments.properties file.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class ControlPanel extends JFrame {
+
+    /**
+     * Class for keeping track of the panels and their associated text.
+     * 
+     * @author @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+     * 
+     */
+    private static class SettingsPanel {
+        final String value;
+        final JPanel panel;
+
+        public SettingsPanel(String value, JPanel panel) {
+            this.value = value;
+            this.panel = panel;
+        }
+
+        public JPanel getPanel() {
+            return panel;
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+    }
+
+    private DeploymentConfiguration config = null;
+
+    /**
+     * Creates a new instance of the ControlPanel.
+     * 
+     * @param config
+     *            Loaded DeploymentsConfiguration file.
+     * 
+     */
+    public ControlPanel(DeploymentConfiguration config) {
+        super();
+        setTitle(Translator.R("CPHead"));
+
+        this.config = config;
+
+        JPanel topPanel = createTopPanel();
+        JPanel mainPanel = createMainSettingsPanel();
+        JPanel buttonPanel = createButtonPanel();
+
+        add(topPanel, BorderLayout.PAGE_START);
+        add(mainPanel, BorderLayout.CENTER);
+        add(buttonPanel, BorderLayout.PAGE_END);
+        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        pack();
+        setMinimumSize(getPreferredSize());
+    }
+
+    private JPanel createTopPanel() {
+        Font currentFont = null;
+        JLabel about = new JLabel(R("CPMainDescriptionShort"));
+        currentFont = about.getFont();
+        about.setFont(currentFont.deriveFont(currentFont.getSize2D() + 2));
+        currentFont = about.getFont();
+        about.setFont(currentFont.deriveFont(Font.BOLD));
+
+        JLabel description = new JLabel(R("CPMainDescriptionLong"));
+        description.setBorder(new EmptyBorder(2, 0, 2, 0));
+
+        JPanel descriptionPanel = new JPanel(new GridLayout(0, 1));
+        descriptionPanel.setBackground(UIManager.getColor("TextPane.background"));
+        descriptionPanel.add(about);
+        descriptionPanel.add(description);
+
+        JLabel image = new JLabel();
+
+        ClassLoader cl = getClass().getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        try {
+            URL imgUrl = cl.getResource("net/sourceforge/jnlp/resources/netx-icon.png");
+            image.setIcon(new ImageIcon(ImageIO.read(imgUrl)));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        JPanel topPanel = new JPanel(new BorderLayout());
+        topPanel.setBackground(UIManager.getColor("TextPane.background"));
+        topPanel.add(descriptionPanel, BorderLayout.LINE_START);
+        topPanel.add(image, BorderLayout.LINE_END);
+        topPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+        return topPanel;
+    }
+
+    /**
+     * Creates the "ok" "apply" and "cancel" buttons.
+     * 
+     * @return A panel with the "ok" "apply" and "cancel" button.
+     */
+    private JPanel createButtonPanel() {
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
+
+        List<JButton> buttons = new ArrayList<JButton>();
+
+        JButton okButton = new JButton(Translator.R("ButOk"));
+        okButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                ControlPanel.this.saveConfiguration();
+                ControlPanel.this.dispose();
+            }
+        });
+        buttons.add(okButton);
+
+        JButton applyButton = new JButton(Translator.R("ButApply"));
+        applyButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                ControlPanel.this.saveConfiguration();
+            }
+        });
+        buttons.add(applyButton);
+
+        JButton cancelButton = new JButton(Translator.R("ButCancel"));
+        cancelButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                ControlPanel.this.dispose();
+            }
+        });
+        buttons.add(cancelButton);
+
+        int maxWidth = 0;
+        int maxHeight = 0;
+        for (JButton button : buttons) {
+            maxWidth = Math.max(button.getMinimumSize().width, maxWidth);
+            maxHeight = Math.max(button.getMinimumSize().height, maxHeight);
+        }
+
+        int wantedWidth = maxWidth + 10;
+        int wantedHeight = maxHeight + 2;
+        for (JButton button : buttons) {
+            button.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
+            buttonPanel.add(button);
+        }
+
+        return buttonPanel;
+    }
+
+    /**
+     * Add the different settings panels to the GUI.
+     * 
+     * @return A panel with all the components in place.
+     */
+    private JPanel createMainSettingsPanel() {
+
+        SettingsPanel[] panels = new SettingsPanel[] { new SettingsPanel(Translator.R("CPTabAbout"), createAboutPanel()),
+                new SettingsPanel(Translator.R("CPTabCache"), createCacheSettingsPanel()),
+                new SettingsPanel(Translator.R("CPTabCertificate"), createCertificatesSettingsPanel()),
+                // TODO: This is commented out since this is not implemented yet
+                // new SettingsPanel(Translator.R("CPTabClassLoader"), createClassLoaderSettingsPanel()),
+                new SettingsPanel(Translator.R("CPTabDebugging"), createDebugSettingsPanel()),
+                new SettingsPanel(Translator.R("CPTabDesktopIntegration"), createDesktopSettingsPanel()),
+                new SettingsPanel(Translator.R("CPTabNetwork"), createNetworkSettingsPanel()),
+                // TODO: This is commented out since this is not implemented yet
+                // new SettingsPanel(Translator.R("CPTabRuntimes"), createRuntimesSettingsPanel()),
+                new SettingsPanel(Translator.R("CPTabSecurity"), createSecuritySettingsPanel()), };
+
+        // Add panels.
+        final JPanel settingsPanel = new JPanel(new CardLayout());
+
+        // Calculate largest minimum size we should use.
+        int height = 0;
+        int width = 0;
+        for (SettingsPanel panel : panels) {
+            JPanel p = panel.getPanel();
+            Dimension d = p.getMinimumSize();
+            if (d.height > height)
+                height = d.height;
+            if (d.width > width)
+                width = d.width;
+        }
+        Dimension dim = new Dimension(width, height);
+
+        for (SettingsPanel panel : panels) {
+            JPanel p = panel.getPanel();
+            p.setPreferredSize(dim);
+            settingsPanel.add(p, panel.toString());
+        }
+
+        final JList settingsList = new JList(panels);
+        settingsList.addListSelectionListener(new ListSelectionListener() {
+            @Override
+            public void valueChanged(ListSelectionEvent e) {
+                JList list = (JList) e.getSource();
+                SettingsPanel panel = (SettingsPanel) list.getSelectedValue();
+                CardLayout cl = (CardLayout) settingsPanel.getLayout();
+                cl.show(settingsPanel, panel.toString());
+            }
+        });
+        JScrollPane settingsListScrollPane = new JScrollPane(settingsList);
+        settingsListScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+
+        final JPanel settingsDetailPanel = new JPanel();
+        settingsDetailPanel.setLayout(new BorderLayout());
+        settingsDetailPanel.add(settingsPanel, BorderLayout.CENTER);
+        settingsDetailPanel.setBorder(new EmptyBorder(0, 5, -3, 0));
+
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(settingsListScrollPane, BorderLayout.LINE_START);
+        mainPanel.add(settingsDetailPanel, BorderLayout.CENTER);
+        mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+        settingsList.setSelectedIndex(0);
+
+        return mainPanel;
+    }
+
+    private JPanel createAboutPanel() {
+        return new AboutPanel();
+    }
+
+    private JPanel createCacheSettingsPanel() {
+        return new TemporaryInternetFilesPanel(this.config);
+    }
+
+    private JPanel createCertificatesSettingsPanel() {
+        JPanel p = new NamedBorderPanel(Translator.R("CPHeadCertificates"), new BorderLayout());
+        p.add(new CertificatePane(null), BorderLayout.CENTER);
+        return p;
+    }
+
+    private JPanel createClassLoaderSettingsPanel() {
+        return createNotImplementedPanel();
+    }
+
+    private JPanel createDebugSettingsPanel() {
+        return new DebuggingPanel(this.config);
+    }
+
+    private JPanel createDesktopSettingsPanel() {
+        return new DesktopShortcutPanel(this.config);
+    }
+
+    private JPanel createNetworkSettingsPanel() {
+        return new NetworkSettingsPanel(this.config);
+    }
+
+    private JPanel createRuntimesSettingsPanel() {
+        return new JREPanel();
+    }
+
+    private JPanel createSecuritySettingsPanel() {
+        return new SecuritySettingsPanel(this.config);
+    }
+
+    /**
+     * This is a placeholder panel.
+     * 
+     * @return
+     */
+    private JPanel createNotImplementedPanel() {
+
+        JPanel notImplementedPanel = new NamedBorderPanel("Unimplemented");
+        notImplementedPanel.setLayout(new BorderLayout());
+
+        ClassLoader cl = getClass().getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        URL imgUrl = cl.getResource("net/sourceforge/jnlp/resources/warning.png");
+        Image img;
+        try {
+            img = ImageIO.read(imgUrl);
+            ImageIcon icon = new ImageIcon(img);
+            JLabel label = new JLabel("Not Implemented", icon, SwingConstants.CENTER);
+            notImplementedPanel.add(label);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return notImplementedPanel;
+    }
+
+    /**
+     * Save the configuration changes.
+     */
+    private void saveConfiguration() {
+        try {
+            config.save();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        final DeploymentConfiguration config = new DeploymentConfiguration();
+        try {
+            config.load();
+        } catch (ConfigurationException e) {
+            // FIXME inform user about this and exit properly
+            // the only known condition under which this can happen is when a
+            // required system configuration file is not found
+
+            // if configuration is not loaded, we will get NullPointerExceptions
+            // everywhere
+            e.printStackTrace();
+        }
+
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e) {
+            // ignore; not a big deal
+        }
+
+        KeyStores.setConfiguration(config);
+
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                final ControlPanel editor = new ControlPanel(config);
+                editor.setVisible(true);
+            }
+        });
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java	(revision 403)
@@ -0,0 +1,150 @@
+/* DebuggingPanel.java -- Displays and sets options for debugging.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This displays the options related to debugging.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class DebuggingPanel extends NamedBorderPanel implements ItemListener {
+
+    /** List of properties used by this panel */
+    public static String[] properties = { "deployment.trace", // Debugging
+            "deployment.log", // Debugging
+            "deployment.console.startup.mode", // Java Console
+    };
+    private DeploymentConfiguration config;
+
+    /**
+     * Create a new instance of the debugging panel.
+     * 
+     * @param config
+     *            loaded DeploymentConfiguration file.
+     */
+    public DebuggingPanel(DeploymentConfiguration config) {
+        super(Translator.R("CPHeadDebugging"), new GridBagLayout());
+
+        this.config = config;
+
+        addComponents();
+    }
+
+    /**
+     * Add components to panel.
+     */
+    private void addComponents() {
+        GridBagConstraints c = new GridBagConstraints();
+
+        JLabel debuggingDescription = new JLabel("<html>" + Translator.R("CPDebuggingDescription") + "<hr /><br /></html>");
+
+        JCheckBox[] debuggingOptions = { new JCheckBox(Translator.R("DPEnableTracing")),
+                new JCheckBox(Translator.R("DPEnableLogging")), };
+
+        ComboItem[] javaConsoleItems = { new ComboItem(Translator.R("DPDisable"), "DISABLE"),
+                new ComboItem(Translator.R("DPHide"), "HIDE"),
+                new ComboItem(Translator.R("DPShow"), "SHOW"), };
+
+        JLabel consoleLabel = new JLabel(Translator.R("DPJavaConsole"));
+        JComboBox consoleComboBox = new JComboBox();
+        consoleComboBox.setActionCommand("deployment.console.startup.mode"); // The property this comboBox affects.
+
+        JPanel consolePanel = new JPanel();
+        consolePanel.setLayout(new FlowLayout(FlowLayout.LEADING));
+        consolePanel.add(consoleLabel);
+        consolePanel.add(consoleComboBox);
+
+        c.fill = GridBagConstraints.BOTH;
+        c.weightx = 1;
+        c.gridx = 0;
+        c.gridy = 0;
+        add(debuggingDescription, c);
+
+        /*
+         * Add the items to the panel unless we can not get the values for them.
+         */
+        for (int i = 0; i < properties.length; i++) {
+            try {
+                String s = config.getProperty(properties[i]);
+                c.gridy = i + 1;
+
+                switch (i) {
+                    case 0:
+                    case 1:
+                        debuggingOptions[i].setSelected(Boolean.parseBoolean(s));
+                        debuggingOptions[i].setActionCommand(properties[i]);
+                        debuggingOptions[i].addItemListener(this);
+                        add(debuggingOptions[i], c);
+                        break;
+                    case 2:
+                        for (int j = 0; j < javaConsoleItems.length; j++) {
+                            consoleComboBox.addItem(javaConsoleItems[j]);
+                            if (config.getProperty("deployment.console.startup.mode").equals(javaConsoleItems[j].getValue()))
+                                consoleComboBox.setSelectedIndex(j);
+                        }
+                        consoleComboBox.addItemListener(this);
+                        add(consolePanel, c);
+                }
+
+            } catch (Exception e) {
+                debuggingOptions[i] = null;
+            }
+        }
+
+        // pack the bottom so that it doesn't change size if resized.
+        Component filler = Box.createRigidArea(new Dimension(1, 1));
+        c.gridy++;
+        c.weighty = 1;
+        add(filler, c);
+    }
+
+    @Override
+    public void itemStateChanged(ItemEvent e) {
+
+        Object o = e.getSource();
+
+        if (o instanceof JCheckBox) {
+            JCheckBox jcb = (JCheckBox) o;
+            config.setProperty(jcb.getActionCommand(), String.valueOf(jcb.isSelected()));
+        } else if (o instanceof JComboBox) {
+            JComboBox jcb = (JComboBox) o;
+            ComboItem c = (ComboItem) e.getItem();
+            config.setProperty(jcb.getActionCommand(), c.getValue());
+        }
+
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java	(revision 403)
@@ -0,0 +1,100 @@
+/* DesktopShortcutPanel.java -- Display option for adding desktop shortcut.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+import javax.swing.Box;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This class provides the panel that allows the user to set whether they want
+ * to create a desktop shortcut for javaws.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class DesktopShortcutPanel extends NamedBorderPanel implements ItemListener {
+
+    private DeploymentConfiguration config;
+
+    /**
+     * Create a new instance of the desktop shortcut settings panel.
+     * 
+     * @param config
+     *            Loaded DeploymentConfiguration file.
+     */
+    public DesktopShortcutPanel(DeploymentConfiguration config) {
+        super(Translator.R("CPHeadDesktopIntegration"), new GridBagLayout());
+        this.config = config;
+
+        addComponents();
+    }
+
+    /**
+     * Add components to panel.
+     */
+    private void addComponents() {
+        GridBagConstraints c = new GridBagConstraints();
+        JLabel description = new JLabel("<html>" + Translator.R("CPDesktopIntegrationDescription") + "<hr /></html>");
+        JComboBox shortcutComboOptions = new JComboBox();
+        ComboItem[] items = { new ComboItem(Translator.R("DSPNeverCreate"), "NEVER"),
+                new ComboItem(Translator.R("DSPAlwaysAllow"), "ALWAYS"),
+                new ComboItem(Translator.R("DSPAskUser"), "ASK_USER"),
+                new ComboItem(Translator.R("DSPAskIfHinted"), "ASK_IF_HINTED"),
+                new ComboItem(Translator.R("DSPAlwaysIfHinted"), "ALWAYS_IF_HINTED") };
+
+        shortcutComboOptions.setActionCommand("deployment.javaws.shortcut"); // The configuration property this combobox affects.
+        for (int j = 0; j < items.length; j++) {
+            shortcutComboOptions.addItem(items[j]);
+            if (config.getProperty("deployment.javaws.shortcut").equals(items[j].getValue()))
+                shortcutComboOptions.setSelectedIndex(j);
+        }
+
+        shortcutComboOptions.addItemListener(this);
+
+        c.fill = GridBagConstraints.BOTH;
+        c.weightx = 1;
+        c.gridx = 0;
+        c.gridy = 0;
+        add(description, c);
+        c.gridy = 1;
+        add(shortcutComboOptions, c);
+
+        // This is to keep it from expanding vertically if resized.
+        Component filler = Box.createRigidArea(new Dimension(1, 1));
+        c.gridy++;
+        c.weighty = 1;
+        add(filler, c);
+    }
+
+    public void itemStateChanged(ItemEvent e) {
+        ComboItem c = (ComboItem) e.getItem();
+        config.setProperty(((JComboBox) e.getSource()).getActionCommand(), c.getValue());
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DocumentAdapter.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DocumentAdapter.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/DocumentAdapter.java	(revision 403)
@@ -0,0 +1,102 @@
+/* DocumentAdapter.java -- Updates properties.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package net.sourceforge.jnlp.controlpanel;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+
+/**
+ * Updates the property as it happens.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ *
+ */
+public class DocumentAdapter implements DocumentListener {
+
+    String[] fields;
+    int index;
+    String property;
+    DeploymentConfiguration config;
+    int mode;
+
+    /**
+     * This creates a new instance of DocumentAdapter.
+     * 
+     * @param fields The list of property.
+     * @param index Location of property to modify.
+     */
+    public DocumentAdapter(String[] fields, int index) {
+        this.fields = fields;
+        this.index = index;
+        mode = 1;
+    }
+
+    /**
+     * This creates a new instance of DocumentAdapter. This allows modifying 
+     * the configuration directly.
+     * 
+     * @param config ConfigurationFile containing the properties.
+     * @param property Name of property to modify.
+     */
+    public DocumentAdapter(DeploymentConfiguration config, String property) {
+        this.property = property;
+        this.config = config;
+        mode = 2;
+    }
+
+    @Override
+    public void insertUpdate(DocumentEvent e) {
+        update(e);
+    }
+
+    @Override
+    public void removeUpdate(DocumentEvent e) {
+        update(e);
+    }
+
+    @Override
+    public void changedUpdate(DocumentEvent e) {
+
+    }
+
+    /**
+     * Update the property as on the appropriate items.
+     * 
+     * @param e The event that caused the call.
+     */
+    private void update(DocumentEvent e) {
+        Document d = e.getDocument();
+        try {
+            String value = d.getText(0, d.getLength()).trim();
+            value = (value.length() == 0) ? null : value;
+            if (mode == 1) {
+                fields[index] = value;
+            } else if (mode == 2) {
+                config.setProperty(property, value);
+            }
+        } catch (BadLocationException e1) {
+            // TODO Auto-generated catch block
+            e1.printStackTrace();
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/JREPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/JREPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/JREPanel.java	(revision 403)
@@ -0,0 +1,47 @@
+/* JREPanel.java - Displays option for changing to another Java Runtime.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JLabel;
+
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This panel is to allow access to setting the JRE but we currently do not
+ * support this.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class JREPanel extends NamedBorderPanel {
+
+    /**
+     * Creates a new instance of the JRE settings panel. (Currently not
+     * supported).
+     */
+    public JREPanel() {
+        super(Translator.R("CPHeadJRESettings"));
+        setLayout(new BorderLayout());
+
+        JLabel jreLabel = new JLabel("<html>" + Translator.R("CPJRESupport") + "</html>");
+        add(jreLabel, BorderLayout.NORTH);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NamedBorderPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NamedBorderPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NamedBorderPanel.java	(revision 403)
@@ -0,0 +1,60 @@
+/* NamedBorderPanel.java -- Makes a border which has a name.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.LayoutManager;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+
+/**
+ * This class provides the a panel that has a border with the name specified.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+public class NamedBorderPanel extends JPanel {
+
+    /**
+     * Creates a new instance of JPanel with a named border and specified
+     * layout.
+     * 
+     * @param title
+     *            Name to be displayed.
+     * @param layout
+     *            Layout to use with this panel.
+     */
+    public NamedBorderPanel(String title, LayoutManager layout) {
+        this(title);
+        setLayout(layout);
+    }
+
+    /**
+     * Creates a new instance of JPanel with a named border.
+     * 
+     * @param title
+     *            Name to be displayed.
+     */
+    public NamedBorderPanel(String title) {
+        super();
+        setBorder(BorderFactory.createCompoundBorder(
+                BorderFactory.createTitledBorder(title),
+                BorderFactory.createEmptyBorder(5, 5, 5, 5)));
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/NetworkSettingsPanel.java	(revision 403)
@@ -0,0 +1,301 @@
+/* NetworkSettingsPanel.java -- Sets proxy settings for network.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+
+import javax.swing.Box;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.PlainDocument;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This is the pane used with creating a JDialog version. This allows changing
+ * the network configuration: Proxy
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+@SuppressWarnings("serial")
+public class NetworkSettingsPanel extends JPanel implements ActionListener {
+
+    private DeploymentConfiguration config;
+
+    private JPanel description;
+    private ArrayList<JPanel> proxyPanels = new ArrayList<JPanel>(); // The stuff with editable fields
+
+    /** List of properties used by this panel */
+    public static String[] properties = { "deployment.proxy.type",
+            "deployment.proxy.http.host",
+            "deployment.proxy.http.port",
+            "deployment.proxy.bypass.local",
+            "deployment.proxy.auto.config.url", };
+
+    /**
+     * Creates a new instance of the network settings panel.
+     * 
+     * @param config
+     *            Loaded DeploymentConfiguration file.
+     */
+    public NetworkSettingsPanel(DeploymentConfiguration config) {
+        super();
+        this.config = config;
+        setLayout(new BorderLayout());
+
+        addComponents();
+    }
+
+    /**
+     * This adds the components to the panel.
+     */
+    protected void addComponents() {
+        JPanel settingPanel = new NamedBorderPanel(Translator.R("CPHeadNetworkSettings"));
+        settingPanel.setLayout(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+        c.weightx = 1;
+        c.weighty = 1;
+        c.gridx = 0;
+
+        JLabel networkDesc = new JLabel("<html>" + Translator.R("CPNetworkSettingsDescription") + "<hr /></html>");
+
+        JLabel[] description = { new JLabel("<html>" + Translator.R("NSDescription-1") + "</html>"),
+                new JLabel("<html>" + Translator.R("NSDescription0") + "</html>"),
+                new JLabel("<html>" + Translator.R("NSDescription1") + "</html>"),
+                new JLabel("<html>" + Translator.R("NSDescription2") + "</html>"),
+                new JLabel("<html>" + Translator.R("NSDescription3") + "</html>") };
+
+        this.description = new JPanel(new CardLayout());
+        for (int i = 0; i < description.length; i++)
+            this.description.add(description[i], String.valueOf(i - 1));
+
+        // Settings for selecting Proxy Server
+        JPanel proxyServerPanel = new JPanel(new GridLayout(0, 1));
+        JPanel proxyLocationPanel = new JPanel(new GridBagLayout());
+        JPanel proxyBypassPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
+
+        JLabel addressLabel = new JLabel(Translator.R("NSAddress") + ":");
+        JLabel portLabel = new JLabel(Translator.R("NSPort") + ":");
+        final JTextField addressField = new JTextField(config.getProperty(properties[1]), 10);
+        addressField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[1]));
+
+        final JTextField portField = new JTextField(5);
+        portField.setDocument(NetworkSettingsPanel.getPortNumberDocument());
+        portField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[2]));
+        portField.setText(config.getProperty(properties[2]));
+
+        // Create the button which allows setting of other types of proxy.
+        JButton advancedProxyButton = new JButton(Translator.R("NSAdvanced") + "...");
+        advancedProxyButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                AdvancedProxySettingsDialog.showAdvancedProxySettingsDialog(config);
+                addressField.setText(config.getProperty(properties[1]));
+                portField.setText(config.getProperty(properties[2]));
+            }
+        });
+
+        JCheckBox bypassCheckBox = new JCheckBox(Translator.R("NSBypassLocal"), Boolean.parseBoolean(config.getProperty(properties[3])));
+        bypassCheckBox.addItemListener(new ItemListener() {
+            @Override
+            public void itemStateChanged(ItemEvent e) {
+                config.setProperty(properties[3], String.valueOf(e.getStateChange() == ItemEvent.SELECTED));
+            }
+        });
+        c.gridy = 0;
+        c.gridx = GridBagConstraints.RELATIVE;
+        c.weightx = 0;
+        proxyLocationPanel.add(Box.createHorizontalStrut(20), c);
+        proxyLocationPanel.add(addressLabel, c);
+        c.weightx = 1;
+        proxyLocationPanel.add(addressField, c);
+        c.weightx = 0;
+        proxyLocationPanel.add(portLabel, c);
+        c.weightx = 1;
+        proxyLocationPanel.add(portField, c);
+        c.weightx = 0;
+        proxyLocationPanel.add(advancedProxyButton, c);
+        proxyBypassPanel.add(Box.createHorizontalStrut(5));
+        proxyBypassPanel.add(bypassCheckBox);
+
+        proxyServerPanel.add(proxyLocationPanel);
+        proxyServerPanel.add(proxyBypassPanel);
+
+        JRadioButton directConnection = new JRadioButton(Translator.R("NSDirectConnection"), config.getProperty(properties[0]).equals("0"));
+        directConnection.setActionCommand("0");
+        directConnection.addActionListener(this);
+
+        JRadioButton useProxyServer = new JRadioButton(Translator.R("NSManualProxy"), config.getProperty(properties[0]).equals("1"));
+        useProxyServer.setActionCommand("1");
+        useProxyServer.addActionListener(this);
+
+        JRadioButton useAutoProxyConfigScript = new JRadioButton(Translator.R("NSAutoProxy"), config.getProperty(properties[0]).equals("2"));
+        useAutoProxyConfigScript.setActionCommand("2");
+        useAutoProxyConfigScript.addActionListener(this);
+
+        JRadioButton useBrowserSettings = new JRadioButton(Translator.R("NSBrowserProxy"), config.getProperty(properties[0]).equals("3"));
+        useBrowserSettings.setActionCommand("3");
+        useBrowserSettings.addActionListener(this);
+
+        ButtonGroup modeSelect = new ButtonGroup();
+        modeSelect.add(useBrowserSettings);
+        modeSelect.add(useProxyServer);
+        modeSelect.add(useAutoProxyConfigScript);
+        modeSelect.add(directConnection);
+
+        // Settings for Automatic Proxy Configuration Script
+        JPanel proxyAutoPanel = new JPanel(new GridBagLayout());
+        JLabel locationLabel = new JLabel(Translator.R("NSScriptLocation") + ":");
+        final JTextField locationField = new JTextField(config.getProperty(properties[4]), 20);
+        locationField.getDocument().addDocumentListener(new DocumentAdapter(config, properties[4]));
+
+        c.gridx = 0;
+        proxyAutoPanel.add(Box.createHorizontalStrut(20), c);
+        c.gridx = GridBagConstraints.RELATIVE;
+        proxyAutoPanel.add(locationLabel, c);
+        c.weightx = 1;
+        proxyAutoPanel.add(locationField, c);
+
+        c.weighty = 0;
+        c.gridx = 0;
+        c.gridy = 0;
+        settingPanel.add(networkDesc, c);
+        c.gridy = 1;
+        settingPanel.add(this.description, c);
+        c.gridy = 2;
+        settingPanel.add(directConnection, c);
+        c.gridy = 3;
+        settingPanel.add(useBrowserSettings, c);
+        c.gridy = 4;
+        settingPanel.add(useProxyServer, c);
+        c.gridy = 5;
+        settingPanel.add(proxyServerPanel, c);
+        proxyPanels.add(proxyServerPanel);
+        c.gridy = 6;
+        settingPanel.add(useAutoProxyConfigScript, c);
+        c.gridy = 7;
+        settingPanel.add(proxyAutoPanel, c);
+        proxyPanels.add(proxyAutoPanel);
+
+        // Filler to pack the bottom of the panel.
+        Component filler = Box.createRigidArea(new Dimension(1, 1));
+        c.gridy++;
+        c.weighty = 1;
+        settingPanel.add(filler, c);
+
+        setState(); // depending on default setting we will enable or disable
+
+        add(settingPanel, BorderLayout.CENTER);
+
+    }
+
+    /**
+     * Enable/Disable the panel and all its children recursively.
+     * 
+     * @param panel
+     *            JPanel which needs to be enabled or disabled.
+     * @param enable
+     *            true if the panel and its children are to be enabled, false
+     *            otherwise.
+     */
+    private void enablePanel(JPanel panel, boolean enable) {
+        // This will be used to enable all components in this panel recursively.
+        // Ridiculously slow if lots of nested panels.
+        for (Component c : panel.getComponents()) {
+            if (c instanceof JPanel) {
+                enablePanel((JPanel) c, enable);
+            }
+            c.setEnabled(enable);
+        }
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        config.setProperty(properties[0], e.getActionCommand());
+        setState();
+    }
+
+    /**
+     * This enables and disables the appropriate panels.
+     */
+    private void setState() {
+        ((CardLayout) this.description.getLayout()).show(this.description, config.getProperty(properties[0]));
+        if (config.getProperty(properties[0]).equals("0")) {
+            for (JPanel panel : proxyPanels)
+                enablePanel(panel, false);
+        } else if (config.getProperty(properties[0]).equals("1")) {
+            enablePanel(proxyPanels.get(1), false);
+            enablePanel(proxyPanels.get(0), true);
+        } else if (config.getProperty(properties[0]).equals("2")) {
+            enablePanel(proxyPanels.get(0), false);
+            enablePanel(proxyPanels.get(1), true);
+        } else if (config.getProperty(properties[0]).equals("3")) {
+            for (JPanel panel : proxyPanels)
+                enablePanel(panel, false);
+        }
+    }
+    
+    /**
+     * Creates a PlainDocument that only take numbers if it will create a valid port number.
+     * @return PlainDocument which will ensure numeric values only and is a valid port number.
+     */
+    public static PlainDocument getPortNumberDocument(){
+        return new PlainDocument(){
+            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+                if (str != null) {
+                    try {
+                        Integer.valueOf(str);
+                        int val = Integer.valueOf(this.getText(0, this.getLength()) + str);
+                        if (val < 1 || val > 65535) { // Invalid port number if true
+                            throw new NumberFormatException("Invalid port number");
+                        }
+                        super.insertString(offs, str, a);
+                    } catch (Exception e) {
+                        JOptionPane.showMessageDialog(null, Translator.R("CPInvalidPort"), Translator.R("CPInvalidPortTitle")
+                                , JOptionPane.WARNING_MESSAGE);
+                    }
+                }
+                return;
+            }
+        };
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/SecuritySettingsPanel.java	(revision 403)
@@ -0,0 +1,141 @@
+/* SecuritySettingsPanel.java -- Display possible security settings.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * This provides a way for the user to modify the security settings through a
+ * GUI.
+ * 
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ * 
+ */
+@SuppressWarnings("serial")
+public class SecuritySettingsPanel extends NamedBorderPanel implements ActionListener {
+
+    private DeploymentConfiguration config;
+
+    // NOTE: All the ones listed with "Default" are in Oracle's implementation.
+    // Not shown on deployments.properties webpage. Add support for these later!
+    /** List of properties used by this panel */
+    public static String[] properties = { "deployment.security.askgrantdialog.show",
+            "deployment.security.askgrantdialog.notinca",
+            "deployment.security.browser.keystore.use", // default TRUE
+            "deployment.security.clientauth.keystore.auto", // Default FALSE
+            "deployment.security.jsse.hostmismatch.warning",
+            "deployment.security.https.warning.show", // Default FALSE
+            "deployment.security.sandbox.awtwarningwindow",
+            "deployment.security.sandbox.jnlp.enhanced",
+            "deployment.security.validation.crl", // Default TRUE
+            "deployment.security.validation.ocsp", // Default FALSE
+            "deployment.security.pretrust.list", // Default TRUE
+            "deployment.security.blacklist.check", // Default TRUE
+            "deployment.security.password.cache", // Default TRUE
+            "deployment.security.SSLv2Hello", // Default FALSE
+            "deployment.security.SSLv3", // Default TRUE
+            "deployment.security.TLSv1", // Default TRUE
+            //            "deployment.security.mixcode", // Default TRUE
+    };
+
+    /**
+     * This creates a new instance of the security settings panel.
+     * 
+     * @param config
+     *            Loaded DeploymentConfiguration file.
+     */
+    public SecuritySettingsPanel(DeploymentConfiguration config) {
+        super(Translator.R("CPHeadSecurity"), new BorderLayout());
+        this.config = config;
+
+        addComponents();
+    }
+
+    /**
+     * Add the components to the panel.
+     */
+    private void addComponents() {
+        JPanel topPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+
+        JLabel description = new JLabel("<html>" + Translator.R("CPSecurityDescription") + "<hr /></html>");
+
+        JCheckBox[] securityGeneralOptions = { new JCheckBox(Translator.R("SGPAllowUserGrantSigned")),
+                new JCheckBox(Translator.R("SGPAllowUserGrantUntrust")),
+                new JCheckBox(Translator.R("SGPUseBrowserKeystore")),
+                new JCheckBox(Translator.R("SGPUsePersonalCertOneMatch")),
+                new JCheckBox(Translator.R("SGPWarnCertHostMismatch")),
+                new JCheckBox(Translator.R("SGPShowValid")),
+                new JCheckBox(Translator.R("SGPShowSandboxWarning")),
+                new JCheckBox(Translator.R("SGPAllowUserAcceptJNLPSecurityRequests")),
+                new JCheckBox(Translator.R("SGPCheckCertRevocationList")),
+                new JCheckBox(Translator.R("SGPEnableOnlineCertValidate")),
+                new JCheckBox(Translator.R("SGPEnableTrustedPublisherList")),
+                new JCheckBox(Translator.R("SGPEnableBlacklistRevocation")),
+                new JCheckBox(Translator.R("SGPEnableCachingPassword")),
+                new JCheckBox(Translator.R("SGPUseSSL2")),
+                new JCheckBox(Translator.R("SGPUseSSL3")),
+                new JCheckBox(Translator.R("SGPUseTLS1")), };
+
+        c.fill = GridBagConstraints.BOTH;
+        c.gridx = 0;
+        c.weightx = 1;
+
+        topPanel.add(description, c);
+
+        // Only display the ones with properties that are valid or existent.
+        for (int i = 0; i < properties.length; i++) {
+            String s = config.getProperty(properties[i]);
+            if (s == null) {
+                securityGeneralOptions[i] = null;
+                continue;
+            }
+            securityGeneralOptions[i].setSelected(Boolean.parseBoolean(s));
+            securityGeneralOptions[i].setActionCommand(properties[i]);
+            securityGeneralOptions[i].addActionListener(this);
+            c.gridy = i + 1;
+            topPanel.add(securityGeneralOptions[i], c);
+        }
+
+        Component filler = Box.createRigidArea(new Dimension(1, 1));
+        c.weighty = 1;
+        c.gridy++;
+        topPanel.add(filler, c);
+
+        add(topPanel, BorderLayout.CENTER);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        config.setProperty(e.getActionCommand(), String.valueOf(((JCheckBox) e.getSource()).isSelected()));
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java	(revision 403)
@@ -0,0 +1,226 @@
+/* TemporaryInternetFilesPanel.java -- Display and sets cache settings.
+Copyright (C) 2010 Red Hat
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package net.sourceforge.jnlp.controlpanel;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.JTextField;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * The actual panel that contains the fields that the user can edit accordingly.
+ * This is provided as a pane for inside the Panel itself, can also be used to
+ * display as a dialog.
+ * TODO: Add functionality:
+ *
+ * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)
+ *
+ */
+@SuppressWarnings("serial")
+public class TemporaryInternetFilesPanel extends NamedBorderPanel implements ChangeListener {
+
+    private DeploymentConfiguration config;
+    private int minSize = -1;
+    private int maxSize = 1000;
+
+    /** List of properties used by this panel */
+    public static String[] properties = { "deployment.javapi.cache.enabled", // false == enabled
+            "deployment.user.cachedir",
+            "deployment.cache.max.size", // Specified in MB
+            "deployment.cache.jarcompression", // Allows values 0-9
+    };
+
+    private JComponent defaultFocusComponent = null;
+    JSpinner spCacheSize;
+    JSlider slCacheSize;
+
+    public TemporaryInternetFilesPanel(DeploymentConfiguration config) {
+        super(Translator.R("CPHeadTempInternetFiles"));
+        this.config = config;
+        setLayout(new BorderLayout());
+
+        addComponents();
+    }
+
+    /**
+     * Add components to panel.
+     */
+    private void addComponents() {
+        JPanel topPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+
+        JLabel description = new JLabel("<html>" + Translator.R("CPTempInternetFilesDescription") + "<hr /></html>");
+
+        JCheckBox enableCaching = new JCheckBox(Translator.R("TIFPEnableCache"), !Boolean.parseBoolean(this.config.getProperty(properties[0])));
+        enableCaching.addItemListener(new ItemListener() {
+            @Override
+            public void itemStateChanged(ItemEvent e) {
+                config.setProperty(properties[0], String.valueOf(!(e.getStateChange() == ItemEvent.SELECTED)));
+            }
+        });
+
+        // This displays the option for changing location of cache
+        // User can NOT edit the text field must do it through dialog.
+        JPanel locationPanel = new NamedBorderPanel(Translator.R("TIFPLocation"), new GridBagLayout());
+        JLabel locationDescription = new JLabel(Translator.R("TIFPLocationLabel") + ":");
+        final JTextField location = new JTextField(this.config.getProperty(properties[1]));
+        location.setEditable(false); // Can not c&p into the location field.
+        JButton bLocation = new JButton(Translator.R("TIFPChange") + "...");
+        bLocation.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                JFileChooser fileChooser = new JFileChooser();
+                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+                if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
+                    String result = fileChooser.getSelectedFile().getAbsolutePath();
+                    location.setText(result);
+                    config.setProperty(properties[1], result);
+                }
+            }
+        });
+
+        c.weightx = 1;
+        c.gridwidth = GridBagConstraints.REMAINDER;
+        c.gridx = 0;
+        c.gridy = 0;
+        locationPanel.add(locationDescription, c);
+        c.gridwidth = 1;
+        c.gridy = 1;
+        locationPanel.add(location, c);
+        c.gridx = 1;
+        c.weightx = 0;
+        locationPanel.add(bLocation, c);
+
+        // This section deals with how to use the disk space.
+        JPanel diskSpacePanel = new NamedBorderPanel(Translator.R("TIFPDiskSpace"), new GridBagLayout());
+        JLabel lCompression = new JLabel(Translator.R("TIFPCompressionLevel")); // Sets compression level for jar files.
+        ComboItem[] compressionOptions = { new ComboItem(Translator.R("TIFPNone"), "0"),
+                new ComboItem("1", "1"),
+                new ComboItem("2", "2"),
+                new ComboItem("3", "3"),
+                new ComboItem("4", "4"),
+                new ComboItem("5", "5"),
+                new ComboItem("6", "6"),
+                new ComboItem("7", "7"),
+                new ComboItem("8", "8"),
+                new ComboItem(Translator.R("TIFPMax"), "9"), };
+        JComboBox cbCompression = new JComboBox(compressionOptions);
+        cbCompression.setSelectedIndex(Integer.parseInt(this.config.getProperty(properties[3])));
+        cbCompression.addItemListener(new ItemListener() {
+            @Override
+            public void itemStateChanged(ItemEvent e) {
+                config.setProperty(properties[3], ((ComboItem) e.getItem()).getValue());
+            }
+        });
+
+        JLabel lCacheSize = new JLabel(Translator.R("TIFPCacheSize") + ":");
+        slCacheSize = new JSlider(minSize, maxSize, Integer.parseInt(this.config.getProperty(properties[2])));
+        slCacheSize.setMinorTickSpacing(50);
+        slCacheSize.setPaintTicks(true);
+        SpinnerNumberModel snmCacheSize = new SpinnerNumberModel(Integer.parseInt(this.config.getProperty(properties[2])), minSize, maxSize, 1);
+        spCacheSize = new JSpinner(snmCacheSize);
+
+        slCacheSize.addChangeListener(this);
+        spCacheSize.addChangeListener(this);
+
+        c.gridy = 0;
+        c.gridx = 0;
+        c.weightx = 1;
+        diskSpacePanel.add(lCompression, c);
+        c.gridx = 1;
+        c.weightx = 0;
+        diskSpacePanel.add(cbCompression, c);
+        c.gridy = 1;
+        c.gridx = 0;
+        c.gridwidth = GridBagConstraints.REMAINDER;
+        c.weightx = 1;
+        diskSpacePanel.add(lCacheSize, c);
+        c.gridwidth = 1;
+        c.gridy = 2;
+        diskSpacePanel.add(slCacheSize, c);
+        c.gridx = 1;
+        diskSpacePanel.add(spCacheSize, c);
+
+        JPanel buttonDeleteRestore = new JPanel(new FlowLayout(FlowLayout.TRAILING));
+        JButton bViewFiles = new JButton(Translator.R("TIFPViewFiles"));
+        bViewFiles.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                CacheViewer.showCacheDialog(config);
+            }
+        });
+        buttonDeleteRestore.add(bViewFiles);
+
+        c.weighty = 0;
+        c.gridx = 0;
+        c.gridy = 0;
+        topPanel.add(enableCaching, c);
+        c.gridy = 1;
+        topPanel.add(locationPanel, c);
+        c.gridy = 2;
+        topPanel.add(diskSpacePanel, c);
+        c.weighty = 1;
+        c.gridy = 3;
+        topPanel.add(buttonDeleteRestore, c);
+        add(description, BorderLayout.NORTH);
+        add(topPanel, BorderLayout.CENTER);
+    }
+
+    /**
+     * Give focus to the default button.
+     */
+    public void focusOnDefaultButton() {
+        if (defaultFocusComponent != null) {
+            defaultFocusComponent.requestFocusInWindow();
+        }
+    }
+
+    @Override
+    public void stateChanged(ChangeEvent e) {
+        Object o = e.getSource();
+        if (o instanceof JSlider)
+            spCacheSize.setValue(((JSlider) o).getValue());
+        else if (o instanceof JSpinner)
+            slCacheSize.setValue((Integer) ((JSpinner) o).getValue());
+
+        config.setProperty(properties[2], spCacheSize.getValue().toString());
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationEvent.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationEvent.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationEvent.java	(revision 403)
@@ -0,0 +1,53 @@
+// Copyright (C) 2002 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.event;
+
+import java.util.*;
+
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * This event is sent when an application is terminated.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public class ApplicationEvent extends EventObject {
+
+    /** the application instance */
+    transient private ApplicationInstance application;
+
+    /**
+     * Creates a launch event for the specified application
+     * instance.
+     *
+     * @param source the application instance
+     */
+    public ApplicationEvent(ApplicationInstance source) {
+        super(source);
+
+        this.application = source;
+    }
+
+    /**
+     * Returns the application instance.
+     */
+    public ApplicationInstance getApplication() {
+        return application;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationListener.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationListener.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/ApplicationListener.java	(revision 403)
@@ -0,0 +1,35 @@
+// Copyright (C) 2002 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.event;
+
+import java.util.*;
+
+/**
+ * The listener that is notified when an application instance is
+ * terminated.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public interface ApplicationListener extends EventListener {
+
+    /**
+     * Invoked when the application is destroyed.
+     */
+    public void applicationDestroyed(ApplicationEvent applicationEvent);
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadEvent.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadEvent.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadEvent.java	(revision 403)
@@ -0,0 +1,67 @@
+// Copyright (C) 2002 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.event;
+
+import java.net.*;
+import java.util.*;
+
+import net.sourceforge.jnlp.cache.*;
+
+/**
+ * This event is sent during the launch of an
+ * application.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.3 $
+ */
+public class DownloadEvent extends EventObject {
+
+    /** the tracker */
+    transient private ResourceTracker tracker;
+
+    /** the resource */
+    transient private Resource resource;
+
+    /**
+     * Creates a launch event for the specified application
+     * instance.
+     *
+     * @param source the resource tracker
+     * @param resource the resource
+     */
+    public DownloadEvent(ResourceTracker source, Resource resource) {
+        super(source);
+
+        this.tracker = source;
+        this.resource = resource;
+    }
+
+    /**
+     * Returns the tracker that owns the resource.
+     */
+    public ResourceTracker getTracker() {
+        return tracker;
+    }
+
+    /**
+     * Returns the location of the resource being downloaded.
+     */
+    public URL getResourceLocation() {
+        return resource.getLocation();
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadListener.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadListener.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/DownloadListener.java	(revision 403)
@@ -0,0 +1,48 @@
+// Copyright (C) 2002 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.event;
+
+import java.util.*;
+
+/**
+ * The listener that is notified of the state of resources being
+ * downloaded by a ResourceTracker.  Events may be delivered on a
+ * background thread, and the event methods should complete
+ * quickly so that they do not slow down other downloading in
+ * progress by tying up a thread.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.3 $
+ */
+public interface DownloadListener extends EventListener {
+
+    /**
+     * Called when a resource is checked for being up-to-date.
+     */
+    public void updateStarted(DownloadEvent downloadEvent);
+
+    /**
+     * Called when a download starts.
+     */
+    public void downloadStarted(DownloadEvent downloadEvent);
+
+    /**
+     * Called when a download completed or there was an error.
+     */
+    public void downloadCompleted(DownloadEvent downloadEvent);
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/package.html
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/package.html	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/event/package.html	(revision 403)
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the JNLP events.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/package.html
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/package.html	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/package.html	(revision 403)
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the classes that represent the parts of a
+Java Network Launching Protocol (JNLP) file as objects, and a way
+to launch a JNLP file as an application, applet, or installer.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/Messages.properties
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/Messages.properties	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/Messages.properties	(revision 403)
@@ -0,0 +1,429 @@
+# Default (English) UI messages for netx
+# L=Launcher, B=Boot, P=Parser, C=cache S=security
+#
+# General
+NullParameter=Null parameter
+ButAllow=Allow
+ButBrowse=Browse...
+ButCancel=\ Cancel\ 
+ButClose=Close
+ButCopy=Copy to Clipboard
+ButMoreInformation=More Information...
+ButOk=OK
+ButProceed=Proceed
+ButRun=Run
+ButApply=Apply
+ButDone=Done
+ButShowDetails=Show Details
+ButHideDetails=Hide Details
+
+AFileOnTheMachine=a file on the machine
+AlwaysAllowAction=Always allow this action
+Usage=Usage:
+Error=Error
+
+Continue=Do you want to continue?
+Field=Field
+From=From
+Name=Name
+Password=Password:
+Publisher=Publisher
+Unknown=<Unknown>
+Username=Username:
+Value=Value
+Version=Version
+
+# LS - Severity
+LSMinor=Minor
+LSFatal=Fatal
+
+# LC - Category 
+LCSystem=System Error
+LCExternalLaunch=External Launch Error
+LCFileFormat=File Format Error
+LCReadError=Read Error
+LCClient=Application Error
+LCLaunching=Launch Error
+LCNotSupported=Unsupported Feature
+LCInit=Initialization Error
+ 
+LAllThreadGroup=All JNLP applications
+LNullUpdatePolicy=Update policy cannot be null.
+ 
+LThreadInterrupted=Thread interrupted while waiting for file to launch.
+LThreadInterruptedInfo=
+LCouldNotLaunch=Could not launch JNLP file.
+LCouldNotLaunchInfo=
+LCantRead=Could not read or parse the JNLP file.
+LCantReadInfo=
+LNullLocation=Could not determine .jnlp file location.
+LNullLocationInfo=An attempt was made to launch a JNLP file in another JVM, but the file could not be located.  In order to launch in an external JVM, the runtime must be able to locate the .jnlp file either in the local filesystem or on a server.
+LNetxJarMissing=Could not determine location of netx.jar.
+LNetxJarMissingInfo=An attempt was made to lauch a JNLP file in another JVM, but the netx.jar could not be located.  In order to launch in an external JVM, the runtime must be able to locate the netx.jar file.
+LNotToSpec=JNLP file not strictly to spec.
+LNotToSpecInfo=The JNLP file contains data that is prohibited by the JNLP specification.  The runtime can attempt to ignore the invalid information and continue launching the file.
+LNotApplication=Not an application file.
+LNotApplicationInfo=An attempt was made to load a non-application file as an application.
+LNotApplet=Not an applet file.
+LNotAppletInfo=An attempt was made to load a non-applet file as an applet.
+LNoInstallers=Installers not supported.
+LNoInstallersInfo=JNLP installer files are not yet supported.
+LInitApplet=Could not initialize applet.
+LInitAppletInfo=
+LInitApplication=Could not initialize application.
+LInitApplicationInfo=
+LNotLaunchable=Not a launchable JNLP file.
+LNotLaunchableInfo=File must be a JNLP application, applet, or installer type.
+LCantDetermineMainClass=Unknown Main-Class.
+LCantDetermineMainClassInfo=Could not determine the main class for this application.
+LUnsignedJarWithSecurity=Cannot grant permissions to unsigned jars.
+LUnsignedJarWithSecurityInfo=Application requested security permissions, but jars are not signed.
+LSignedAppJarUsingUnsignedJar=Signed application using unsigned jars.
+LSignedAppJarUsingUnsignedJarInfo=The main application jar is signed, but some of the jars it is using aren't.
+
+JNotApplet=File is not an applet.
+JNotApplication=File is not an application.
+JNotComponent=File is not a component.
+JNotInstaller=File is not an installer.
+JInvalidExtensionDescriptor=Extension does not refer to a component or installer (name={1}, location={2}).
+
+LNotVerified=Jars not verified.
+LCancelOnUserRequest=Canceled on user request.
+LFatalVerification=A fatal error occurred while trying to verify jars.
+LFatalVerificationInfo=
+
+LNotVerifiedDialog=Not all jars could be verified.
+LAskToContinue=Would you still like to continue running this application?
+
+# Parser
+PInvalidRoot=Root node is not a jnlp node
+PNoResources=No resources section defined
+PUntrustedNative=nativelib element cannot be specified unless a trusted environment is requested.
+PExtensionHasJ2SE=j2se element cannot be specified in a component extension file.
+PInnerJ2SE=j2se element cannot be specified within a j2se element.
+PTwoMains=Duplicate main JAR defined in a resources element (there can be only one)
+PNativeHasMain=Cannot specify main attribute on native JARs.
+PNoInfoElement=No information section defined
+PTwoDescriptions=Duplicate description of kind {0}
+PSharing=Element "sharing-allowed" is illegal in a standard JNLP file
+PTwoSecurity=Only one security element allowed per JNLPFile.
+PEmptySecurity=Security element specified but does not contain a permissions element.
+PTwoDescriptors=Only one application descriptor element allowed per JNLPFile.
+PTwoDesktops=Only one desktop element allowed
+PTwoMenus=Only one menu element allowed
+PTwoTitles=Only one title element allowed
+PTwoIcons=Only one icon element allowed
+PTwoUpdates=Only one update element is allowed
+PUnknownApplet=Unknown Applet
+PBadWidth=Invalid applet width.
+PBadHeight=Invalid applet height.
+PUrlNotInCodebase=Relative URL does not specify a subdirectory of the codebase. (node={0}, href={1}, base={2})
+PBadRelativeUrl=Invalid relative URL (node={0}, href={1}, base={2})
+PBadNonrelativeUrl=Invalid non-relative URL (node={0}, href={0}).
+PNeedsAttribute=The {0} element must specify a {1} attribute.
+PBadXML=Invalid XML document syntax.
+PBadHeapSize=Invalid value for heap size ({0})
+
+# Runtime
+BLaunchAbout=Launching about window...
+BNeedsFile=Must specify a .jnlp file
+RNoAboutJnlp=Unable to find about.jnlp
+BFileLoc=JNLP file location
+BBadProp=Incorrect property format {0} (should be key=value)
+BBadParam=Incorrect parameter format {0} (should be name=value)
+BNoDir=Directory {0} does not exist.
+RNoResource=Missing Resource: {0}
+RShutdown=This exception to prevent shutdown of JVM, but the process has been terminated.
+RExitTaken=Exit class already set and caller is not exit class.
+RCantReplaceSM=Changing the SecurityManager is not allowed.
+RCantCreateFile=Cant create file {0}
+RCantDeleteFile=Cant delete file {0}
+RRemoveRPermFailed=Removing read permission on file {0} failed
+RRemoveWPermFailed=Removing write permissions on file {0} failed
+RRemoveXPermFailed=Removing execute permissions on file {0} failed
+RGetRPermFailed=Acquiring read permissions on file {0} failed
+RGetWPermFailed=Acquiring write permissions on file {0} failed
+RGetXPermFailed=Acquiring execute permissions on file {0} failed
+RCantCreateDir=Cant create directory {0}
+RCantRename=Cant rename {0} to {1}
+RDenyStopped=Stopped applications have no permissions.
+RExitNoApp=Can not exit the JVM because the current application cannot be determined.
+RNoLockDir=Unable to create locks directory ({0})
+RNestedJarExtration=Unable to extract nested jar.
+RUnexpected=Unexpected {0} at {1}
+RConfigurationError=Fatal error while reading the configuration
+RConfigurationFatal=ERROR: a fatal error has occurred while loading configuration. Perhaps a global configuration was required but could not be found
+RPRoxyPacNotSupported=Using Proxy Auto Config (PAC) files is not supported.
+RProxyFirefoxNotFound=Unable to use Firefox's proxy settings. Using "DIRECT" as proxy type.
+RProxyFirefoxOptionNotImplemented=Browser proxy option "{0}" ({1}) not supported yet.
+RBrowserLocationPromptTitle=Browser Location
+RBrowserLocationPromptMessage=Specify Browser Location
+RBrowserLocationPromptMessageWithReason=Specify Browser Location (the browser command "{0}" is invalid).
+
+# Boot options, message should be shorter than this ---------------->
+BOUsage=javaws [-run-options] <jnlp file>
+BOUsage2=javaws [-control-options]
+BOJnlp      = Location of JNLP file to launch (url or file).
+BOArg       = Adds an application argument before launching.
+BOParam     = Adds an applet parameter before launching.
+BOProperty  = Sets a system property before launching.
+BOUpdate    = Update check if seconds since last checked.
+BOLicense   = Display the GPL license and exit.
+BOVerbose   = Enable verbose output.
+BOAbout     = Shows a sample application.
+BONosecurity= Disables the secure runtime environment.
+BONoupdate  = Disables checking for updates.
+BOHeadless  = Disables download window, other UIs.
+BOStrict    = Enables strict checking of JNLP file format.
+BOViewer    = Shows the trusted certificate viewer.
+BXnofork    = Do not create another JVM.
+BXclearcache= Clean the JNLP application cache.
+BOHelp      = Print this message and exit.
+
+# Cache
+CAutoGen=automatically generated - do not edit
+CNotCacheable={0} is not a cacheable resource
+CDownloading=Downloading
+CComplete=Complete
+CChooseCache=Choose a cache directory...
+CChooseCacheInfo=Netx needs a location for storing cache files.
+CChooseCacheDir=Cache directory
+CCannotClearCache=Can not clear cache at this time
+
+# Security
+SFileReadAccess=The application has requested read access to {0}. Do you want to allow this action?
+SFileWriteAccess=The application has requested write access to {0}. Do you want to allow this action?
+SDesktopShortcut=The application has requested permission to create a desktop launcher. Do you want to allow this action?
+SSigUnverified=The application's digital signature cannot be verified. Do you want to run the application?
+SSigVerified=The application's digital signature has been verified. Do you want to run the application?
+SSignatureError=The application's digital signature has an error. Do you want to run the application?
+SUntrustedSource=The digital signature could not be verified by a trusted source. Only run if you trust the origin of the application.
+STrustedSource=The digital signature has been validated by a trusted source.
+SClipboardReadAccess=The application has requested read-only access to the system clipboard. Do you want to allow this action?
+SClipboardWriteAccess=The application has requested write-only access to the system clipboard. Do you want to allow this action?
+SPrinterAccess=The application has requested printer access. Do you want to allow this action?
+SNetworkAccess=The application has requested permission to establish connections to {0}. Do you want to allow this action?
+SNoAssociatedCertificate=<no associated certificate>
+SAlwaysTrustPublisher=Always trust content from this publisher
+SHttpsUnverified=The website's certificate cannot be verified.
+SNotAllSignedSummary=Only parts of this application code are signed.
+SNotAllSignedDetail=This application contains both signed and unsigned code. While signed code is safe if you trust the provider, unsigned code may imply code outside of the trusted provider's control.
+SNotAllSignedQuestion=Do you wish to proceed and run this application anyway?
+SAuthenticationPrompt=The {0} server at {1} is requesting authentication. It says "{2}"
+
+# Security - used for the More Information dialog
+SBadKeyUsage=Resources contain entries whose signer certificate's KeyUsage extension doesn't allow code signing.
+SBadExtendedKeyUsage=Resources contain entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing.
+SBadNetscapeCertType=Resources contain entries whose signer certificate's NetscapeCertType extension doesn't allow code signing.
+SHasUnsignedEntry=Resources contain unsigned entries which have not been integrity-checked.
+SHasExpiredCert=The digital signature has expired.
+SHasExpiringCert=Resources contain entries whose signer certificate will expire within six months.
+SNotYetValidCert=Resources contain entries whose signer certificate is not yet valid.
+SUntrustedCertificate=The digital signature was generated with an untrusted certificate.
+STrustedCertificate=The digital signature was generated with a trusted certificate.
+SCNMisMatch=The expected hostname for this certificate is: "{0}"<BR>The address being connected to is: "{1}"
+SRunWithoutRestrictions=This application will be run without the security restrictions normally provided by java.
+SCertificateDetails=Certificate Details
+
+# Security - certificate information
+SIssuer=Issuer
+SSerial=Serial
+SMD5Fingerprint=MD5 Fingerprint
+SSHA1Fingerprint=SHA1 Fingerprint
+SSignature=Signature
+SSignatureAlgorithm=Signature Algorithm
+SSubject=Subject
+SValidity=Validity
+
+# Certificate Viewer
+CVCertificateViewer=Certificates
+CVCertificateType=Certificate Type
+CVDetails=Details
+CVExport=Export
+CVImport=Import
+CVIssuedBy=Issued By
+CVIssuedTo=Issued To
+CVRemove=Remove
+CVRemoveConfirmMessage=Are you sure you want to remove the selected certificate?
+CVRemoveConfirmTitle=Confirmation - Remove Certificate?
+CVUser=User
+CVSystem=System
+
+#KeyStores: see KeyStores.java
+KS=KeyStore
+KSCerts=Trusted Certificates
+KSJsseCerts=Trusted JSSE Certificates
+KSCaCerts=Trusted Root CA Certificates
+KSJsseCaCerts=Trusted JSSE Root CA Certificates,
+KSClientCerts=Client Authentication Certificates
+
+# Deployment Configuration messages
+DCIncorrectValue=Property "{0}" has incorrect value "{1}". Possible values {2}.
+DCInternal=Internal error: {0}
+DCSourceInternal=<internal>
+DCUnknownSettingWithName=Property "{0}" is unknown.
+
+# Value Validator messages. Messages should follow "Possible values ..." 
+VVPossibleValues=Possible values {0}
+VVPossibleBooleanValues=are {0} or {1}
+VVPossibleFileValues=include the absolute location of a file - it must begin with a /
+VVPossibleFileValuesDOS=include the absolute location of a file - it must begin with a drive letter
+VVPossibleRangedIntegerValues=are in range {0} to {1} (inclusive)
+VVPossibleUrlValues=include any valid url (eg http://icedtea.classpath.org/hg/)
+
+# Control Panel - Main
+CPMainDescriptionShort=Configure IcedTea-Web
+CPMainDescriptionLong=Configure how the browser plugin (IcedTeaNPPlugin) and javaws (NetX) work
+
+# Control Panel - Tab Descriptions
+CPAboutDescription=View version information about Icedtea Control Panel.
+CPNetworkSettingsDescription=Configure network settings, including how IcedTea-Web connects to the internet and whether to use any proxies.
+CPTempInternetFilesDescription=Java stores application data for faster execution the next time you run it.
+CPJRESettingsDescription=View and manage Java Runtime Environment versions and settings for Java applications and applets.
+CPCertificatesDescription=Use certificates to positively identify yourself, certifications, authorities, and plublishers.
+CPSecurityDescription=Use this to configure security settings.
+CPDebuggingDescription=Enable options here to help with debugging
+CPDesktopIntegrationDescription=Set whether or not to allow creation of desktop shortcut.
+
+# Control Panel - Buttons
+CPButAbout=About...
+CPButNetworkSettings=Network Settings...
+CPButSettings=Settings...
+CPButView=View...
+CPButCertificates=Certificates...
+
+# Control Panel - Headers
+CPHead=IcedTea Web Control Panel
+CPHeadAbout=About
+CPHeadNetworkSettings=Network Proxy Settings
+CPHeadTempInternetFiles=Temporary Internet Files
+CPHeadJRESettings=Java Runtime Environment Settings
+CPHeadCertificates=Certificates
+CPHeadDebugging=Debugging Settings
+CPHeadDesktopIntegration=Desktop Integrations
+CPHeadSecurity=Security Settings
+
+# Control Panel - Tabs
+CPTabAbout=About IcedTea-Web
+CPTabCache=Cache
+CPTabCertificate=Certificates
+CPTabClassLoader=Class Loaders
+CPTabDebugging=Debugging
+CPTabDesktopIntegration=Desktop Integration
+CPTabNetwork=Network
+CPTabRuntimes=Runtimes
+CPTabSecurity=Security
+
+# Control Panel - AboutPanel
+CPAboutInfo=This is the control panel for setting deployments.properties.<br/>Not all options will take effect until implemented.<br/>The use of multiple JREs is currently unsupported.<br/>
+
+# Control Panel - AdvancedProxySettings
+APSDialogTitle=Network Settings
+APSServersPanel=Servers
+APSProxyTypeLabel=Type
+APSProxyAddressLabel=Proxy Address
+APSProxyPortLabel=Proxy Port
+APSLabelHTTP=HTTP
+APSLabelSecure=Secure
+APSLabelFTP=FTP
+APSLabelSocks=Socks
+APSSameProxyForAllProtocols=Use the same proxy server for all protocols.
+APSExceptionsLabel=Exceptions
+APSExceptionsDescription=Do not use proxy server for addresses beginning with
+APSExceptionInstruction=Separate each entry with a semicolon.
+
+# Control Panel - DebugginPanel
+DPEnableTracing=Enable tracing
+DPEnableLogging=Enable logging
+DPDisable=Disable
+DPHide=Hide on startup
+DPShow=Show on startup
+DPJavaConsole=Java Console
+
+# Control Panel - DesktopShortcutPanel
+DSPNeverCreate=Never create
+DSPAlwaysAllow=Always allow
+DSPAskUser=Ask user
+DSPAskIfHinted=Ask if hinted
+DSPAlwaysIfHinted=Always if hinted
+
+# Control Panel - NetworkSettingsPanel
+NSDescription-1=Unknown Setting.
+NSDescription0=Use direct connection.
+NSDescription1=Override browser proxy settings.
+NSDescription2=Use automatic proxy configuration script at the specified location.
+NSDescription3=Use proxy settings from your default browser to connect to the internet.
+NSAddress=Address
+NSPort=Port
+NSAdvanced=Advanced
+NSBypassLocal=Bypass proxy server for local addresses
+NSDirectConnection=Direct connection
+NSManualProxy=Manual proxy server
+NSAutoProxy=Automatic proxy configuration script
+NSBrowserProxy=Use browser settings
+NSScriptLocation=Script location
+
+# Control Panel - SecurityGeneralPanel
+SGPAllowUserGrantSigned=Allow users to grant permissions to signed content 
+SGPAllowUserGrantUntrust=Allow users to grant permissions to content from an untrusted authority 
+SGPUseBrowserKeystore=Use certificates and keys in browser keystore (Unsupported)
+SGPUsePersonalCertOneMatch=Use personal certificate automatically if only one matches server request (Unsupported)
+SGPWarnCertHostMismatch=Warn if site certificate does not match hostname  
+SGPShowValid=Show site certificate even if it is valid (Unsupported)
+SGPShowSandboxWarning=Show sandbox warning banner 
+SGPAllowUserAcceptJNLPSecurityRequests=Allow user to accept JNLP security requests 
+SGPCheckCertRevocationList=Check certificates for revocation using Certificate Revocation Lists (CRLs) (Unsupported)
+SGPEnableOnlineCertValidate=Enable online certificate validation (Unsupported)
+SGPEnableTrustedPublisherList=Enable list of trusted publishers (Unsupported)
+SGPEnableBlacklistRevocation=Enable blacklist revocation check (Unsupported)
+SGPEnableCachingPassword=Enable caching password for authentication (Unsupported)
+SGPUseSSL2=Use SSL 2.0 compatible ClientHello format (Unsupported)
+SGPUseSSL3=Use SSL 3.0 (Unsupported)
+SGPUseTLS1=Use TLS 1.0 (Unsupported)
+
+# Control Panel - TemporaryInternetFilesPanel
+TIFPEnableCache=Keep temporary files on my computer
+TIFPLocation=Location
+TIFPLocationLabel=Select the location where temporary files are kept
+TIFPChange=Change
+TIFPDiskSpace=Disk space
+TIFPCompressionLevel=Select the compression level for JAR files
+TIFPNone=None
+TIFPMax=Max
+TIFPCacheSize=Set the amount of disk space for storing temporary files
+TIFPDeleteFiles=Delete files
+TIFPViewFiles=View files...
+
+# Control Panel - Cache Viewer
+CVCPDialogTitle=Cache Viewer
+CVCPButRefresh=Refresh
+CVCPButDelete=Delete
+CVCPColLastModified=Last Modified
+CVCPColSize=Size (Bytes)
+CVCPColDomain=Domain
+CVCPColType=Type
+CVCPColPath=Path
+CVCPColName=Name
+
+# Control Panel - Misc.
+CPJRESupport=IcedTea-Web currently does not support the use of multiple JREs.
+CPInvalidPort=Invalid port number given.\n[Valid port numbers are 1-65535]
+CPInvalidPortTitle=Error on input.
+
+# command line control panel
+CLNoInfo=No information avaiable (is this a valid option?).
+CLValue=Value: {0}
+CLValueSource=Source: {0}
+CLDescription=Description: {0}
+CLUnknownCommand=Unknown command {0}
+CLUnknownProperty=Unknown property-name "{0}"
+CLWarningUnknownProperty=WARNING: Unknown property name "{0}" - creating new property
+CLNoIssuesFound=No issues found.
+CLIncorrectValue=Property "{0}" has incorrect value "{1}". Possible values {2}.
+CLListDescription=Shows a list of all property names and values that are in use by IcedTea-Web
+CLGetDescription=Shows the value for property-name
+CLSetDescription=Sets the property-name to value if possible. The value is checked for being valid. If the administrator has locked the property, this will have no effect
+CLResetDescription=Resets the value for property-name to it\'s default value
+CLInfoDescription=Shows more information about the given property
+CLCheckDescription=Shows any properties that have been defined but are not recognized by IcedTea Web
+CLHelpDescription=The itweb-settings tool allows a user to modify, view and check configuration. \nTo use the GUI, do not pass any arguments. To use the CLI mode, pass in the approrpiate command and parameters. For help with a particular command, try: {0} command help
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/about.jnlp
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/about.jnlp	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/resources/about.jnlp	(revision 403)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="1.0" href="about.jnlp" codebase=".">
+  <information>
+    <title>About window for NetX</title>
+    <vendor>NetX</vendor>
+    <homepage href="http://jnlp.sourceforge.net/netx/"/>
+    <description>Displays information about NetX</description>
+    <offline/>
+  </information>
+  <resources>
+    <j2se version="1.4+"/>
+    <jar href="about.jar"/>
+  </resources>
+  <application-desc main-class="net.sourceforge.javaws.about.Main">
+  </application-desc>
+</jnlp>
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java	(revision 403)
@@ -0,0 +1,63 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+/**
+ * Thread group for a JNLP application.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public class AppThreadGroup extends ThreadGroup {
+
+    /** the app */
+    private ApplicationInstance app = null;
+
+    /**
+     * Creates new JavaAppThreadGroup
+     *
+     * @param name of the App
+     */
+    public AppThreadGroup(ThreadGroup parent, String name) {
+        super(parent, name);
+    }
+
+    /**
+     * Sets the JNLP app this group is for; can only be called once.
+     */
+    public void setApplication(ApplicationInstance app) {
+        if (this.app != null)
+            throw new IllegalStateException("Application can only be set once");
+
+        this.app = app;
+    }
+
+    /**
+     * Returns the JNLP app for this thread group.
+     */
+    public ApplicationInstance getApplication() {
+        return app;
+    }
+
+    /**
+     * Handle uncaught exceptions for the app.
+     */
+    public void uncaughtException(Thread t, Throwable e) {
+        super.uncaughtException(t, e);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java	(revision 403)
@@ -0,0 +1,103 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.net.*;
+import java.applet.*;
+import javax.sound.sampled.*;
+
+// based on Deane Richan's AppletAudioClip
+
+/**
+ * An applet audio clip using the javax.sound API.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.8 $
+ */
+public class AppletAudioClip implements AudioClip {
+
+    /** the clip */
+    private Clip clip;
+
+    /**
+     * Creates new AudioClip.  If the clip cannot be opened no
+     * exception is thrown, instead the methods of the AudioClip
+     * return without performing any operations.
+     *
+     * @param location the clip location
+     */
+    public AppletAudioClip(URL location) {
+        try {
+            AudioInputStream stream = AudioSystem.getAudioInputStream(location);
+
+            clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
+            clip.open(stream);
+        } catch (Exception ex) {
+            System.err.println("Error loading sound:" + location.toString());
+            clip = null;
+        }
+    }
+
+    /**
+     * Plays the clip in a continuous loop until the stop method is
+     * called.
+     */
+    public void loop() {
+        if (clip == null)
+            return;
+
+        clip.loop(Clip.LOOP_CONTINUOUSLY);
+    }
+
+    /**
+     * Plays the clip from the beginning.
+     */
+    public void play() {
+        if (clip == null)
+            return;
+
+        // applet audio clip resets to beginning when played again
+        clip.stop();
+        clip.setFramePosition(0);
+        clip.start();
+    }
+
+    /**
+     * Stops playing the clip.
+     */
+    public void stop() {
+        if (clip == null)
+            return;
+
+        clip.stop();
+    }
+
+    /**
+     * Stops playing the clip and disposes it; the clip cannot be
+     * played after being disposed.
+     */
+    void dispose() {
+        if (clip != null) {
+            clip.stop();
+            clip.flush();
+            clip.close();
+        }
+
+        clip = null;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java	(revision 403)
@@ -0,0 +1,346 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.applet.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+import java.lang.reflect.InvocationTargetException;
+import java.net.*;
+import java.io.*;
+import javax.swing.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.util.*;
+
+/**
+ * The applet environment including stub, context, and frame.  The
+ * default environment puts the applet in a non-resiable frame;
+ * this can be changed by obtaining the frame and setting it
+ * resizable.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.12 $
+ */
+public class AppletEnvironment implements AppletContext, AppletStub {
+
+    /** the JNLP file */
+    private JNLPFile file;
+
+    /** the applet */
+    private Applet applet;
+
+    /** the parameters */
+    private Map<String, String> parameters;
+
+    /** the applet container */
+    private Container cont;
+
+    /** weak references to the audio clips */
+    private WeakList<AppletAudioClip> weakClips = new WeakList<AppletAudioClip>();
+
+    /** whether the applet has been started / displayed */
+    private boolean appletStarted = false;
+
+    /** whether the applet has been destroyed */
+    private boolean destroyed = false;
+
+    /**
+     * Create a new applet environment for the applet specified by
+     * the JNLP file.
+     */
+    public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance, Container cont) {
+        this.file = file;
+        this.applet = appletInstance.getApplet();
+
+        parameters = file.getApplet().getParameters();
+        this.cont = cont;
+    }
+
+    /**
+     * Create a new applet environment for the applet specified by
+     * the JNLP file, in a new frame.
+     */
+    public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance) {
+        this(file, appletInstance, null);
+
+        Frame frame = new Frame(file.getApplet().getName() + " - Applet");
+        frame.setResizable(false);
+
+        appletInstance.addWindow(frame);
+        // may not need this once security manager can close windows
+        // that do not have app code on the stack
+        WindowListener closer = new WindowAdapter() {
+            public void windowClosing(WindowEvent event) {
+                appletInstance.destroy();
+                System.exit(0);
+            }
+        };
+        frame.addWindowListener(closer);
+        this.cont = frame;
+    }
+
+    /**
+     * Checks whether the applet has been destroyed, and throws an
+     * IllegalStateException if the applet has been destroyed of.
+     *
+     * @throws IllegalStateException
+     */
+    private void checkDestroyed() {
+        if (destroyed)
+            throw new IllegalStateException("Illegal applet stub/context access: applet destroyed.");
+    }
+
+    /**
+     * Disposes the applet's resources and disables the applet
+     * environment from further use; after calling this method the
+     * applet stub and context methods throw IllegalStateExceptions.
+     */
+    public void destroy() {
+        destroyed = true;
+
+        List<AppletAudioClip> clips = weakClips.hardList();
+        for (int i = 0; i < clips.size(); i++) {
+            clips.get(i).dispose();
+        }
+    }
+
+    /**
+     * Returns the frame that contains the applet.  Disposing this
+     * frame will destroy the applet.
+     */
+    public Container getAppletFrame() {
+        // TODO: rename this method to getAppletContainer ?
+        return cont;
+    }
+
+    /**
+     * Initialize, start, and show the applet.
+     */
+    public void startApplet() {
+        checkDestroyed();
+
+        if (appletStarted)
+            return;
+
+        appletStarted = true;
+
+        try {
+            AppletDesc appletDesc = file.getApplet();
+
+            if (cont instanceof AppletStub)
+                applet.setStub((AppletStub) cont);
+            else
+                applet.setStub(this);
+
+            cont.setLayout(new BorderLayout());
+            cont.add("Center", applet);
+            cont.validate();
+
+            // This is only needed if the applet is in its own frame.
+            if (cont instanceof Frame) {
+                Frame frame = (Frame) cont;
+                frame.pack(); // cause insets to be calculated
+
+                Insets insets = frame.getInsets();
+                frame.setSize(appletDesc.getWidth() + insets.left + insets.right,
+                              appletDesc.getHeight() + insets.top + insets.bottom);
+            }
+
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        // do first because some applets need to be displayed before
+                        // starting (they use Component.getImage or something)
+                        cont.setVisible(true);
+
+                        applet.init();
+                        applet.start();
+
+                        cont.invalidate(); // this should force the applet to
+                        cont.validate(); // the correct size and to repaint
+                        cont.repaint();
+                    }
+                });
+            } catch (InterruptedException ie) {
+
+            } catch (InvocationTargetException ite) {
+
+            }
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            // should also kill the applet?
+        }
+    }
+
+    // applet context methods
+
+    /**
+     * Returns the applet if the applet's name is specified,
+     * otherwise return null.
+     */
+    public Applet getApplet(String name) {
+        checkDestroyed();
+
+        if (name != null && name.equals(file.getApplet().getName()))
+            return applet;
+        else
+            return null;
+    }
+
+    /**
+     * Returns an enumeration that contains only the applet
+     * from the JNLP file.
+     */
+    public Enumeration<Applet> getApplets() {
+        checkDestroyed();
+
+        return Collections.enumeration(Arrays.asList(new Applet[] { applet }));
+    }
+
+    /**
+     * Returns an audio clip.
+     */
+    public AudioClip getAudioClip(URL location) {
+        checkDestroyed();
+
+        AppletAudioClip clip = new AppletAudioClip(location);
+
+        weakClips.add(clip);
+        weakClips.trimToSize();
+
+        return clip;
+    }
+
+    /**
+     * Return an image loaded from the specified location.
+     */
+    public Image getImage(URL location) {
+        checkDestroyed();
+
+        //return Toolkit.getDefaultToolkit().createImage(location);
+        Image image = (new ImageIcon(location)).getImage();
+
+        return image;
+    }
+
+    /**
+     * Not implemented yet.
+     */
+    public void showDocument(java.net.URL uRL) {
+        checkDestroyed();
+
+    }
+
+    /**
+     * Not implemented yet.
+     */
+    public void showDocument(java.net.URL uRL, java.lang.String str) {
+        checkDestroyed();
+
+    }
+
+    /**
+     * Not implemented yet.
+     */
+    public void showStatus(java.lang.String str) {
+        checkDestroyed();
+
+    }
+
+    /**
+     * Required for JRE1.4, but not implemented yet.
+     */
+    public void setStream(String key, InputStream stream) {
+        checkDestroyed();
+
+    }
+
+    /**
+     * Required for JRE1.4, but not implemented yet.
+     */
+    public InputStream getStream(String key) {
+        checkDestroyed();
+
+        return null;
+    }
+
+    /**
+     * Required for JRE1.4, but not implemented yet.
+     */
+    public Iterator<String> getStreamKeys() {
+        checkDestroyed();
+
+        return null;
+    }
+
+    // stub methods
+
+    public void appletResize(int width, int height) {
+        checkDestroyed();
+
+        if (cont instanceof Frame) {
+            Frame frame = (Frame) cont;
+            Insets insets = frame.getInsets();
+
+            frame.setSize(width + insets.left + insets.right,
+                          height + insets.top + insets.bottom);
+        }
+    }
+
+    public AppletContext getAppletContext() {
+        checkDestroyed();
+
+        return this;
+    }
+
+    public URL getCodeBase() {
+        checkDestroyed();
+
+        return file.getCodeBase();
+    }
+
+    public URL getDocumentBase() {
+        checkDestroyed();
+
+        return file.getApplet().getDocumentBase();
+    }
+
+    // FIXME: Sun's applet code forces all parameters to lower case.
+    // Does Netx's JNLP code do the same, so we can remove the first lookup?
+    public String getParameter(String name) {
+        checkDestroyed();
+
+        String s = (String) parameters.get(name);
+        if (s != null)
+            return s;
+
+        return (String) parameters.get(name.toLowerCase());
+    }
+
+    public boolean isActive() {
+        checkDestroyed();
+
+        // it won't be started or stopped, so if it can call it's running
+        return true;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletInstance.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletInstance.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/AppletInstance.java	(revision 403)
@@ -0,0 +1,127 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.applet.*;
+import java.awt.*;
+
+import net.sourceforge.jnlp.*;
+
+/**
+ * Represents a launched application instance created from a JNLP
+ * file.  This class does not control the operation of the applet,
+ * use the AppletEnvironment class to start and stop the applet.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.9 $
+ */
+public class AppletInstance extends ApplicationInstance {
+
+    /** whether the applet's stop and destroy methods have been called */
+    private boolean appletStopped = false;
+
+    /** the applet */
+    private Applet applet;
+
+    /** the applet environment */
+    private AppletEnvironment environment;
+
+    /**
+     * Create a New Task based on the Specified URL
+     */
+    public AppletInstance(JNLPFile file, ThreadGroup group, ClassLoader loader, Applet applet) {
+        super(file, group, loader);
+
+        this.applet = applet;
+
+        this.environment = new AppletEnvironment(file, this);
+    }
+
+    /**
+     *
+     */
+    public AppletInstance(JNLPFile file, ThreadGroup group, ClassLoader loader, Applet applet, Container cont) {
+        super(file, group, loader);
+        this.applet = applet;
+        this.environment = new AppletEnvironment(file, this, cont);
+    }
+
+    /**
+     * Sets whether the applet is resizable or not.  Applets default
+     * to being not resizable.
+     */
+    public void setResizable(boolean resizable) {
+        Container c = environment.getAppletFrame();
+        if (c instanceof Frame)
+            ((Frame) c).setResizable(resizable);
+    }
+
+    /**
+     * Returns whether the applet is resizable.
+     */
+    public boolean isResizable() {
+        Container c = environment.getAppletFrame();
+        if (c instanceof Frame)
+            return ((Frame) c).isResizable();
+
+        return false;
+    }
+
+    /**
+     * Returns the application title.
+     */
+    public String getTitle() {
+        return getJNLPFile().getApplet().getName();
+    }
+
+    /**
+     * Returns the applet environment.
+     */
+    public AppletEnvironment getAppletEnvironment() {
+        return environment;
+    }
+
+    /**
+     * Returns the applet.
+     */
+    public Applet getApplet() {
+        return applet;
+    }
+
+    /**
+     * Stop the application and destroy its resources.
+     */
+    public void destroy() {
+        if (appletStopped)
+            return;
+
+        appletStopped = true;
+
+        try {
+            applet.stop();
+            applet.destroy();
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+        }
+
+        environment.destroy();
+
+        super.destroy();
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java	(revision 403)
@@ -0,0 +1,355 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.awt.Window;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+import javax.swing.event.EventListenerList;
+
+import sun.awt.AppContext;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.PropertyDesc;
+import net.sourceforge.jnlp.SecurityDesc;
+import net.sourceforge.jnlp.ShortcutDesc;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.event.ApplicationEvent;
+import net.sourceforge.jnlp.event.ApplicationListener;
+import net.sourceforge.jnlp.security.SecurityDialogs;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.util.WeakList;
+import net.sourceforge.jnlp.util.XDesktopEntry;
+
+/**
+ * Represents a running instance of an application described in a
+ * JNLPFile.  This class provides a way to track the application's
+ * resources and destroy the application.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.15 $
+ */
+public class ApplicationInstance {
+
+    // todo: should attempt to unload the environment variables
+    // installed by the application.
+
+    /** the file */
+    private JNLPFile file;
+
+    /** the thread group */
+    private ThreadGroup group;
+
+    /** the classloader */
+    private ClassLoader loader;
+
+    /**
+     * Every application/applet gets its own AppContext. This allows us to do
+     * things like have two different look and feels for two different applets
+     * (running in the same VM), allows untrusted programs to manipulate the
+     * event queue (safely) and (possibly) more.<p>
+     *
+     * It is set to the AppContext which created this ApplicationInstance
+     */
+    private AppContext appContext;
+
+    /** whether the application has stopped running */
+    private boolean stopped = false;
+
+    /** weak list of windows opened by the application */
+    private WeakList<Window> weakWindows = new WeakList<Window>();
+
+    /** list of application listeners  */
+    private EventListenerList listeners = new EventListenerList();
+
+    /** whether or not this application is signed */
+    private boolean isSigned = false;
+
+    /**
+     * Create an application instance for the file. This should be done in the
+     * appropriate {@link ThreadGroup} only.
+     */
+    public ApplicationInstance(JNLPFile file, ThreadGroup group, ClassLoader loader) {
+        this.file = file;
+        this.group = group;
+        this.loader = loader;
+        this.isSigned = ((JNLPClassLoader) loader).getSigning();
+        this.appContext = AppContext.getAppContext();
+    }
+
+    /**
+     * Add an Application listener
+     */
+    public void addApplicationListener(ApplicationListener listener) {
+        listeners.add(ApplicationListener.class, listener);
+    }
+
+    /**
+     * Remove an Application Listener
+     */
+    public void removeApplicationListener(ApplicationListener listener) {
+        listeners.remove(ApplicationListener.class, listener);
+    }
+
+    /**
+     * Notify listeners that the application has been terminated.
+     */
+    protected void fireDestroyed() {
+        Object list[] = listeners.getListenerList();
+        ApplicationEvent event = null;
+
+        for (int i = list.length - 1; i > 0; i -= 2) { // last to first required
+            if (event == null)
+                event = new ApplicationEvent(this);
+
+            ((ApplicationListener) list[i]).applicationDestroyed(event);
+        }
+    }
+
+    /**
+     * Initialize the application's environment (installs
+     * environment variables, etc).
+     */
+    public void initialize() {
+        installEnvironment();
+
+        //Fixme: -Should check whether a desktop entry already exists for
+        //        for this jnlp file, and do nothing if it exists.
+        //       -If no href is specified in the jnlp tag, it should
+        //        default to using the one passed in as an argument.
+        addMenuAndDesktopEntries();
+    }
+
+    /**
+     * Creates menu and desktop entries if required by the jnlp file
+     */
+
+    private void addMenuAndDesktopEntries() {
+        XDesktopEntry entry = new XDesktopEntry(file);
+        ShortcutDesc sd = file.getInformation().getShortcut();
+
+        if (shouldCreateShortcut(sd)) {
+            entry.createDesktopShortcut();
+        }
+
+        if (sd != null && sd.getMenu() != null) {
+            /*
+             * Sun's WebStart implementation doesnt seem to do anything under GNOME
+             */
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("ApplicationInstance.addMenuAndDesktopEntries():"
+                        + " Adding menu entries NOT IMPLEMENTED");
+            }
+        }
+
+    }
+
+    /**
+     * Indicates whether a desktop launcher/shortcut should be created for this
+     * application instance
+     *
+     * @param sd the ShortcutDesc element from the JNLP file
+     * @return true if a desktop shortcut should be created
+     */
+    private boolean shouldCreateShortcut(ShortcutDesc sd) {
+        String currentSetting = JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_CREATE_DESKTOP_SHORTCUT);
+        boolean createShortcut = false;
+
+        /*
+         * check configuration and possibly prompt user to find out if a
+         * shortcut should be created or not
+         */
+        if (currentSetting.equals(ShortcutDesc.CREATE_NEVER)) {
+            createShortcut = false;
+        } else if (currentSetting.equals(ShortcutDesc.CREATE_ALWAYS)) {
+            createShortcut = true;
+        } else if (currentSetting.equals(ShortcutDesc.CREATE_ASK_USER)) {
+            if (SecurityDialogs.showAccessWarningDialog(AccessType.CREATE_DESTKOP_SHORTCUT, file)) {
+                createShortcut = true;
+            }
+        } else if (currentSetting.equals(ShortcutDesc.CREATE_ASK_USER_IF_HINTED)) {
+            if (sd != null && sd.onDesktop()) {
+                if (SecurityDialogs.showAccessWarningDialog(AccessType.CREATE_DESTKOP_SHORTCUT, file)) {
+                    createShortcut = true;
+                }
+            }
+        } else if (currentSetting.equals(ShortcutDesc.CREATE_ALWAYS_IF_HINTED)) {
+            if (sd != null && sd.onDesktop()) {
+                createShortcut = true;
+            }
+        }
+
+        return createShortcut;
+    }
+
+    /**
+     * Releases the application's resources before it is collected.
+     * Only collectable if classloader and thread group are
+     * also collectable so basically is almost never called (an
+     * application would have to close its windows and exit its
+     * threads but not call System.exit).
+     */
+    public void finalize() {
+        destroy();
+    }
+
+    /**
+     * Install the environment variables.
+     */
+    void installEnvironment() {
+        final PropertyDesc props[] = file.getResources().getProperties();
+
+        CodeSource cs = new CodeSource((URL) null, (java.security.cert.Certificate[]) null);
+
+        JNLPClassLoader loader = (JNLPClassLoader) this.loader;
+        SecurityDesc s = loader.getSecurity();
+
+        ProtectionDomain pd = new ProtectionDomain(cs, s.getPermissions(cs), null, null);
+
+        // Add to hashmap
+        AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] { pd });
+
+        PrivilegedAction<Object> installProps = new PrivilegedAction<Object>() {
+            public Object run() {
+                for (int i = 0; i < props.length; i++) {
+                    System.setProperty(props[i].getKey(), props[i].getValue());
+                }
+
+                return null;
+            }
+        };
+        AccessController.doPrivileged(installProps, acc);
+    }
+
+    /**
+     * Returns the JNLP file for this task.
+     */
+    public JNLPFile getJNLPFile() {
+        return file;
+    }
+
+    /**
+     * Returns the application title.
+     */
+    public String getTitle() {
+        return file.getTitle();
+    }
+
+    /**
+     * Returns whether the application is running.
+     */
+    public boolean isRunning() {
+        return !stopped;
+    }
+
+    /**
+     * Stop the application and destroy its resources.
+     */
+    @SuppressWarnings("deprecation")
+    public void destroy() {
+        if (stopped)
+            return;
+
+        try {
+            // destroy resources
+            for (int i = 0; i < weakWindows.size(); i++) {
+                Window w = weakWindows.get(i);
+                if (w != null)
+                    w.dispose();
+            }
+
+            weakWindows.clear();
+
+            // interrupt threads
+            Thread threads[] = new Thread[group.activeCount() * 2];
+            int nthreads = group.enumerate(threads);
+            for (int i = 0; i < nthreads; i++) {
+                if (JNLPRuntime.isDebug())
+                    System.out.println("Interrupt thread: " + threads[i]);
+
+                threads[i].interrupt();
+            }
+
+            // then stop
+            Thread.currentThread().yield();
+            nthreads = group.enumerate(threads);
+            for (int i = 0; i < nthreads; i++) {
+                if (JNLPRuntime.isDebug())
+                    System.out.println("Stop thread: " + threads[i]);
+
+                threads[i].stop();
+            }
+
+            // then destroy - except Thread.destroy() not implemented in jdk
+
+        } finally {
+            stopped = true;
+            fireDestroyed();
+        }
+    }
+
+    /**
+     * Returns the thread group.
+     *
+     * @throws IllegalStateException if the app is not running
+     */
+    public ThreadGroup getThreadGroup() throws IllegalStateException {
+        if (stopped)
+            throw new IllegalStateException();
+
+        return group;
+    }
+
+    /**
+     * Returns the classloader.
+     *
+     * @throws IllegalStateException if the app is not running
+     */
+    public ClassLoader getClassLoader() throws IllegalStateException {
+        if (stopped)
+            throw new IllegalStateException();
+
+        return loader;
+    }
+
+    /**
+     * Adds a window that this application opened.  When the
+     * application is disposed, these windows will also be disposed.
+     */
+    protected void addWindow(Window window) {
+        weakWindows.add(window);
+        weakWindows.trimToSize();
+    }
+
+    /**
+     * Returns whether or not this jar is signed.
+     */
+    public boolean isSigned() {
+        return isSigned;
+    }
+
+    public AppContext getAppContext() {
+        return appContext;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot.java	(revision 403)
@@ -0,0 +1,349 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.Launcher;
+import net.sourceforge.jnlp.ParserSettings;
+import net.sourceforge.jnlp.cache.CacheUtil;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.security.viewer.CertificateViewer;
+import net.sourceforge.jnlp.services.ServiceUtil;
+
+/**
+ * This is the main entry point for the JNLP client.  The main
+ * method parses the command line parameters and loads a JNLP
+ * file into the secure runtime environment.  This class is meant
+ * to be called from the command line or file association; to
+ * initialize the netx engine from other code invoke the
+ * <code>JNLPRuntime.initialize</code> method after configuring
+ * the runtime.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.21 $
+ */
+public final class Boot implements PrivilegedAction<Void> {
+
+    // todo: decide whether a spawned netx (external launch)
+    // should inherit the same options as this instance (store argv?)
+
+    private static final String name = Boot.class.getPackage().getImplementationTitle();
+    private static final String version = Boot.class.getPackage().getImplementationVersion();
+
+    /** the text to display before launching the about link */
+    private static final String aboutMessage = ""
+            + name + " " + version
+            + "\n"
+            + R("BLaunchAbout");
+
+    private static final String miniLicense = "\n"
+            + "   netx - an open-source JNLP client.\n"
+            + "   Copyright (C) 2001-2003 Jon A. Maxwell (JAM)\n"
+            + "\n"
+            + "   // This library is free software; you can redistribute it and/or\n"
+            + "   modify it under the terms of the GNU Lesser General Public\n"
+            + "   License as published by the Free Software Foundation; either\n"
+            + "   version 2.1 of the License, or (at your option) any later version.\n"
+            + "\n"
+            + "   This library is distributed in the hope that it will be useful,\n"
+            + "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+            + "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
+            + "   Lesser General Public License for more details.\n"
+            + "\n"
+            + "   You should have received a copy of the GNU Lesser General Public\n"
+            + "   License along with this library; if not, write to the Free Software\n"
+            + "   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n"
+            + "\n";
+
+    private static final String helpMessage = "\n"
+            + "Usage:   " + R("BOUsage") + "\n"
+            + "         " + R("BOUsage2") + "\n"
+            + "\n"
+            + "control-options:" + "\n"
+            + "  -about                " + R("BOAbout") + "\n"
+            + "  -viewer               " + R("BOViewer") + "\n"
+            + "\n"
+            + "run-options:" + "\n"
+            + "  -arg arg              " + R("BOArg") + "\n"
+            + "  -param name=value     " + R("BOParam") + "\n"
+            + "  -property name=value  " + R("BOProperty") + "\n"
+            + "  -update seconds       " + R("BOUpdate") + "\n"
+            + "  -license              " + R("BOLicense") + "\n"
+            + "  -verbose              " + R("BOVerbose") + "\n"
+            + "  -nosecurity           " + R("BONosecurity") + "\n"
+            + "  -noupdate             " + R("BONoupdate") + "\n"
+            + "  -headless             " + R("BOHeadless") + "\n"
+            + "  -strict               " + R("BOStrict") + "\n"
+            + "  -Xnofork              " + R("BXnofork") + "\n"
+            + "  -Xclearcache          " + R("BXclearcache") + "\n"
+            + "  -help                 " + R("BOHelp") + "\n";
+
+    private static final String doubleArgs = "-basedir -jnlp -arg -param -property -update";
+
+    private static String args[]; // avoid the hot potato
+
+    /**
+     * Launch the JNLP file specified by the command-line arguments.
+     */
+    public static void main(String[] argsIn) {
+        args = argsIn;
+
+        if (null != getOption("-viewer")) {
+
+            try {
+                CertificateViewer.main(null);
+                System.exit(0);
+            } catch (Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+
+        }
+
+        if (null != getOption("-license")) {
+            System.out.println(miniLicense);
+            System.exit(0);
+        }
+
+        if (null != getOption("-help")) {
+            System.out.println(helpMessage);
+            System.exit(0);
+        }
+
+        if (null != getOption("-about"))
+            System.out.println(aboutMessage);
+
+        if (null != getOption("-verbose"))
+            JNLPRuntime.setDebug(true);
+
+        if (null != getOption("-update")) {
+            int value = Integer.parseInt(getOption("-update"));
+            JNLPRuntime.setDefaultUpdatePolicy(new UpdatePolicy(value * 1000l));
+        }
+
+        if (null != getOption("-headless"))
+            JNLPRuntime.setHeadless(true);
+
+        if (null != getOption("-noupdate"))
+            JNLPRuntime.setDefaultUpdatePolicy(UpdatePolicy.NEVER);
+
+        if (null != getOption("-Xnofork")) {
+            JNLPRuntime.setForksAllowed(false);
+        }
+
+        JNLPRuntime.setInitialArgments(Arrays.asList(argsIn));
+
+        // do in a privileged action to clear the security context of
+        // the Boot13 class, which doesn't have any privileges in
+        // JRE1.3; JRE1.4 works without Boot13 or this PrivilegedAction.
+        AccessController.doPrivileged(new Boot());
+
+    }
+
+    /**
+     * The privileged part (jdk1.3 compatibility).
+     */
+    public Void run() {
+        JNLPRuntime.setSecurityEnabled(null == getOption("-nosecurity"));
+        JNLPRuntime.initialize(true);
+
+        /*
+         * FIXME
+         * This should have been done with the rest of the argument parsing
+         * code. But we need to know what the cache and base directories are,
+         * and baseDir is initialized here
+         */
+        if (null != getOption("-Xclearcache")) {
+            CacheUtil.clearCache();
+            return null;
+        }
+
+        Map<String, String[]> extra = new HashMap<String, String[]>();
+        extra.put("arguments", getOptions("-arg"));
+        extra.put("parameters", getOptions("-param"));
+        extra.put("properties", getOptions("-property"));
+
+        boolean strict = (null != getOption("-strict"));
+        ParserSettings settings = new ParserSettings(strict);
+
+        try {
+            Launcher launcher = new Launcher(false);
+            launcher.setParserSettings(settings);
+            launcher.setInformationToMerge(extra);
+            launcher.launch(getFileLocation(), true);
+        } catch (LaunchException ex) {
+            // default handler prints this
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+
+            fatalError(R("RUnexpected", ex.toString(), ex.getStackTrace()[0]));
+        }
+
+        return null;
+    }
+
+    private static void fatalError(String message) {
+        System.err.println("netx: " + message);
+        System.exit(1);
+    }
+
+    /**
+     * Returns the location of the about.jnlp file or null if this file
+     * does not exist.
+     */
+    private static String getAboutFile() {
+        ClassLoader cl = Boot.class.getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+        try {
+                    //extracts full path to about.jnlp
+            String s = cl.getResource("net/sourceforge/jnlp/runtime/Boot.class").toString();
+            s=s.substring(0,s.indexOf("!"));
+            s=s.substring(s.indexOf(":")+1);
+            s=s.substring(s.indexOf(":")+1);
+            s="file://"+s.replace("netx.jar","about.jnlp");
+            if (JNLPRuntime.isDebug()){
+                System.out.println("Using " + s + " as about.jnlp URL");
+            }
+
+            return s;
+         } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * Returns the url of file to open; does not return if no file was
+     * specified, or if the file location was invalid.
+     */
+    private static URL getFileLocation() {
+
+        String location = getJNLPFile();
+
+        // override -jnlp with aboutFile
+        if (getOption("-about") != null) {
+            location = getAboutFile();
+            if (location == null)
+                fatalError(R("RNoAboutJnlp"));
+        } else {
+            location = getJNLPFile();
+        }
+
+        if (location == null) {
+            System.out.println(helpMessage);
+            System.exit(1);
+        }
+
+        if (JNLPRuntime.isDebug())
+            System.out.println(R("BFileLoc") + ": " + location);
+
+        URL url = null;
+
+        try {
+            if (new File(location).exists())
+                // TODO: Should be toURI().toURL()
+                url = new File(location).toURL(); // Why use file.getCanonicalFile?
+            else
+                url = new URL(ServiceUtil.getBasicService().getCodeBase(), location);
+        } catch (Exception e) {
+            fatalError("Invalid jnlp file " + location);
+            if (JNLPRuntime.isDebug())
+                e.printStackTrace();
+        }
+
+        return url;
+    }
+
+    /**
+     * Gets the JNLP file from the command line arguments, or exits upon error.
+     */
+    private static String getJNLPFile() {
+
+        if (args.length == 0) {
+            System.out.println(helpMessage);
+            System.exit(0);
+        } else if (args.length == 1) {
+            return args[args.length - 1];
+        } else {
+            String lastArg = args[args.length - 1];
+            String secondLastArg = args[args.length - 2];
+
+            if (doubleArgs.indexOf(secondLastArg) == -1) {
+                return lastArg;
+            } else {
+                System.out.println(helpMessage);
+                System.exit(0);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return value of the first occurence of the specified
+     * option, or null if the option is not present.  If the
+     * option is a flag (0-parameter) and is present then the
+     * option name is returned.
+     */
+    private static String getOption(String option) {
+        String result[] = getOptions(option);
+
+        if (result.length == 0)
+            return null;
+        else
+            return result[0];
+    }
+
+    /**
+     * Return all the values of the specified option, or an empty
+     * array if the option is not present.  If the option is a
+     * flag (0-parameter) and is present then the option name is
+     * returned once for each occurrence.
+     */
+    private static String[] getOptions(String option) {
+        List<String> result = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (option.equals(args[i])) {
+                if (-1 == doubleArgs.indexOf(option))
+                    result.add(option);
+                else if (i + 1 < args.length)
+                    result.add(args[i + 1]);
+            }
+
+            if (args[i].startsWith("-") && -1 != doubleArgs.indexOf(args[i]))
+                i++;
+        }
+
+        return result.toArray(new String[result.size()]);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot13.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot13.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Boot13.java	(revision 403)
@@ -0,0 +1,98 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.lang.reflect.*;
+import java.net.*;
+import java.security.*;
+
+/**
+ * Allows a Policy and SecurityManager to be set in JRE1.3 without
+ * running the code with only applet permissions; this class is
+ * for backward compatibility only and is totally unnecessary if
+ * running in jdk 1.4 or later (can call Boot directly).
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.5 $
+ */
+public class Boot13 extends URLClassLoader {
+
+    // The problem with setting a Policy in jdk1.3 is that the
+    // system and application classes seem to be loaded in such a
+    // way that only their protection domain determines the
+    // permissions; the policy object is never asked for permissions
+    // after the class is loaded.  This hack creates a classloader
+    // that loads duplicate versions of the classes in such a
+    // manner where they ask with the policy object.  The jdk1.4
+    // correctly honors the Policy object making this unneccessary
+    // post-1.3.
+
+    private Boot13(URL source[]) {
+        super(source);
+    }
+
+    protected PermissionCollection getPermissions(CodeSource source) {
+        Permissions result = new Permissions();
+        result.add(new AllPermission());
+
+        return result;
+    }
+
+    public Class loadClass(String name) throws ClassNotFoundException {
+        Class c = findLoadedClass(name);
+        if (c != null)
+            return c;
+
+        // reverse the search order so that classes from this
+        // classloader, which sets the right permissions, are found
+        // before the parent classloader which has the same classes
+        // but the wrong permissions.
+        try {
+            return findClass(name);
+        } catch (ClassNotFoundException ex) {
+        }
+
+        return getParent().loadClass(name);
+    }
+
+    public static void main(final String args[]) throws Exception {
+        URL cs = Boot13.class.getProtectionDomain().getCodeSource().getLocation();
+        //  instead of using a custom loadClass search order, we could
+        //  put the classes in a boot/ subdir of the JAR and load
+        //  them from there.  This would be an improvement by not
+        //  allowing applications to get a duplicate jnlp engine (one
+        //  with applet access permissions) by using the system
+        //  classloader but a drawback by not allowing Boot to be
+        //  called directly.
+        //cs = new URL("jar:"+cs+"!/boot/");
+
+        if (cs == null) {
+            System.err.println("fatal: cannot determine code source.");
+            System.exit(1);
+        }
+
+        Boot13 b = new Boot13(new URL[] { cs });
+
+        Thread.currentThread().setContextClassLoader(b); // try to prevent getting the non-policy version of classes
+
+        Class<?> c = b.loadClass("net.sourceforge.jnlp.runtime.Boot");
+        Method main = c.getDeclaredMethod("main", new Class<?>[] { String[].class });
+
+        main.invoke(null, new Object[] { args });
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java	(revision 403)
@@ -0,0 +1,157 @@
+/* CachedJarFileCallback.java
+   Copyright (C) 2011 Red Hat, Inc.
+   Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.JarFile;
+
+import net.sourceforge.jnlp.util.UrlUtils;
+
+import sun.net.www.protocol.jar.URLJarFile;
+import sun.net.www.protocol.jar.URLJarFileCallBack;
+
+/**
+ * Invoked by URLJarFile to get a JarFile corresponding to a URL.
+ *
+ * Large parts of this class are based on JarFileFactory and URLJarFile.
+ */
+final class CachedJarFileCallback implements URLJarFileCallBack {
+
+    private static final CachedJarFileCallback INSTANCE = new CachedJarFileCallback();
+
+    public synchronized static CachedJarFileCallback getInstance() {
+        return INSTANCE;
+    }
+
+    /* our managed cache */
+    private final Map<URL, URL> mapping;
+
+    private CachedJarFileCallback() {
+        mapping = new ConcurrentHashMap<URL, URL>();
+    }
+
+    protected void addMapping(URL remoteUrl, URL localUrl) {
+        mapping.put(remoteUrl, localUrl);
+    }
+
+    @Override
+    public JarFile retrieve(URL url) throws IOException {
+        URL localUrl = mapping.get(url);
+
+        if (localUrl == null) {
+            /*
+             * If the jar url is not known, treat it as it would be treated in
+             * general by URLJarFile.
+             */
+            return cacheJarFile(url);
+        }
+
+        if (UrlUtils.isLocalFile(localUrl)) {
+            // if it is known to us, just return the cached file
+            return new JarFile(localUrl.getPath());
+        } else {
+            // throw new IllegalStateException("a non-local file in cache");
+            return null;
+        }
+
+    }
+
+    /*
+     * This method is a copy of URLJarFile.retrieve() without the callback check.
+     */
+    private JarFile cacheJarFile(URL url) throws IOException {
+        JarFile result = null;
+
+        final int BUF_SIZE = 2048;
+
+        /* get the stream before asserting privileges */
+        final InputStream in = url.openConnection().getInputStream();
+
+        try {
+            result =
+                    AccessController.doPrivileged(new PrivilegedExceptionAction<JarFile>() {
+                        @Override
+                        public JarFile run() throws IOException {
+                            OutputStream out = null;
+                            File tmpFile = null;
+                            try {
+                                tmpFile = File.createTempFile("jar_cache", null);
+                                tmpFile.deleteOnExit();
+                                out = new FileOutputStream(tmpFile);
+                                int read = 0;
+                                byte[] buf = new byte[BUF_SIZE];
+                                while ((read = in.read(buf)) != -1) {
+                                    out.write(buf, 0, read);
+                                }
+                                out.close();
+                                out = null;
+                                return new URLJarFile(tmpFile, null);
+                            } catch (IOException e) {
+                                if (tmpFile != null) {
+                                    tmpFile.delete();
+                                }
+                                throw e;
+                            } finally {
+                                if (in != null) {
+                                    in.close();
+                                }
+                                if (out != null) {
+                                    out.close();
+                                }
+                            }
+                        }
+                    });
+        } catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getException();
+        }
+
+        return result;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java	(revision 403)
@@ -0,0 +1,54 @@
+/* FakePacEvaluator.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+import java.net.URL;
+
+/**
+ * A dummy PacEvaluator that always returns "DIRECT"
+ */
+public class FakePacEvaluator implements PacEvaluator {
+    @Override
+    public String getProxies(URL url) {
+        if (JNLPRuntime.isDebug()) {
+            System.err.println(R("RPRoxyPacNotSupported"));
+        }
+        return "DIRECT";
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	(revision 403)
@@ -0,0 +1,1467 @@
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import net.sourceforge.jnlp.DownloadOptions;
+import net.sourceforge.jnlp.ExtensionDesc;
+import net.sourceforge.jnlp.JARDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.ParseException;
+import net.sourceforge.jnlp.PluginBridge;
+import net.sourceforge.jnlp.ResourcesDesc;
+import net.sourceforge.jnlp.SecurityDesc;
+import net.sourceforge.jnlp.Version;
+import net.sourceforge.jnlp.cache.CacheUtil;
+import net.sourceforge.jnlp.cache.ResourceTracker;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.security.SecurityDialogs;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.tools.JarSigner;
+import net.sourceforge.jnlp.util.FileUtils;
+import sun.misc.JarIndex;
+
+/**
+ * Classloader that takes it's resources from a JNLP file.  If the
+ * JNLP file defines extensions, separate classloaders for these
+ * will be created automatically.  Classes are loaded with the
+ * security context when the classloader was created.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.20 $
+ */
+public class JNLPClassLoader extends URLClassLoader {
+
+    // todo: initializePermissions should get the permissions from
+    // extension classes too so that main file classes can load
+    // resources in an extension.
+
+    /** map from JNLPFile url to shared classloader */
+    private static Map<String, JNLPClassLoader> urlToLoader =
+            new HashMap<String, JNLPClassLoader>(); // never garbage collected!
+
+    /** the directory for native code */
+    private File nativeDir = null; // if set, some native code exists
+
+    /** a list of directories that contain native libraries */
+    private List<File> nativeDirectories = Collections.synchronizedList(new LinkedList<File>());
+
+    /** security context */
+    private AccessControlContext acc = AccessController.getContext();
+
+    /** the permissions for the cached jar files */
+    private List<Permission> resourcePermissions;
+
+    /** the app */
+    private ApplicationInstance app = null; // here for faster lookup in security manager
+
+    /** list of this, local and global loaders this loader uses */
+    private JNLPClassLoader loaders[] = null; // ..[0]==this
+
+    /** whether to strictly adhere to the spec or not */
+    private boolean strict = true;
+
+    /** loads the resources */
+    private ResourceTracker tracker = new ResourceTracker(true); // prefetch
+
+    /** the update policy for resources */
+    private UpdatePolicy updatePolicy;
+
+    /** the JNLP file */
+    private JNLPFile file;
+
+    /** the resources section */
+    private ResourcesDesc resources;
+
+    /** the security section */
+    private SecurityDesc security;
+
+    /** Permissions granted by the user during runtime. */
+    private ArrayList<Permission> runtimePermissions = new ArrayList<Permission>();
+
+    /** all jars not yet part of classloader or active */
+    private List<JARDesc> available = new ArrayList<JARDesc>();
+
+    /** all of the jar files that were verified */
+    private ArrayList<String> verifiedJars = null;
+
+    /** all of the jar files that were not verified */
+    private ArrayList<String> unverifiedJars = null;
+
+    /** the jarsigner tool to verify our jars */
+    private JarSigner js = null;
+
+    private boolean signing = false;
+
+    /** ArrayList containing jar indexes for various jars available to this classloader */
+    private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>();
+
+    /** Set of classpath strings declared in the manifest.mf files */
+    private Set<String> classpaths = new HashSet<String>();
+
+    /** File entries in the jar files available to this classloader */
+    private TreeSet<String> jarEntries = new TreeSet<String>();
+
+    /** Map of specific original (remote) CodeSource Urls  to securitydesc */
+    private HashMap<URL, SecurityDesc> jarLocationSecurityMap =
+            new HashMap<URL, SecurityDesc>();
+    
+    /** Loader for codebase (which is a path, rather than a file) */
+    private CodeBaseClassLoader codeBaseLoader;
+
+    /**
+     * Create a new JNLPClassLoader from the specified file.
+     *
+     * @param file the JNLP file
+     */
+    protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy) throws LaunchException {
+        super(new URL[0], JNLPClassLoader.class.getClassLoader());
+
+        if (JNLPRuntime.isDebug())
+            System.out.println("New classloader: " + file.getFileLocation());
+
+        this.file = file;
+        this.updatePolicy = policy;
+        this.resources = file.getResources();
+
+        // initialize extensions
+        initializeExtensions();
+
+        initializeResources();
+
+        // initialize permissions
+        initializePermissions();
+
+        setSecurity();
+
+        installShutdownHooks();
+
+    }
+
+    /**
+     * Install JVM shutdown hooks to clean up resources allocated by this
+     * ClassLoader.
+     */
+    private void installShutdownHooks() {
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                /*
+                 * Delete only the native dir created by this classloader (if
+                 * there is one). Other classloaders (parent, peers) will all
+                 * cleanup things they created
+                 */
+                if (nativeDir != null) {
+                    if (JNLPRuntime.isDebug()) {
+                        System.out.println("Cleaning up native directory" + nativeDir.getAbsolutePath());
+                    }
+                    try {
+                        FileUtils.recursiveDelete(nativeDir,
+                                new File(System.getProperty("java.io.tmpdir")));
+                    } catch (IOException e) {
+                        /*
+                         * failed to delete a file in tmpdir, no big deal (not
+                         * to mention that the VM is shutting down at this
+                         * point so no much we can do)
+                         */
+                    }
+                }
+            }
+        });
+    }
+
+    private void setSecurity() throws LaunchException {
+
+        URL codebase = null;
+
+        if (file.getCodeBase() != null) {
+            codebase = file.getCodeBase();
+        } else {
+            //Fixme: codebase should be the codebase of the Main Jar not
+            //the location. Although, it still works in the current state.
+            codebase = file.getResources().getMainJAR().getLocation();
+        }
+
+        /**
+         * When we're trying to load an applet, file.getSecurity() will return
+         * null since there is no jnlp file to specify permissions. We
+         * determine security settings here, after trying to verify jars.
+         */
+        if (file instanceof PluginBridge) {
+            if (signing == true) {
+                this.security = new SecurityDesc(file,
+                        SecurityDesc.ALL_PERMISSIONS,
+                        codebase.getHost());
+            } else {
+                this.security = new SecurityDesc(file,
+                        SecurityDesc.SANDBOX_PERMISSIONS,
+                        codebase.getHost());
+            }
+        } else { //regular jnlp file
+
+            /*
+             * Various combinations of the jars being signed and <security> tags being
+             * present are possible. They are treated as follows
+             *
+             * Jars          JNLP File         Result
+             *
+             * Signed        <security>        Appropriate Permissions
+             * Signed        no <security>     Sandbox
+             * Unsigned      <security>        Error
+             * Unsigned      no <security>     Sandbox
+             *
+             */
+            if (!file.getSecurity().getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS) && !signing) {
+                throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LUnsignedJarWithSecurity"), R("LUnsignedJarWithSecurityInfo"));
+            } else if (signing == true) {
+                this.security = file.getSecurity();
+            } else {
+                this.security = new SecurityDesc(file,
+                        SecurityDesc.SANDBOX_PERMISSIONS,
+                        codebase.getHost());
+            }
+        }
+    }
+
+    /**
+     * Returns a JNLP classloader for the specified JNLP file.
+     *
+     * @param file the file to load classes for
+     * @param policy the update policy to use when downloading resources
+     */
+    public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy) throws LaunchException {
+        JNLPClassLoader baseLoader = null;
+        JNLPClassLoader loader = null;
+        String uniqueKey = file.getUniqueKey();
+
+        if (uniqueKey != null)
+            baseLoader = urlToLoader.get(uniqueKey);
+
+        try {
+
+
+            // A null baseloader implies that no loader has been created 
+            // for this codebase/jnlp yet. Create one.
+            if (baseLoader == null ||
+                    (file.isApplication() && 
+                     !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) {
+
+                loader = new JNLPClassLoader(file, policy);
+
+                // New loader init may have caused extentions to create a
+                // loader for this unique key. Check.
+                JNLPClassLoader extLoader = urlToLoader.get(uniqueKey);
+
+                if (extLoader != null && extLoader != loader) {
+                    if (loader.signing && !extLoader.signing)
+                        if (!SecurityDialogs.showNotAllSignedWarningDialog(file))
+                            throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo"));
+
+                    loader.merge(extLoader);
+                }
+
+                // loader is now current + ext. But we also need to think of
+                // the baseLoader
+                if (baseLoader != null && baseLoader != loader) {
+                    loader.merge(baseLoader);
+                }
+
+            } else {
+                // if key is same and locations match, this is the loader we want
+                if (!file.isApplication()) {
+                    // If this is an applet, we do need to consider its loader
+                    loader = new JNLPClassLoader(file, policy);
+
+                    if (baseLoader != null)
+                        baseLoader.merge(loader);
+                }
+                loader = baseLoader;
+            }
+
+        } catch (LaunchException e) {
+            throw e;
+        }
+
+        // loaders are mapped to a unique key. Only extensions and parent
+        // share a key, so it is safe to always share based on it
+        urlToLoader.put(uniqueKey, loader);
+
+        return loader;
+    }
+
+    /**
+     * Returns a JNLP classloader for the JNLP file at the specified
+     * location.
+     *
+     * @param location the file's location
+     * @param version the file's version
+     * @param policy the update policy to use when downloading resources
+     */
+    public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy)
+            throws IOException, ParseException, LaunchException {
+        JNLPClassLoader loader = urlToLoader.get(uniqueKey);
+
+        if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation()))
+            loader = getInstance(new JNLPFile(location, uniqueKey, version, false, policy), policy);
+
+        return loader;
+    }
+
+    /**
+     * Load the extensions specified in the JNLP file.
+     */
+    void initializeExtensions() {
+        ExtensionDesc[] ext = resources.getExtensions();
+
+        List<JNLPClassLoader> loaderList = new ArrayList<JNLPClassLoader>();
+
+        loaderList.add(this);
+
+        //if (ext != null) {
+        for (int i = 0; i < ext.length; i++) {
+            try {
+                String uniqueKey = this.getJNLPFile().getUniqueKey();
+                JNLPClassLoader loader = getInstance(ext[i].getLocation(), uniqueKey, ext[i].getVersion(), updatePolicy);
+                loaderList.add(loader);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+        //}
+
+        loaders = loaderList.toArray(new JNLPClassLoader[loaderList.size()]);
+    }
+
+    /**
+     * Make permission objects for the classpath.
+     */
+    void initializePermissions() {
+        resourcePermissions = new ArrayList<Permission>();
+
+        JARDesc jars[] = resources.getJARs();
+        for (int i = 0; i < jars.length; i++) {
+            Permission p = CacheUtil.getReadPermission(jars[i].getLocation(),
+                                                       jars[i].getVersion());
+
+            if (JNLPRuntime.isDebug()) {
+                if (p == null)
+                    System.out.println("Unable to add permission for " + jars[i].getLocation());
+                else
+                    System.out.println("Permission added: " + p.toString());
+            }
+            if (p != null)
+                resourcePermissions.add(p);
+        }
+    }
+
+    /**
+     * Load all of the JARs used in this JNLP file into the
+     * ResourceTracker for downloading.
+     */
+    void initializeResources() throws LaunchException {
+        JARDesc jars[] = resources.getJARs();
+        if (jars == null || jars.length == 0)
+            return;
+        /*
+        if (jars == null || jars.length == 0) {
+                throw new LaunchException(null, null, R("LSFatal"),
+                                    R("LCInit"), R("LFatalVerification"), "No jars!");
+        }
+        */
+        List<JARDesc> initialJars = new ArrayList<JARDesc>();
+
+        for (int i = 0; i < jars.length; i++) {
+
+            available.add(jars[i]);
+
+            if (jars[i].isEager())
+                initialJars.add(jars[i]); // regardless of part
+
+            tracker.addResource(jars[i].getLocation(),
+                                jars[i].getVersion(),
+                                getDownloadOptionsForJar(jars[i]),
+                                jars[i].isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE
+                               );
+        }
+
+        if (strict)
+            fillInPartJars(initialJars); // add in each initial part's lazy jars
+
+        if (JNLPRuntime.isVerifying()) {
+
+            JarSigner js;
+            waitForJars(initialJars); //download the jars first.
+
+            try {
+                js = verifyJars(initialJars);
+            } catch (Exception e) {
+                //we caught an Exception from the JarSigner class.
+                //Note: one of these exceptions could be from not being able
+                //to read the cacerts or trusted.certs files.
+                e.printStackTrace();
+                throw new LaunchException(null, null, R("LSFatal"),
+                                        R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo"));
+            }
+
+            //Case when at least one jar has some signing
+            if (js.anyJarsSigned() && js.isFullySignedByASingleCert()) {
+                signing = true;
+
+                if (!js.allJarsSigned() &&
+                                    !SecurityDialogs.showNotAllSignedWarningDialog(file))
+                    throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo"));
+
+                //user does not trust this publisher
+                if (!js.getAlreadyTrustPublisher()) {
+                    checkTrustWithUser(js);
+                } else {
+                    /**
+                     * If the user trusts this publisher (i.e. the publisher's certificate
+                     * is in the user's trusted.certs file), we do not show any dialogs.
+                     */
+                }
+            } else {
+
+                signing = false;
+                //otherwise this jar is simply unsigned -- make sure to ask
+                //for permission on certain actions
+            }
+        }
+
+        for (JARDesc jarDesc : file.getResources().getJARs()) {
+            try {
+                File cachedFile = tracker.getCacheFile(jarDesc.getLocation());
+
+                if (cachedFile == null) {
+                    System.err.println("JAR " + jarDesc.getLocation() + " not found. Continuing.");
+                    continue; // JAR not found. Keep going.
+                }
+
+                // TODO: Should be toURI().toURL()
+                URL location = cachedFile.toURL();
+                SecurityDesc jarSecurity = file.getSecurity();
+
+                if (file instanceof PluginBridge) {
+
+                    URL codebase = null;
+
+                    if (file.getCodeBase() != null) {
+                        codebase = file.getCodeBase();
+                    } else {
+                        //Fixme: codebase should be the codebase of the Main Jar not
+                        //the location. Although, it still works in the current state.
+                        codebase = file.getResources().getMainJAR().getLocation();
+                    }
+
+                    if (signing) {
+                        jarSecurity = new SecurityDesc(file,
+                                                        SecurityDesc.ALL_PERMISSIONS,
+                                                        codebase.getHost());
+                    } else {
+                        jarSecurity = new SecurityDesc(file,
+                                                        SecurityDesc.SANDBOX_PERMISSIONS,
+                                                        codebase.getHost());
+                    }
+                }
+
+                jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity);
+            } catch (MalformedURLException mfe) {
+                System.err.println(mfe.getMessage());
+            }
+        }
+
+        activateJars(initialJars);
+    }
+
+    private void checkTrustWithUser(JarSigner js) throws LaunchException {
+        if (!js.getRootInCacerts()) { //root cert is not in cacerts
+            boolean b = SecurityDialogs.showCertWarningDialog(
+                    AccessType.UNVERIFIED, file, js);
+            if (!b)
+                throw new LaunchException(null, null, R("LSFatal"),
+                        R("LCLaunching"), R("LNotVerified"), "");
+        } else if (js.getRootInCacerts()) { //root cert is in cacerts
+            boolean b = false;
+            if (js.noSigningIssues())
+                b = SecurityDialogs.showCertWarningDialog(
+                        AccessType.VERIFIED, file, js);
+            else if (!js.noSigningIssues())
+                b = SecurityDialogs.showCertWarningDialog(
+                        AccessType.SIGNING_ERROR, file, js);
+            if (!b)
+                throw new LaunchException(null, null, R("LSFatal"),
+                        R("LCLaunching"), R("LCancelOnUserRequest"), "");
+        }
+    }
+
+    /**
+     * Add applet's codebase URL.  This allows compatibility with
+     * applets that load resources from their codebase instead of
+     * through JARs, but can slow down resource loading.  Resources
+     * loaded from the codebase are not cached.
+     */
+    public void enableCodeBase() {
+        addToCodeBaseLoader(file.getCodeBase());
+    }
+
+    /**
+     * Sets the JNLP app this group is for; can only be called once.
+     */
+    public void setApplication(ApplicationInstance app) {
+        if (this.app != null) {
+            if (JNLPRuntime.isDebug()) {
+                Exception ex = new IllegalStateException("Application can only be set once");
+                ex.printStackTrace();
+            }
+            return;
+        }
+
+        this.app = app;
+    }
+
+    /**
+     * Returns the JNLP app for this classloader
+     */
+    public ApplicationInstance getApplication() {
+        return app;
+    }
+
+    /**
+     * Returns the JNLP file the classloader was created from.
+     */
+    public JNLPFile getJNLPFile() {
+        return file;
+    }
+
+    /**
+     * Returns the permissions for the CodeSource.
+     */
+    protected PermissionCollection getPermissions(CodeSource cs) {
+        Permissions result = new Permissions();
+
+        // should check for extensions or boot, automatically give all
+        // access w/o security dialog once we actually check certificates.
+
+        // copy security permissions from SecurityDesc element
+        if (security != null) {
+            // Security desc. is used only to track security settings for the
+            // application. However, an application may comprise of multiple
+            // jars, and as such, security must be evaluated on a per jar basis.
+
+            // set default perms
+            PermissionCollection permissions = security.getSandBoxPermissions();
+
+            // If more than default is needed:
+            // 1. Code must be signed
+            // 2. ALL or J2EE permissions must be requested (note: plugin requests ALL automatically)
+            if (cs.getCodeSigners() != null &&
+                    (getCodeSourceSecurity(cs.getLocation()).getSecurityType().equals(SecurityDesc.ALL_PERMISSIONS) ||
+                     getCodeSourceSecurity(cs.getLocation()).getSecurityType().equals(SecurityDesc.J2EE_PERMISSIONS))) {
+
+                permissions = getCodeSourceSecurity(cs.getLocation()).getPermissions(cs);
+            }
+
+            Enumeration<Permission> e = permissions.elements();
+            while (e.hasMoreElements())
+                result.add(e.nextElement());
+        }
+
+        // add in permission to read the cached JAR files
+        for (int i = 0; i < resourcePermissions.size(); i++)
+            result.add(resourcePermissions.get(i));
+
+        // add in the permissions that the user granted.
+        for (int i = 0; i < runtimePermissions.size(); i++)
+            result.add(runtimePermissions.get(i));
+
+        return result;
+    }
+
+    protected void addPermission(Permission p) {
+        runtimePermissions.add(p);
+    }
+
+    /**
+     * Adds to the specified list of JARS any other JARs that need
+     * to be loaded at the same time as the JARs specified (ie, are
+     * in the same part).
+     */
+    protected void fillInPartJars(List<JARDesc> jars) {
+        for (int i = 0; i < jars.size(); i++) {
+            String part = jars.get(i).getPart();
+
+            for (int a = 0; a < available.size(); a++) {
+                JARDesc jar = available.get(a);
+
+                if (part != null && part.equals(jar.getPart()))
+                    if (!jars.contains(jar))
+                        jars.add(jar);
+            }
+        }
+    }
+
+    /**
+     * Ensures that the list of jars have all been transferred, and
+     * makes them available to the classloader.  If a jar contains
+     * native code, the libraries will be extracted and placed in
+     * the path.
+     *
+     * @param jars the list of jars to load
+     */
+    protected void activateJars(final List<JARDesc> jars) {
+        PrivilegedAction<Void> activate = new PrivilegedAction<Void>() {
+
+            @SuppressWarnings("deprecation")
+            public Void run() {
+                // transfer the Jars
+                waitForJars(jars);
+
+                for (int i = 0; i < jars.size(); i++) {
+                    JARDesc jar = jars.get(i);
+
+                    available.remove(jar);
+
+                    // add jar
+                    File localFile = tracker.getCacheFile(jar.getLocation());
+                    try {
+                        URL location = jar.getLocation(); // non-cacheable, use source location
+                        if (localFile != null) {
+                            // TODO: Should be toURI().toURL()
+                            location = localFile.toURL(); // cached file
+
+                            // This is really not the best way.. but we need some way for
+                            // PluginAppletViewer::getCachedImageRef() to check if the image
+                            // is available locally, and it cannot use getResources() because
+                            // that prefetches the resource, which confuses MediaTracker.waitForAll()
+                            // which does a wait(), waiting for notification (presumably
+                            // thrown after a resource is fetched). This bug manifests itself
+                            // particularly when using The FileManager applet from Webmin.
+
+                            JarFile jarFile = new JarFile(localFile);
+                            Enumeration<JarEntry> e = jarFile.entries();
+                            while (e.hasMoreElements()) {
+                                JarEntry je = e.nextElement();
+
+                                // another jar in my jar? it is more likely than you think
+                                if (je.getName().endsWith(".jar")) {
+                                    // We need to extract that jar so that it can be loaded
+                                    // (inline loading with "jar:..!/..." path will not work
+                                    // with standard classloader methods)
+
+                                    String extractedJarLocation = localFile.getParent() + "/" + je.getName();
+                                    File parentDir = new File(extractedJarLocation).getParentFile();
+                                    if (!parentDir.isDirectory() && !parentDir.mkdirs()) {
+                                        throw new RuntimeException(R("RNestedJarExtration"));
+                                    }
+                                    FileOutputStream extractedJar = new FileOutputStream(extractedJarLocation);
+                                    InputStream is = jarFile.getInputStream(je);
+
+                                    byte[] bytes = new byte[1024];
+                                    int read = is.read(bytes);
+                                    int fileSize = read;
+                                    while (read > 0) {
+                                        extractedJar.write(bytes, 0, read);
+                                        read = is.read(bytes);
+                                        fileSize += read;
+                                    }
+
+                                    is.close();
+                                    extractedJar.close();
+
+                                    // 0 byte file? skip
+                                    if (fileSize <= 0) {
+                                        continue;
+                                    }
+
+                                    JarSigner signer = new JarSigner();
+                                    List<JARDesc> jars = new ArrayList<JARDesc>();
+                                    JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false);
+                                    jars.add(jarDesc);
+                                    tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null);
+                                    signer.verifyJars(jars, tracker);
+
+                                    if (signer.anyJarsSigned() && !signer.getAlreadyTrustPublisher()) {
+                                        checkTrustWithUser(signer);
+                                    }
+
+                                    try {
+                                        URL fileURL = new URL("file://" + extractedJarLocation);
+                                        // there is no remote URL for this, so lets fake one
+                                        URL fakeRemote = new URL(jar.getLocation().toString() + "!" + je.getName());
+                                        CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL);
+                                        addURL(fakeRemote);
+
+                                        SecurityDesc jarSecurity = file.getSecurity();
+
+                                        if (file instanceof PluginBridge) {
+
+                                            URL codebase = null;
+
+                                            if (file.getCodeBase() != null) {
+                                                codebase = file.getCodeBase();
+                                            } else {
+                                                //Fixme: codebase should be the codebase of the Main Jar not
+                                                //the location. Although, it still works in the current state.
+                                                codebase = file.getResources().getMainJAR().getLocation();
+                                            }
+
+                                            jarSecurity = new SecurityDesc(file,
+                                                    SecurityDesc.ALL_PERMISSIONS,
+                                                    codebase.getHost());
+                                        }
+
+                                        jarLocationSecurityMap.put(fakeRemote, jarSecurity);
+
+                                    } catch (MalformedURLException mfue) {
+                                        if (JNLPRuntime.isDebug())
+                                            System.err.println("Unable to add extracted nested jar to classpath");
+
+                                        mfue.printStackTrace();
+                                    }
+                                }
+
+                                jarEntries.add(je.getName());
+                            }
+
+                        }
+
+                        addURL(jar.getLocation());
+
+                        // there is currently no mechanism to cache files per
+                        // instance.. so only index cached files
+                        if (localFile != null) {
+                            CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), localFile.toURL());
+
+                            JarFile jarFile = new JarFile(localFile.getAbsolutePath());
+                            Manifest mf = jarFile.getManifest();
+                            classpaths.addAll(getClassPathsFromManifest(mf, jar.getLocation().getPath()));
+                            JarIndex index = JarIndex.getJarIndex(jarFile, null);
+                            if (index != null)
+                                jarIndexes.add(index);
+                        } else {
+                            CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), jar.getLocation());
+                        }
+
+                        if (JNLPRuntime.isDebug())
+                            System.err.println("Activate jar: " + location);
+                    }
+                    catch (Exception ex) {
+                        if (JNLPRuntime.isDebug())
+                            ex.printStackTrace();
+                    }
+
+                    // some programs place a native library in any jar
+                    activateNative(jar);
+                }
+
+                return null;
+            }
+        };
+
+        AccessController.doPrivileged(activate, acc);
+    }
+
+    /**
+     * Search for and enable any native code contained in a JAR by copying the
+     * native files into the filesystem. Called in the security context of the
+     * classloader.
+     */
+    protected void activateNative(JARDesc jar) {
+        if (JNLPRuntime.isDebug())
+            System.out.println("Activate native: " + jar.getLocation());
+
+        File localFile = tracker.getCacheFile(jar.getLocation());
+        if (localFile == null)
+            return;
+
+        String[] librarySuffixes = { ".so", ".dylib", ".jnilib", ".framework", ".dll" };
+
+        try {
+            JarFile jarFile = new JarFile(localFile, false);
+            Enumeration<JarEntry> entries = jarFile.entries();
+
+            while (entries.hasMoreElements()) {
+                JarEntry e = entries.nextElement();
+
+                if (e.isDirectory()) {
+                    continue;
+                }
+
+                String name = new File(e.getName()).getName();
+                boolean isLibrary = false;
+
+                for (String suffix : librarySuffixes) {
+                    if (name.endsWith(suffix)) {
+                        isLibrary = true;
+                        break;
+                    }
+                }
+                if (!isLibrary) {
+                    continue;
+                }
+
+                if (nativeDir == null)
+                    nativeDir = getNativeDir();
+
+                File outFile = new File(nativeDir, name);
+                if (!outFile.isFile()) {
+                    FileUtils.createRestrictedFile(outFile, true);
+                }
+                CacheUtil.streamCopy(jarFile.getInputStream(e),
+                                     new FileOutputStream(outFile));
+
+            }
+        } catch (IOException ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+        }
+    }
+
+    /**
+     * Return the base directory to store native code files in.
+     * This method does not need to return the same directory across
+     * calls.
+     */
+    protected File getNativeDir() {
+        final int rand = (int)((Math.random()*2 - 1) * Integer.MAX_VALUE);
+        nativeDir = new File(System.getProperty("java.io.tmpdir")
+                             + File.separator + "netx-native-"
+                             + (rand & 0xFFFF));
+        File parent = nativeDir.getParentFile();
+        if (!parent.isDirectory() && !parent.mkdirs()) {
+            return null;
+        }
+
+        try {
+            FileUtils.createRestrictedDirectory(nativeDir);
+            // add this new native directory to the search path
+            addNativeDirectory(nativeDir);
+            return nativeDir;
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Adds the {@link File} to the search path of this {@link JNLPClassLoader}
+     * when trying to find a native library
+     */
+    protected void addNativeDirectory(File nativeDirectory) {
+        nativeDirectories.add(nativeDirectory);
+    }
+
+    /**
+     * Returns a list of all directories in the search path of the current classloader
+     * when it tires to find a native library.
+     * @return a list of directories in the search path for native libraries
+     */
+    protected List<File> getNativeDirectories() {
+        return nativeDirectories;
+    }
+
+    /**
+     * Return the absolute path to the native library.
+     */
+    protected String findLibrary(String lib) {
+        String syslib = System.mapLibraryName(lib);
+
+        for (File dir : getNativeDirectories()) {
+            File target = new File(dir, syslib);
+            if (target.exists())
+                return target.toString();
+        }
+
+        String result = super.findLibrary(lib);
+        if (result != null)
+            return result;
+
+        return findLibraryExt(lib);
+    }
+
+    /**
+     * Try to find the library path from another peer classloader.
+     */
+    protected String findLibraryExt(String lib) {
+        for (int i = 0; i < loaders.length; i++) {
+            String result = null;
+
+            if (loaders[i] != this)
+                result = loaders[i].findLibrary(lib);
+
+            if (result != null)
+                return result;
+        }
+
+        return null;
+    }
+
+    /**
+     * Wait for a group of JARs, and send download events if there
+     * is a download listener or display a progress window otherwise.
+     *
+     * @param jars the jars
+     */
+    private void waitForJars(List jars) {
+        URL urls[] = new URL[jars.size()];
+
+        for (int i = 0; i < jars.size(); i++) {
+            JARDesc jar = (JARDesc) jars.get(i);
+
+            urls[i] = jar.getLocation();
+        }
+
+        CacheUtil.waitForResources(app, tracker, urls, file.getTitle());
+    }
+
+    /**
+         * Verifies code signing of jars to be used.
+         *
+         * @param jars the jars to be verified.
+         */
+    private JarSigner verifyJars(List<JARDesc> jars) throws Exception {
+
+        js = new JarSigner();
+        js.verifyJars(jars, tracker);
+        return js;
+    }
+
+    /**
+     * Find the loaded class in this loader or any of its extension loaders.
+     */
+    protected Class findLoadedClassAll(String name) {
+        for (int i = 0; i < loaders.length; i++) {
+            Class result = null;
+
+            if (loaders[i] == this)
+                result = super.findLoadedClass(name);
+            else
+                result = loaders[i].findLoadedClassAll(name);
+
+            if (result != null)
+                return result;
+        }
+        
+        // Result is still null. Return what the codebaseloader 
+        // has (which returns null if it is not loaded there either)
+        if (codeBaseLoader != null)
+            return codeBaseLoader.findLoadedClassFromParent(name);
+        else
+            return null;
+    }
+
+    /**
+     * Find a JAR in the shared 'extension' classloaders, this
+     * classloader, or one of the classloaders for the JNLP file's
+     * extensions.
+     */
+    public synchronized Class<?> loadClass(String name) throws ClassNotFoundException {
+
+        Class<?> result = findLoadedClassAll(name);
+
+        // try parent classloader
+        if (result == null) {
+            try {
+                ClassLoader parent = getParent();
+                if (parent == null)
+                    parent = ClassLoader.getSystemClassLoader();
+
+                return parent.loadClass(name);
+            } catch (ClassNotFoundException ex) {
+            }
+        }
+
+        // filter out 'bad' package names like java, javax
+        // validPackage(name);
+
+        // search this and the extension loaders
+        if (result == null) {
+            try {
+                result = loadClassExt(name);
+            } catch (ClassNotFoundException cnfe) {
+                // Not found in external loader either
+
+                // Look in 'Class-Path' as specified in the manifest file
+                try {
+                    for (String classpath: classpaths) {
+                        JARDesc desc;
+                        try {
+                            URL jarUrl = new URL(file.getCodeBase(), classpath);
+                            desc = new JARDesc(jarUrl, null, null, false, true, false, true);
+                        } catch (MalformedURLException mfe) {
+                            throw new ClassNotFoundException(name, mfe);
+                        }
+                        addNewJar(desc);
+                    }
+
+                    result = loadClassExt(name);
+                    return result;
+                } catch (ClassNotFoundException cnfe1) {
+                    if (JNLPRuntime.isDebug()) {
+                        cnfe1.printStackTrace();
+                    }
+                }
+
+                // As a last resort, look in any available indexes
+
+                // Currently this loads jars directly from the site. We cannot cache it because this
+                // call is initiated from within the applet, which does not have disk read/write permissions
+                for (JarIndex index : jarIndexes) {
+                    // Non-generic code in sun.misc.JarIndex
+                    @SuppressWarnings("unchecked")
+                    LinkedList<String> jarList = index.get(name.replace('.', '/'));
+
+                    if (jarList != null) {
+                        for (String jarName : jarList) {
+                            JARDesc desc;
+                            try {
+                                desc = new JARDesc(new URL(file.getCodeBase(), jarName),
+                                        null, null, false, true, false, true);
+                            } catch (MalformedURLException mfe) {
+                                throw new ClassNotFoundException(name);
+                            }
+                            try {
+                                addNewJar(desc);
+                            } catch (Exception e) {
+                                if (JNLPRuntime.isDebug()) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+
+                        // If it still fails, let it error out
+                        result = loadClassExt(name);
+                    }
+                }
+            }
+        }
+
+        if (result == null) {
+            throw new ClassNotFoundException(name);
+        }
+
+        return result;
+    }
+
+    /**
+     * Adds a new JARDesc into this classloader.
+     * <p>
+     * This will add the JARDesc into the resourceTracker and block until it
+     * is downloaded.
+     * @param desc the JARDesc for the new jar
+     */
+    private void addNewJar(JARDesc desc) {
+
+        available.add(desc);
+
+        tracker.addResource(desc.getLocation(),
+                desc.getVersion(),
+                null,
+                JNLPRuntime.getDefaultUpdatePolicy()
+                );
+
+        URL remoteURL = desc.getLocation();
+        URL cachedUrl = tracker.getCacheURL(remoteURL);
+        addURL(remoteURL);
+        CachedJarFileCallback.getInstance().addMapping(remoteURL, cachedUrl);
+    }
+
+    /**
+     * Find the class in this loader or any of its extension loaders.
+     */
+    protected Class findClass(String name) throws ClassNotFoundException {
+        for (int i = 0; i < loaders.length; i++) {
+            try {
+                if (loaders[i] == this)
+                    return super.findClass(name);
+                else
+                    return loaders[i].findClass(name);
+            } catch (ClassNotFoundException ex) {
+            } catch (ClassFormatError cfe) {
+            }
+        }
+
+        // Try codebase loader
+        if (codeBaseLoader != null)
+            return codeBaseLoader.findClass(name);
+        
+        // All else failed. Throw CNFE
+        throw new ClassNotFoundException(name);
+    }
+
+    /**
+     * Search for the class by incrementally adding resources to the
+     * classloader and its extension classloaders until the resource
+     * is found.
+     */
+    private Class loadClassExt(String name) throws ClassNotFoundException {
+        // make recursive
+        addAvailable();
+
+        // find it
+        try {
+            return findClass(name);
+        } catch (ClassNotFoundException ex) {
+        }
+
+        // add resources until found
+        while (true) {
+            JNLPClassLoader addedTo = addNextResource();
+
+            if (addedTo == null)
+                throw new ClassNotFoundException(name);
+
+            try {
+                return addedTo.findClass(name);
+            } catch (ClassNotFoundException ex) {
+            }
+        }
+    }
+
+    /**
+     * Finds the resource in this, the parent, or the extension
+     * class loaders.
+     */
+    public URL getResource(String name) {
+        URL result = super.getResource(name);
+
+        for (int i = 1; i < loaders.length; i++)
+            if (result == null)
+                result = loaders[i].getResource(name);
+        
+        // If result is still null, look in the codebase loader
+        if (result == null && codeBaseLoader != null)
+            result = codeBaseLoader.getResource(name);
+
+        return result;
+    }
+
+    /**
+     * Finds the resource in this, the parent, or the extension
+     * class loaders.
+     */
+    @Override
+    public Enumeration<URL> findResources(String name) throws IOException {
+        Vector<URL> resources = new Vector<URL>();
+        Enumeration<URL> e;
+
+        for (int i = 0; i < loaders.length; i++) {
+
+            if (loaders[i] == this)
+                e = super.findResources(name);
+            else
+                e = loaders[i].findResources(name);
+
+            while (e.hasMoreElements())
+                resources.add(e.nextElement());
+        }
+
+        // Add resources from codebase (only if nothing was found above, 
+        // otherwise the server will get hammered) 
+        if (resources.isEmpty() && codeBaseLoader != null) {
+            e = codeBaseLoader.findResources(name);
+            while (e.hasMoreElements())
+                resources.add(e.nextElement());
+        }
+
+        return resources.elements();
+    }
+
+    /**
+     * Returns if the specified resource is available locally from a cached jar
+     *
+     * @param s The name of the resource
+     * @return Whether or not the resource is available locally
+     */
+    public boolean resourceAvailableLocally(String s) {
+        return jarEntries.contains(s);
+    }
+
+    /**
+     * Adds whatever resources have already been downloaded in the
+     * background.
+     */
+    protected void addAvailable() {
+        // go through available, check tracker for it and all of its
+        // part brothers being available immediately, add them.
+
+        for (int i = 1; i < loaders.length; i++) {
+            loaders[i].addAvailable();
+        }
+    }
+
+    /**
+     * Adds the next unused resource to the classloader.  That
+     * resource and all those in the same part will be downloaded
+     * and added to the classloader before returning.  If there are
+     * no more resources to add, the method returns immediately.
+     *
+     * @return the classloader that resources were added to, or null
+     */
+    protected JNLPClassLoader addNextResource() {
+        if (available.size() == 0) {
+            for (int i = 1; i < loaders.length; i++) {
+                JNLPClassLoader result = loaders[i].addNextResource();
+
+                if (result != null)
+                    return result;
+            }
+            return null;
+        }
+
+        // add jar
+        List<JARDesc> jars = new ArrayList<JARDesc>();
+        jars.add(available.get(0));
+
+        fillInPartJars(jars);
+        activateJars(jars);
+
+        return this;
+    }
+
+    // this part compatibility with previous classloader
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public String getExtensionName() {
+        String result = file.getInformation().getTitle();
+
+        if (result == null)
+            result = file.getInformation().getDescription();
+        if (result == null && file.getFileLocation() != null)
+            result = file.getFileLocation().toString();
+        if (result == null && file.getCodeBase() != null)
+            result = file.getCodeBase().toString();
+
+        return result;
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public String getExtensionHREF() {
+        return file.getFileLocation().toString();
+    }
+
+    public boolean getSigning() {
+        return signing;
+    }
+
+    protected SecurityDesc getSecurity() {
+        return security;
+    }
+
+    /**
+     * Returns the security descriptor for given code source URL
+     *
+     * @param source the origin (remote) url of the code
+     * @return The SecurityDescriptor for that source
+     */
+
+    protected SecurityDesc getCodeSourceSecurity(URL source) {
+        return jarLocationSecurityMap.get(source);
+    }
+
+    /**
+     * Merges the code source/security descriptor mapping from another loader
+     *
+     * @param extLoader The loader form which to merge
+     * @throws SecurityException if the code is called from an untrusted source
+     */
+    private void merge(JNLPClassLoader extLoader) {
+
+        try {
+            System.getSecurityManager().checkPermission(new AllPermission());
+        } catch (SecurityException se) {
+            throw new SecurityException("JNLPClassLoader() may only be called from trusted sources!");
+        }
+
+        // jars
+        for (URL u : extLoader.getURLs())
+            addURL(u);
+        
+        // Codebase
+        addToCodeBaseLoader(extLoader.file.getCodeBase());
+
+        // native search paths
+        for (File nativeDirectory : extLoader.getNativeDirectories())
+            addNativeDirectory(nativeDirectory);
+
+        // security descriptors
+        for (URL key : extLoader.jarLocationSecurityMap.keySet()) {
+            jarLocationSecurityMap.put(key, extLoader.jarLocationSecurityMap.get(key));
+        }
+    }
+
+    /**
+     * Adds the given path to the path loader
+     * 
+     * @param URL the path to add
+     * @throws IllegalArgumentException If the given url is not a path
+     */
+    private void addToCodeBaseLoader(URL u) {
+
+        // Only paths may be added
+        if (!u.getFile().endsWith("/")) {
+            throw new IllegalArgumentException("addToPathLoader only accepts path based URLs");
+        }
+
+        // If there is no loader yet, create one, else add it to the 
+        // existing one (happens when called from merge())
+        if (codeBaseLoader == null) {
+            codeBaseLoader = new CodeBaseClassLoader(new URL[] { u }, this);
+        } else {
+            codeBaseLoader.addURL(u);
+        }
+    }
+
+    private DownloadOptions getDownloadOptionsForJar(JARDesc jar) {
+        return file.getDownloadOptionsForJar(jar);
+    }
+
+    /**
+     * Returns a set of paths that indicate the Class-Path entries in the
+     * manifest file. The paths are rooted in the same directory as the
+     * originalJarPath.
+     * @param mf the manifest
+     * @param originalJarPath the remote/original path of the jar containing
+     * the manifest
+     * @return a Set of String where each string is a path to the jar on
+     * the original jar's classpath.
+     */
+    private Set<String> getClassPathsFromManifest(Manifest mf, String originalJarPath) {
+        Set<String> result = new HashSet<String>();
+        if (mf != null) {
+            // extract the Class-Path entries from the manifest and split them
+            String classpath = mf.getMainAttributes().getValue("Class-Path");
+            if (classpath == null || classpath.trim().length() == 0) {
+                return result;
+            }
+            String[] paths = classpath.split(" +");
+            for (String path : paths) {
+                if (path.trim().length() == 0) {
+                    continue;
+                }
+                // we want to search for jars in the same subdir on the server
+                // as the original jar that contains the manifest file, so find
+                // out its subdirectory and use that as the dir
+                String dir = "";
+                int lastSlash = originalJarPath.lastIndexOf("/");
+                if (lastSlash != -1) {
+                    dir = originalJarPath.substring(0, lastSlash + 1);
+                }
+                String fullPath = dir + path;
+                result.add(fullPath);
+            }
+        }
+        return result;
+    }
+
+    /*
+     * Helper class to expose protected URLClassLoader methods.
+     */
+
+    public static class CodeBaseClassLoader extends URLClassLoader {
+
+        JNLPClassLoader parentJNLPClassLoader;
+        
+        public CodeBaseClassLoader(URL[] urls, JNLPClassLoader cl) {
+            super(urls);
+            parentJNLPClassLoader = cl;
+        }
+
+        @Override
+        public void addURL(URL url) { 
+            super.addURL(url); 
+        }
+
+        @Override
+        public Class<?> findClass(String name) throws ClassNotFoundException { 
+            return super.findClass(name); 
+        }
+
+        /**
+         * Returns the output of super.findLoadedClass().
+         * 
+         * The method is renamed because ClassLoader.findLoadedClass() is final
+         * 
+         * @param name The name of the class to find
+         * @return Output of ClassLoader.findLoadedClass() which is the class if found, null otherwise 
+         * @see java.lang.ClassLoader#findLoadedClass(String)
+         */
+        public Class<?> findLoadedClassFromParent(String name) {
+            return findLoadedClass(name);
+        }
+
+        /**
+         * Returns JNLPClassLoader that encompasses this loader
+         * 
+         * @return parent JNLPClassLoader
+         */
+        public JNLPClassLoader getParentJNLPClassLoader() {
+            return parentJNLPClassLoader;
+        }
+
+        @Override
+        public Enumeration<URL> findResources(String name) throws IOException {
+            if (!name.startsWith("META-INF")) {
+                return super.findResources(name);
+            }
+            return (new Vector<URL>(0)).elements();
+        }
+
+        @Override
+        public URL findResource(String name) {
+            if (!name.startsWith("META-INF")) {
+                return super.findResource(name);
+            }
+            return null;
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java	(revision 403)
@@ -0,0 +1,185 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.*;
+import java.util.Enumeration;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+
+/**
+ * Policy for JNLP environment.  This class delegates to the
+ * system policy but always grants permissions to the JNLP code
+ * and system CodeSources (no separate policy file needed).  This
+ * class may also grant permissions to applications at runtime if
+ * approved by the user.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+public class JNLPPolicy extends Policy {
+
+    /** classes from this source have all permissions */
+    private static CodeSource shellSource;
+
+    /** classes from this source have all permissions */
+    private static CodeSource systemSource;
+
+    /** the previous policy */
+    private static Policy systemPolicy;
+
+    private final String jreExtDir;
+
+    /** the system level policy for jnlps */
+    private Policy systemJnlpPolicy = null;
+
+    /** the user-level policy for jnlps */
+    private Policy userJnlpPolicy = null;
+
+    protected JNLPPolicy() {
+        shellSource = JNLPPolicy.class.getProtectionDomain().getCodeSource();
+        systemSource = Policy.class.getProtectionDomain().getCodeSource();
+        systemPolicy = Policy.getPolicy();
+
+        systemJnlpPolicy = getPolicyFromConfig(DeploymentConfiguration.KEY_SYSTEM_SECURITY_POLICY);
+        userJnlpPolicy = getPolicyFromConfig(DeploymentConfiguration.KEY_USER_SECURITY_POLICY);
+
+        String jre = System.getProperty("java.home");
+        jreExtDir = jre + File.separator + "lib" + File.separator + "ext";
+    }
+
+    /**
+     * Return a mutable, heterogeneous-capable permission collection
+     * for the source.
+     */
+    public PermissionCollection getPermissions(CodeSource source) {
+        if (source.equals(systemSource) || source.equals(shellSource))
+            return getAllPermissions();
+
+        if (isSystemJar(source)) {
+            return getAllPermissions();
+        }
+
+        // if we check the SecurityDesc here then keep in mind that
+        // code can add properties at runtime to the ResourcesDesc!
+        if (JNLPRuntime.getApplication() != null) {
+            if (JNLPRuntime.getApplication().getClassLoader() instanceof JNLPClassLoader) {
+                JNLPClassLoader cl = (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader();
+
+                PermissionCollection clPermissions = cl.getPermissions(source);
+
+                Enumeration<Permission> e;
+                CodeSource appletCS = new CodeSource(JNLPRuntime.getApplication().getJNLPFile().getSourceLocation(), (java.security.cert.Certificate[]) null);
+
+                // systempolicy permissions need to be accounted for as well
+                e = systemPolicy.getPermissions(appletCS).elements();
+                while (e.hasMoreElements())
+                    clPermissions.add(e.nextElement());
+
+                // and so do permissions from the jnlp-specific system policy
+                if (systemJnlpPolicy != null) {
+                    e = systemJnlpPolicy.getPermissions(appletCS).elements();
+                    while (e.hasMoreElements())
+                        clPermissions.add(e.nextElement());
+                }
+
+                // and permissiosn from jnlp-specific user policy too
+                if (userJnlpPolicy != null) {
+                    e = userJnlpPolicy.getPermissions(appletCS).elements();
+                    while (e.hasMoreElements())
+                        clPermissions.add(e.nextElement());
+                }
+
+                return clPermissions;
+            }
+        }
+
+        // delegate to original Policy object; required to run under WebStart
+        return systemPolicy.getPermissions(source);
+    }
+
+    /**
+     * Refresh.
+     */
+    public void refresh() {
+        // no op
+    }
+
+    /**
+     * Return an all-permissions collection.
+     */
+    private Permissions getAllPermissions() {
+        Permissions result = new Permissions();
+
+        result.add(new AllPermission());
+        return result;
+    }
+
+    /**
+     * Returns true if the CodeSource corresponds to a system jar. That is,
+     * it's part of the JRE.
+     */
+    private boolean isSystemJar(CodeSource source) {
+        if (source == null || source.getLocation() == null) {
+            return false;
+        }
+
+        // anything in JRE/lib/ext is a system jar and has full permissions
+        String sourceProtocol = source.getLocation().getProtocol();
+        String sourcePath = source.getLocation().getPath();
+        if (sourceProtocol.toUpperCase().equals("FILE") &&
+                sourcePath.startsWith(jreExtDir)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Constructs a delegate policy based on a config setting
+     * @param key a KEY_* in DeploymentConfiguration
+     * @return a policy based on the configuration set by the user
+     */
+    private Policy getPolicyFromConfig(String key) {
+        Policy policy = null;
+        String policyLocation = null;
+        DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+        policyLocation = config.getProperty(key);
+        if (policyLocation != null) {
+            try {
+                URI policyUri = new URI(policyLocation);
+                policy = getInstance("JavaPolicy", new URIParameter(policyUri));
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (NoSuchAlgorithmException e) {
+                e.printStackTrace();
+            } catch (URISyntaxException e) {
+                e.printStackTrace();
+            }
+        }
+        return policy;
+    }
+
+    public boolean implies(ProtectionDomain domain, Permission permission) {
+        //Include the permissions that may be added during runtime.
+        PermissionCollection pc = getPermissions(domain.getCodeSource());
+        return super.implies(domain, permission) || pc.implies(permission);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java	(revision 403)
@@ -0,0 +1,418 @@
+// Copyright (C) 2010 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.net.Proxy.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+
+/**
+ * A ProxySelector specific to JNLPs. This proxy uses the deployment
+ * configuration to determine what to do.
+ *
+ * @see java.net.ProxySelector
+ */
+public abstract class JNLPProxySelector extends ProxySelector {
+
+    public static final int PROXY_TYPE_UNKNOWN = -1;
+    public static final int PROXY_TYPE_NONE = 0;
+    public static final int PROXY_TYPE_MANUAL = 1;
+    public static final int PROXY_TYPE_AUTO = 2;
+    public static final int PROXY_TYPE_BROWSER = 3;
+
+    /** The default port to use as a fallback. Currently squid's default port */
+    public static final int FALLBACK_PROXY_PORT = 3128;
+
+    private PacEvaluator pacEvaluator = null;
+
+    /** The proxy type. See PROXY_TYPE_* constants */
+    private int proxyType = PROXY_TYPE_UNKNOWN;
+
+    /** the URL to the PAC file */
+    private URL autoConfigUrl = null;
+
+    /** a list of URLs that should be bypassed for proxy purposes */
+    private List<String> bypassList = null;
+
+    /** whether localhost should be bypassed for proxy purposes */
+    private boolean bypassLocal = false;
+
+    /**
+     * whether the http proxy should be used for https and ftp protocols as well
+     */
+    private boolean sameProxy = false;
+
+    private String proxyHttpHost;
+    private int proxyHttpPort;
+    private String proxyHttpsHost;
+    private int proxyHttpsPort;
+    private String proxyFtpHost;
+    private int proxyFtpPort;
+    private String proxySocks4Host;
+    private int proxySocks4Port;
+
+    // FIXME what is this? where should it be used?
+    private String overrideHosts = null;
+
+    /**
+     * Creates a new JNLPProxySelector.
+     */
+    public JNLPProxySelector() {
+        parseConfiguration();
+    }
+
+    /**
+     * Initialize this ProxySelector by reading the configuration
+     */
+    private void parseConfiguration() {
+        DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+
+        proxyType = Integer.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_TYPE));
+
+        String autoConfigString = config.getProperty(DeploymentConfiguration.KEY_PROXY_AUTO_CONFIG_URL);
+        if (autoConfigString != null) {
+            try {
+                autoConfigUrl = new URL(autoConfigString);
+            } catch (MalformedURLException e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (autoConfigUrl != null) {
+            pacEvaluator = PacEvaluatorFactory.getPacEvaluator(autoConfigUrl);
+        }
+
+        bypassList = new ArrayList<String>();
+        String proxyBypass = config.getProperty(DeploymentConfiguration.KEY_PROXY_BYPASS_LIST);
+        if (proxyBypass != null) {
+            StringTokenizer tokenizer = new StringTokenizer(proxyBypass, ",");
+            while (tokenizer.hasMoreTokens()) {
+                String host = tokenizer.nextToken();
+                if (host != null && host.trim().length() != 0) {
+                    bypassList.add(host);
+                }
+            }
+        }
+
+        bypassLocal = Boolean.valueOf(config
+                .getProperty(DeploymentConfiguration.KEY_PROXY_BYPASS_LOCAL));
+
+        sameProxy = Boolean.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_SAME));
+
+        proxyHttpHost = getHost(config, DeploymentConfiguration.KEY_PROXY_HTTP_HOST);
+        proxyHttpPort = getPort(config, DeploymentConfiguration.KEY_PROXY_HTTP_PORT);
+
+        proxyHttpsHost = getHost(config, DeploymentConfiguration.KEY_PROXY_HTTPS_HOST);
+        proxyHttpsPort = getPort(config, DeploymentConfiguration.KEY_PROXY_HTTPS_PORT);
+
+        proxyFtpHost = getHost(config, DeploymentConfiguration.KEY_PROXY_FTP_HOST);
+        proxyFtpPort = getPort(config, DeploymentConfiguration.KEY_PROXY_FTP_PORT);
+
+        proxySocks4Host = getHost(config, DeploymentConfiguration.KEY_PROXY_SOCKS4_HOST);
+        proxySocks4Port = getPort(config, DeploymentConfiguration.KEY_PROXY_SOCKS4_PORT);
+
+        overrideHosts = config.getProperty(DeploymentConfiguration.KEY_PROXY_OVERRIDE_HOSTS);
+    }
+
+    /**
+     * Uses the given key to get a host from the configuraion
+     */
+    private String getHost(DeploymentConfiguration config, String key) {
+        String proxyHost = config.getProperty(key);
+        if (proxyHost != null) {
+            proxyHost = proxyHost.trim();
+        }
+        return proxyHost;
+    }
+
+    /**
+     * Uses the given key to get a port from the configuration
+     */
+    private int getPort(DeploymentConfiguration config, String key) {
+        int proxyPort = FALLBACK_PROXY_PORT;
+        String port;
+        port = config.getProperty(key);
+        if (port != null && port.trim().length() != 0) {
+            try {
+                proxyPort = Integer.valueOf(port);
+            } catch (NumberFormatException e) {
+                e.printStackTrace();
+            }
+        }
+        return proxyPort;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+        ioe.printStackTrace();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<Proxy> select(URI uri) {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Selecting proxy for: " + uri);
+        }
+
+        if (inBypassList(uri)) {
+            List<Proxy> proxies = Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray()));
+            }
+            return proxies;
+        }
+
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        switch (proxyType) {
+            case PROXY_TYPE_MANUAL:
+                proxies.addAll(getFromConfiguration(uri));
+                break;
+            case PROXY_TYPE_AUTO:
+                proxies.addAll(getFromPAC(uri));
+                break;
+            case PROXY_TYPE_BROWSER:
+                proxies.addAll(getFromBrowser(uri));
+                break;
+            case PROXY_TYPE_UNKNOWN:
+                // fall through
+            case PROXY_TYPE_NONE:
+                // fall through
+            default:
+                proxies.add(Proxy.NO_PROXY);
+                break;
+        }
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray()));
+        }
+        return proxies;
+    }
+
+    /**
+     * Returns true if the uri should be bypassed for proxy purposes
+     */
+    private boolean inBypassList(URI uri) {
+        try {
+            String scheme = uri.getScheme();
+            /* scheme can be http/https/ftp/socket */
+
+            if (scheme.equals("http") || scheme.equals("https") || scheme.equals("ftp")) {
+                URL url = uri.toURL();
+                if (bypassLocal && isLocalHost(url.getHost())) {
+                    return true;
+                }
+
+                if (bypassList.contains(url.getHost())) {
+                    return true;
+                }
+            } else if (scheme.equals("socket")) {
+                String host = uri.getSchemeSpecificPart().split(":")[0];
+
+                if (bypassLocal && isLocalHost(host)) {
+                    return true;
+                }
+
+                if (bypassList.contains(host)) {
+                    return true;
+                }
+            }
+        } catch (MalformedURLException e) {
+            return false;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns true if the host is the hostname or the IP address of the
+     * localhost
+     */
+    private boolean isLocalHost(String host) {
+
+        try {
+            if (InetAddress.getByName(host).isLoopbackAddress()) {
+                return true;
+            }
+        } catch (UnknownHostException e1) {
+            // continue
+        }
+
+        try {
+            if (host.equals(InetAddress.getLocalHost().getHostName())) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            // continue
+        }
+
+        try {
+            if (host.equals(InetAddress.getLocalHost().getHostAddress())) {
+                return true;
+            }
+        } catch (UnknownHostException e) {
+            // continue
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a list of proxies by using the information in the deployment
+     * configuration
+     *
+     * @param uri
+     * @return a List of Proxy objects
+     */
+    private List<Proxy> getFromConfiguration(URI uri) {
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        String scheme = uri.getScheme();
+
+        if (sameProxy) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort);
+            Proxy proxy;
+            if (scheme.equals("socket")) {
+                proxy = new Proxy(Type.SOCKS, sa);
+            } else {
+                proxy = new Proxy(Type.HTTP, sa);
+            }
+            proxies.add(proxy);
+        } else if (scheme.equals("http")) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("https")) {
+            SocketAddress sa = new InetSocketAddress(proxyHttpsHost, proxyHttpsPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("ftp")) {
+            SocketAddress sa = new InetSocketAddress(proxyFtpHost, proxyFtpPort);
+            proxies.add(new Proxy(Type.HTTP, sa));
+        } else if (scheme.equals("socket")) {
+            SocketAddress sa = new InetSocketAddress(proxySocks4Host, proxySocks4Port);
+            proxies.add(new Proxy(Type.SOCKS, sa));
+        } else {
+            proxies.add(Proxy.NO_PROXY);
+        }
+
+        return proxies;
+    }
+
+    /**
+     * Returns a list of proxies by using the Proxy Auto Config (PAC) file. See
+     * http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file for more
+     * information.
+     *
+     * @return a List of valid Proxy objects
+     */
+    protected List<Proxy> getFromPAC(URI uri) {
+        if (autoConfigUrl == null || uri.getScheme().equals("socket")) {
+            return Arrays.asList(new Proxy[] { Proxy.NO_PROXY });
+        }
+
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        try {
+            String proxiesString = pacEvaluator.getProxies(uri.toURL());
+            proxies.addAll(getProxiesFromPacResult(proxiesString));
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+            proxies.add(Proxy.NO_PROXY);
+        }
+
+        return proxies;
+    }
+
+    /**
+     * Returns a list of proxies by querying the browser
+     *
+     * @param uri the uri to get proxies for
+     * @return a list of proxies
+     */
+    protected abstract List<Proxy> getFromBrowser(URI uri);
+
+    /**
+     * Converts a proxy string from a browser into a List of Proxy objects
+     * suitable for java.
+     * @param pacString a string indicating proxies. For example
+     * "PROXY foo.bar:3128; DIRECT"
+     * @return a list of Proxy objects represeting the parsed string.
+     */
+    public static List<Proxy> getProxiesFromPacResult(String pacString) {
+        List<Proxy> proxies = new ArrayList<Proxy>();
+
+        String[] tokens = pacString.split(";");
+        for (String token: tokens) {
+            if (token.startsWith("PROXY")) {
+                String hostPortPair = token.substring("PROXY".length()).trim();
+                if (!hostPortPair.contains(":")) {
+                    continue;
+                }
+                String host = hostPortPair.split(":")[0];
+                int port;
+                try {
+                    port = Integer.valueOf(hostPortPair.split(":")[1]);
+                } catch (NumberFormatException nfe) {
+                    continue;
+                }
+                SocketAddress sa = new InetSocketAddress(host, port);
+                proxies.add(new Proxy(Type.HTTP, sa));
+            } else if (token.startsWith("SOCKS")) {
+                String hostPortPair = token.substring("SOCKS".length()).trim();
+                if (!hostPortPair.contains(":")) {
+                    continue;
+                }
+                String host = hostPortPair.split(":")[0];
+                int port;
+                try {
+                    port = Integer.valueOf(hostPortPair.split(":")[1]);
+                } catch (NumberFormatException nfe) {
+                    continue;
+                }
+                SocketAddress sa = new InetSocketAddress(host, port);
+                proxies.add(new Proxy(Type.SOCKS, sa));
+            } else if (token.startsWith("DIRECT")) {
+                proxies.add(Proxy.NO_PROXY);
+            } else {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("Unrecognized proxy token: " + token);
+                }
+            }
+        }
+
+        return proxies;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	(revision 403)
@@ -0,0 +1,735 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.*;
+import java.net.Authenticator;
+import java.net.ProxySelector;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.util.List;
+import java.security.*;
+import javax.jnlp.*;
+import javax.naming.ConfigurationException;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.swing.UIManager;
+import javax.swing.text.html.parser.ParserDelegator;
+
+import sun.net.www.protocol.jar.URLJarFile;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.browser.BrowserAwareProxySelector;
+import net.sourceforge.jnlp.cache.*;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.security.JNLPAuthenticator;
+import net.sourceforge.jnlp.security.KeyStores;
+import net.sourceforge.jnlp.security.SecurityDialogMessageHandler;
+import net.sourceforge.jnlp.security.VariableX509TrustManager;
+import net.sourceforge.jnlp.services.*;
+import net.sourceforge.jnlp.util.*;
+
+/**
+ * Configure and access the runtime environment.  This class
+ * stores global jnlp properties such as default download
+ * indicators, the install/base directory, the default resource
+ * update policy, etc.  Some settings, such as the base directory,
+ * cannot be changed once the runtime has been initialized.<p>
+ *
+ * The JNLP runtime can be locked to prevent further changes to
+ * the runtime environment except by a specified class.  If set,
+ * only instances of the <i>exit class</i> can exit the JVM or
+ * change the JNLP runtime settings once the runtime has been
+ * initialized.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.19 $
+ */
+public class JNLPRuntime {
+
+    static {
+        loadResources();
+    }
+
+    /** the localized resource strings */
+    private static ResourceBundle resources;
+
+    private static final DeploymentConfiguration config = new DeploymentConfiguration();
+
+    /** the security manager */
+    private static JNLPSecurityManager security;
+
+    /** the security policy */
+    private static JNLPPolicy policy;
+
+    /** handles all security message to show appropriate security dialogs */
+    private static SecurityDialogMessageHandler securityDialogMessageHandler;
+
+    /** a default launch handler */
+    private static LaunchHandler handler = null;
+
+    /** default download indicator */
+    private static DownloadIndicator indicator = null;
+
+    /** update policy that controls when to check for updates */
+    private static UpdatePolicy updatePolicy = UpdatePolicy.ALWAYS;
+
+    /** netx window icon */
+    private static Image windowIcon = null;
+
+    /** whether initialized */
+    private static boolean initialized = false;
+
+    /** whether netx is in command-line mode (headless) */
+    private static boolean headless = false;
+
+    /** whether we'll be checking for jar signing */
+    private static boolean verify = true;
+
+    /** whether the runtime uses security */
+    private static boolean securityEnabled = true;
+
+    /** whether debug mode is on */
+    private static boolean debug = false;
+
+    /** whether streams should be redirected */
+    private static boolean redirectStreams = false;
+
+    /** mutex to wait on, for initialization */
+    public static Object initMutex = new Object();
+
+    /** set to true if this is a webstart application. */
+    private static boolean isWebstartApplication;
+
+    /** set to false to indicate another JVM should not be spawned, even if necessary */
+    private static boolean forksAllowed = true;
+
+    /** contains the arguments passed to the jnlp runtime */
+    private static List<String> initialArguments;
+
+    /** a lock which is held to indicate that an instance of netx is running */
+    private static FileLock fileLock;
+
+    public static final String STDERR_FILE = "java.stderr";
+    public static final String STDOUT_FILE = "java.stdout";
+
+    /**
+     * Returns whether the JNLP runtime environment has been
+     * initialized.  Once initialized, some properties such as the
+     * base directory cannot be changed.  Before
+     */
+    public static boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * Initialize the JNLP runtime environment by installing the
+     * security manager and security policy, initializing the JNLP
+     * standard services, etc.<p>
+     *
+     * This method should be called from the main AppContext/Thread. <p>
+     *
+     * This method cannot be called more than once.  Once
+     * initialized, methods that alter the runtime can only be
+     * called by the exit class.<p>
+     *
+     * @param isApplication is true if a webstart application is being initialized
+     *
+     * @throws IllegalStateException if the runtime was previously initialized
+     */
+    public static void initialize(boolean isApplication) throws IllegalStateException {
+        checkInitialized();
+
+        try {
+            config.load();
+        } catch (ConfigurationException e) {
+            /* exit if there is a fatal exception loading the configuration */
+            if (isApplication) {
+                System.out.println(getMessage("RConfigurationError"));
+                System.exit(1);
+            }
+        }
+
+        KeyStores.setConfiguration(config);
+
+        initializeStreams();
+
+        isWebstartApplication = isApplication;
+
+        //Setting the system property for javawebstart's version.
+        //The version stored will be the same as java's version.
+        System.setProperty("javawebstart.version", "javaws-" +
+                System.getProperty("java.version"));
+
+        if (headless == false)
+            checkHeadless();
+
+        if (!headless && windowIcon == null)
+            loadWindowIcon();
+
+        if (!headless && indicator == null)
+            indicator = new DefaultDownloadIndicator();
+
+        if (handler == null) {
+            if (headless) {
+                handler = new DefaultLaunchHandler();
+            } else {
+                handler = new GuiLaunchHandler();
+            }
+        }
+
+        ServiceManager.setServiceManagerStub(new XServiceManagerStub()); // ignored if we're running under Web Start
+
+        policy = new JNLPPolicy();
+        security = new JNLPSecurityManager(); // side effect: create JWindow
+
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e) {
+            // ignore it
+        }
+
+        doMainAppContextHacks();
+
+        if (securityEnabled) {
+            Policy.setPolicy(policy); // do first b/c our SM blocks setPolicy
+            System.setSecurityManager(security);
+        }
+
+        securityDialogMessageHandler = startSecurityThreads();
+
+        // wire in custom authenticator for SSL connections
+        try {
+            SSLSocketFactory sslSocketFactory;
+            SSLContext context = SSLContext.getInstance("SSL");
+            TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() };
+            context.init(null, trust, null);
+            sslSocketFactory = context.getSocketFactory();
+
+            HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
+        } catch (Exception e) {
+            System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway...");
+            e.printStackTrace();
+        }
+
+        // plug in a custom authenticator and proxy selector
+        Authenticator.setDefault(new JNLPAuthenticator());
+        ProxySelector.setDefault(new BrowserAwareProxySelector());
+
+        // Restrict access to netx classes
+        Security.setProperty("package.access", 
+                             Security.getProperty("package.access")+",net.sourceforge.jnlp");
+
+        URLJarFile.setCallBack(CachedJarFileCallback.getInstance());
+
+        initialized = true;
+
+    }
+
+    /**
+     * This must NOT be called form the application ThreadGroup. An application
+     * can inject events into its {@link EventQueue} and bypass the security
+     * dialogs.
+     *
+     * @return a {@link SecurityDialogMessageHandler} that can be used to post
+     * security messages
+     */
+    private static SecurityDialogMessageHandler startSecurityThreads() {
+        ThreadGroup securityThreadGroup = new ThreadGroup("NetxSecurityThreadGroup");
+        SecurityDialogMessageHandler runner = new SecurityDialogMessageHandler();
+        Thread securityThread = new Thread(securityThreadGroup, runner, "NetxSecurityThread");
+        securityThread.setDaemon(true);
+        securityThread.start();
+        return runner;
+    }
+
+    /**
+     * Performs a few hacks that are needed for the main AppContext
+     *
+     * @see Launcher#doPerApplicationAppContextHacks
+     */
+    private static void doMainAppContextHacks() {
+
+        /*
+         * With OpenJDK6 (but not with 7) a per-AppContext dtd is maintained.
+         * This dtd is created by the ParserDelgate. However, the code in
+         * HTMLEditorKit (used to render HTML in labels and textpanes) creates
+         * the ParserDelegate only if there are no existing ParserDelegates. The
+         * result is that all other AppContexts see a null dtd.
+         */
+        new ParserDelegator();
+    }
+
+    /**
+     * Initializes the standard output and error streams, redirecting them or
+     * duplicating them as required.
+     */
+    private static void initializeStreams() {
+        Boolean enableLogging = Boolean.valueOf(config
+                .getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING));
+        if (redirectStreams || enableLogging) {
+            String logDir = config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR);
+
+            try {
+                File errFile = new File(logDir, JNLPRuntime.STDERR_FILE);
+                FileUtils.createParentDir(errFile);
+                FileUtils.createRestrictedFile(errFile, true);
+                File outFile = new File(logDir, JNLPRuntime.STDOUT_FILE);
+                FileUtils.createParentDir(outFile);
+                FileUtils.createRestrictedFile(outFile, true);
+
+                if (redirectStreams) {
+                    System.setErr(new PrintStream(new FileOutputStream(errFile)));
+                    System.setOut(new PrintStream(new FileOutputStream(outFile)));
+                } else {
+                    System.setErr(new TeeOutputStream(new FileOutputStream(errFile), System.err));
+                    System.setOut(new TeeOutputStream(new FileOutputStream(outFile), System.out));
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Gets the Configuration associated with this runtime
+     * @return a {@link DeploymentConfiguration} object that can be queried to
+     * find relevant configuration settings
+     */
+    public static DeploymentConfiguration getConfiguration() {
+        return config;
+    }
+
+    /**
+     * Returns true if a webstart application has been initialized, and false
+     * for a plugin applet.
+     */
+    public static boolean isWebstartApplication() {
+        return isWebstartApplication;
+    }
+
+    /**
+     * Returns the window icon.
+     */
+    public static Image getWindowIcon() {
+        return windowIcon;
+    }
+
+    /**
+     * Sets the window icon that is displayed in Java applications
+     * and applets instead of the default Java icon.
+     *
+     * @throws IllegalStateException if caller is not the exit class
+     */
+    public static void setWindowIcon(Image image) {
+        checkExitClass();
+        windowIcon = image;
+    }
+
+    /**
+     * Returns whether the JNLP client will use any AWT/Swing
+     * components.
+     */
+    public static boolean isHeadless() {
+        return headless;
+    }
+
+    /**
+     * Returns whether we are verifying code signing.
+     */
+    public static boolean isVerifying() {
+        return verify;
+    }
+
+    /**
+     * Sets whether the JNLP client will use any AWT/Swing
+     * components.  In headless mode, client features that use the
+     * AWT are disabled such that the client can be used in
+     * headless mode (<code>java.awt.headless=true</code>).
+     *
+     * @throws IllegalStateException if the runtime was previously initialized
+     */
+    public static void setHeadless(boolean enabled) {
+        checkInitialized();
+        headless = enabled;
+    }
+
+    /**
+         * Sets whether we will verify code signing.
+         * @throws IllegalStateException if the runtime was previously initialized
+         */
+    public static void setVerify(boolean enabled) {
+        checkInitialized();
+        verify = enabled;
+    }
+
+    /**
+     * Returns whether the secure runtime environment is enabled.
+     */
+    public static boolean isSecurityEnabled() {
+        return securityEnabled;
+    }
+
+    /**
+     * Sets whether to enable the secure runtime environment.
+     * Disabling security can increase performance for some
+     * applications, and can be used to use netx with other code
+     * that uses its own security manager or policy.
+     *
+     * Disabling security is not recommended and should only be
+     * used if the JNLP files opened are trusted.  This method can
+     * only be called before initalizing the runtime.<p>
+     *
+     * @param enabled whether security should be enabled
+     * @throws IllegalStateException if the runtime is already initialized
+     */
+    public static void setSecurityEnabled(boolean enabled) {
+        checkInitialized();
+        securityEnabled = enabled;
+    }
+
+    /**
+     *
+     * @return the {@link SecurityDialogMessageHandler} that should be used to
+     * post security dialog messages
+     */
+    public static SecurityDialogMessageHandler getSecurityDialogHandler() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new AllPermission());
+        }
+        return securityDialogMessageHandler;
+    }
+
+    /**
+     * Set a class that can exit the JVM; if not set then any class
+     * can exit the JVM.
+     *
+     * @throws IllegalStateException if caller is not the exit class
+     */
+    public static void setExitClass(Class exitClass) {
+        checkExitClass();
+        security.setExitClass(exitClass);
+    }
+
+    /**
+     * Disables applets from calling exit.
+     *
+     * Once disabled, exit cannot be re-enabled for the duration of the JVM instance
+     */
+    public static void disableExit() {
+        security.disableExit();
+    }
+
+    /**
+     * Return the current Application, or null if none can be
+     * determined.
+     */
+    public static ApplicationInstance getApplication() {
+        return security.getApplication();
+    }
+
+    /**
+     * Return whether debug statements for the JNLP client code
+     * should be printed.
+     */
+    public static boolean isDebug() {
+        return debug;
+    }
+
+    /**
+     * Sets whether debug statements for the JNLP client code
+     * should be printed to the standard output.
+     *
+     * @throws IllegalStateException if caller is not the exit class
+     */
+    public static void setDebug(boolean enabled) {
+        checkExitClass();
+        debug = enabled;
+    }
+
+    /**
+     * Sets whether the standard output/error streams should be redirected to
+     * the loggging files.
+     *
+     * @throws IllegalStateException if the runtime has already been initialized
+     */
+    public static void setRedirectStreams(boolean redirect) {
+        checkInitialized();
+        redirectStreams = redirect;
+    }
+
+    /**
+     * Sets the default update policy.
+     *
+     * @throws IllegalStateException if caller is not the exit class
+     */
+    public static void setDefaultUpdatePolicy(UpdatePolicy policy) {
+        checkExitClass();
+        updatePolicy = policy;
+    }
+
+    /**
+     * Returns the default update policy.
+     */
+    public static UpdatePolicy getDefaultUpdatePolicy() {
+        return updatePolicy;
+    }
+
+    /**
+     * Sets the default launch handler.
+     */
+    public static void setDefaultLaunchHandler(LaunchHandler handler) {
+        checkExitClass();
+        JNLPRuntime.handler = handler;
+    }
+
+    /**
+     * Returns the default launch handler.
+     */
+    public static LaunchHandler getDefaultLaunchHandler() {
+        return handler;
+    }
+
+    /**
+     * Sets the default download indicator.
+     *
+     * @throws IllegalStateException if caller is not the exit class
+     */
+    public static void setDefaultDownloadIndicator(DownloadIndicator indicator) {
+        checkExitClass();
+        JNLPRuntime.indicator = indicator;
+    }
+
+    /**
+     * Returns the default download indicator.
+     */
+    public static DownloadIndicator getDefaultDownloadIndicator() {
+        return indicator;
+    }
+
+    /**
+     * Returns the localized resource string identified by the
+     * specified key.  If the message is empty, a null is
+     * returned.
+     */
+    public static String getMessage(String key) {
+        try {
+            String result = resources.getString(key);
+            if (result.length() == 0)
+                return null;
+            else
+                return result;
+        } catch (Exception ex) {
+            if (!key.equals("RNoResource"))
+                return getMessage("RNoResource", new Object[] { key });
+            else
+                return "Missing resource: " + key;
+        }
+    }
+
+    /**
+     * Returns the localized resource string using the specified
+     * arguments.
+     *
+     * @param args the formatting arguments to the resource string
+     */
+    public static String getMessage(String key, Object... args) {
+        return MessageFormat.format(getMessage(key), args);
+    }
+
+    /**
+     * Returns true if the current runtime will fork
+     */
+    public static boolean getForksAllowed() {
+        return forksAllowed;
+    }
+
+    public static void setForksAllowed(boolean value) {
+        checkInitialized();
+        forksAllowed = value;
+    }
+
+    /**
+     * Throws an exception if called when the runtime is
+     * already initialized.
+     */
+    private static void checkInitialized() {
+        if (initialized)
+            throw new IllegalStateException("JNLPRuntime already initialized.");
+    }
+
+    /**
+     * Throws an exception if called with security enabled but
+     * a caller is not the exit class and the runtime has been
+     * initialized.
+     */
+    private static void checkExitClass() {
+        if (securityEnabled && initialized)
+            if (!security.isExitClass())
+                throw new IllegalStateException("Caller is not the exit class");
+    }
+
+    /**
+     * Check whether the VM is in headless mode.
+     */
+    private static void checkHeadless() {
+        //if (GraphicsEnvironment.isHeadless()) // jdk1.4+ only
+        //    headless = true;
+        try {
+            if ("true".equalsIgnoreCase(System.getProperty("java.awt.headless")))
+                headless = true;
+        } catch (SecurityException ex) {
+        }
+    }
+
+    /**
+     * Load the resources.
+     */
+    private static void loadResources() {
+        try {
+            resources = ResourceBundle.getBundle("net.sourceforge.jnlp.resources.Messages");
+        } catch (Exception ex) {
+            throw new IllegalStateException("Missing resource bundle in netx.jar:net/sourceforge/jnlp/resource/Messages.properties");
+        }
+    }
+
+    /**
+     * Load the window icon.
+     */
+    private static void loadWindowIcon() {
+        if (windowIcon != null)
+            return;
+
+        try {
+            windowIcon = new javax.swing.ImageIcon((new sun.misc.Launcher())
+                        .getClassLoader().getResource("net/sourceforge/jnlp/resources/netx-icon.png")).getImage();
+        } catch (Exception ex) {
+            if (JNLPRuntime.isDebug())
+                ex.printStackTrace();
+        }
+    }
+
+    /**
+     * @return true if running on Windows
+     */
+    public static boolean isWindows() {
+        String os = System.getProperty("os.name");
+        return (os != null && os.startsWith("Windows"));
+    }
+
+    /**
+     * @return true if running on a Unix or Unix-like system (including Linux
+     * and *BSD)
+     */
+    public static boolean isUnix() {
+        String sep = System.getProperty("file.separator");
+        return (sep != null && sep.equals("/"));
+    }
+
+    public static void setInitialArgments(List<String> args) {
+        checkInitialized();
+        SecurityManager securityManager = System.getSecurityManager();
+        if (securityManager != null)
+            securityManager.checkPermission(new AllPermission());
+        initialArguments = args;
+    }
+
+    public static List<String> getInitialArguments() {
+        return initialArguments;
+    }
+
+    /**
+     * Indicate that netx is running by creating the {@link JNLPRuntime#INSTANCE_FILE} and
+     * acquiring a shared lock on it
+     */
+    public synchronized static void markNetxRunning() {
+        if (fileLock != null) return;
+        try {
+            String message = "This file is used to check if netx is running";
+
+            File netxRunningFile = new File(JNLPRuntime.getConfiguration()
+                    .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE));
+            if (!netxRunningFile.exists()) {
+                FileUtils.createParentDir(netxRunningFile);
+                FileUtils.createRestrictedFile(netxRunningFile, true);
+                FileOutputStream fos = new FileOutputStream(netxRunningFile);
+                try {
+                    fos.write(message.getBytes());
+                } finally {
+                    fos.close();
+                }
+            }
+
+            FileInputStream is = new FileInputStream(netxRunningFile);
+            FileChannel channel = is.getChannel();
+            fileLock = channel.lock(0, 1, true);
+            if (!fileLock.isShared()){ // We know shared locks aren't offered on this system.
+                FileLock temp = null;
+                for (long pos = 1; temp == null && pos < Long.MAX_VALUE - 1; pos++){
+                    temp = channel.tryLock(pos, 1, false); // No point in requesting for shared lock.
+                }
+                fileLock.release(); // We can release now, since we hold another lock.
+                fileLock = temp; // Keep the new lock so we can release later.
+            }
+            
+            if (fileLock != null && fileLock.isShared()) {
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("Acquired shared lock on " +
+                            netxRunningFile.toString() + " to indicate javaws is running");
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            public void run() {
+                markNetxStopped();
+                CacheUtil.cleanCache();
+            }
+        });
+    }
+
+    /**
+     * Indicate that netx is stopped by releasing the shared lock on
+     * {@link JNLPRuntime#INSTANCE_FILE}.
+     */
+    private static void markNetxStopped() {
+        if (fileLock == null) {
+            return;
+        }
+        try {
+            fileLock.release();
+            fileLock.channel().close();
+            fileLock = null;
+            if (JNLPRuntime.isDebug()) {
+                String file = JNLPRuntime.getConfiguration()
+                        .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE);
+                System.out.println("Release shared lock on " + file);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	(revision 403)
@@ -0,0 +1,538 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.Frame;
+import java.awt.Window;
+import java.lang.ref.WeakReference;
+import java.net.SocketPermission;
+import java.security.AllPermission;
+import java.security.AccessControlException;
+import java.security.Permission;
+import java.security.SecurityPermission;
+
+import javax.swing.JWindow;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.services.ServiceUtil;
+import net.sourceforge.jnlp.util.WeakList;
+import sun.awt.AWTSecurityManager;
+import sun.awt.AppContext;
+import sun.security.util.SecurityConstants;
+
+/**
+ * Security manager for JNLP environment.  This security manager
+ * cannot be replaced as it always denies attempts to replace the
+ * security manager or policy.<p>
+ *
+ * The JNLP security manager tracks windows created by an
+ * application, allowing those windows to be disposed when the
+ * application exits but the JVM does not.  If security is not
+ * enabled then the first application to call System.exit will
+ * halt the JVM.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.17 $
+ */
+class JNLPSecurityManager extends AWTSecurityManager {
+
+    // todo: some apps like JDiskReport can close the VM even when
+    // an exit class is set - fix!
+
+    // todo: create an event dispatch thread for each application,
+    // so that the context classloader doesn't have to be switched
+    // to the foreground application (the currently the approach
+    // since some apps need their classloader as event dispatch
+    // thread's context classloader).
+
+    // todo: use a custom Permission object to identify the current
+    // application in an AccessControlContext by setting a side
+    // effect in its implies method.  Use a custom
+    // AllPermissions-like permission to do this for apps granted
+    // all permissions (but investigate whether this will nuke
+    // the all-permission optimizations in the JRE).
+
+    // todo: does not exit app if close button pressed on JFrame
+    // with CLOSE_ON_EXIT (or whatever) set; if doesn't exit, use an
+    // WindowListener to catch WindowClosing event, then if exit is
+    // called immediately afterwards from AWT thread.
+
+    // todo: deny all permissions to applications that should have
+    // already been 'shut down' by closing their resources and
+    // interrupt the threads if operating in a shared-VM (exit class
+    // set).  Deny will probably will slow checks down a lot though.
+
+    // todo: weak remember last getProperty application and
+    // re-install properties if another application calls, or find
+    // another way for different apps to have different properties
+    // in java.lang.Sytem with the same names.
+
+    /** only class that can exit the JVM, if set */
+    private Object exitClass = null;
+
+    /** this exception prevents exiting the JVM */
+    private SecurityException closeAppEx = // making here prevents huge stack traces
+    new SecurityException(R("RShutdown"));
+
+    /** weak list of windows created */
+    private WeakList<Window> weakWindows = new WeakList<Window>();
+
+    /** weak list of applications corresponding to window list */
+    private WeakList<ApplicationInstance> weakApplications =
+            new WeakList<ApplicationInstance>();
+
+    /** Sets whether or not exit is allowed (in the context of the plugin, this is always false) */
+    private boolean exitAllowed = true;
+
+    /**
+     * The AppContext of the main application (netx). We need to store this here
+     * so we can return this when no code from an external application is
+     * running on the thread
+     */
+    private AppContext mainAppContext;
+
+    /**
+     * Creates a JNLP SecurityManager.
+     */
+    JNLPSecurityManager() {
+        // this has the side-effect of creating the Swing shared Frame
+        // owner.  Since no application is running at this time, it is
+        // not added to any window list when checkTopLevelWindow is
+        // called for it (and not disposed).
+
+        if (!JNLPRuntime.isHeadless())
+            new JWindow().getOwner();
+
+        mainAppContext = AppContext.getAppContext();
+    }
+
+    /**
+     * Returns whether the exit class is present on the stack, or
+     * true if no exit class is set.
+     */
+    public boolean isExitClass() {
+        return isExitClass(getClassContext());
+    }
+
+    /**
+     * Returns whether the exit class is present on the stack, or
+     * true if no exit class is set.
+     */
+    private boolean isExitClass(Class stack[]) {
+        if (exitClass == null)
+            return true;
+
+        for (int i = 0; i < stack.length; i++)
+            if (stack[i] == exitClass)
+                return true;
+
+        return false;
+    }
+
+    /**
+     * Set the exit class, which is the only class that can exit the
+     * JVM; if not set then any class can exit the JVM.
+     *
+     * @param exitClass the exit class
+     * @throws IllegalStateException if the exit class is already set
+     */
+    public void setExitClass(Class exitClass) throws IllegalStateException {
+        if (this.exitClass != null)
+            throw new IllegalStateException(R("RExitTaken"));
+
+        this.exitClass = exitClass;
+    }
+
+    /**
+     * Return the current Application, or null if none can be
+     * determined.
+     */
+    protected ApplicationInstance getApplication() {
+        return getApplication(Thread.currentThread(), getClassContext(), 0);
+    }
+
+    /**
+     * Return the application the opened the specified window (only
+     * call from event dispatch thread).
+     */
+    protected ApplicationInstance getApplication(Window window) {
+        for (int i = weakWindows.size(); i-- > 0;) {
+            Window w = weakWindows.get(i);
+            if (w == null) {
+                weakWindows.remove(i);
+                weakApplications.remove(i);
+            }
+
+            if (w == window)
+                return weakApplications.get(i);
+        }
+
+        return null;
+    }
+
+    /**
+     * Return the current Application, or null.
+     */
+    protected ApplicationInstance getApplication(Thread thread, Class<?> stack[], int maxDepth) {
+        ClassLoader cl;
+        JNLPClassLoader jnlpCl;
+
+        cl = thread.getContextClassLoader();
+        while (cl != null) {
+            jnlpCl = getJnlpClassLoader(cl);
+            if (jnlpCl != null && jnlpCl.getApplication() != null) {
+                return jnlpCl.getApplication();
+            }
+            cl = cl.getParent();
+        }
+
+        if (maxDepth <= 0)
+            maxDepth = stack.length;
+
+        // this needs to be tightened up
+        for (int i = 0; i < stack.length && i < maxDepth; i++) {
+            cl = stack[i].getClassLoader();
+            while (cl != null) {
+                jnlpCl = getJnlpClassLoader(cl);
+                if (jnlpCl != null && jnlpCl.getApplication() != null) {
+                    return jnlpCl.getApplication();
+                }
+                cl = cl.getParent();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the JNLPClassLoader associated with the given ClassLoader, or
+     * null.
+     * @param cl a ClassLoader
+     * @return JNLPClassLoader or null
+     */
+    private JNLPClassLoader getJnlpClassLoader(ClassLoader cl) {
+        // Since we want to deal with JNLPClassLoader, extract it if this
+        // is a codebase loader
+        if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+            cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+        if (cl instanceof JNLPClassLoader) {
+            JNLPClassLoader loader = (JNLPClassLoader) cl;
+            return loader;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the application's thread group if the application can
+     * be determined; otherwise returns super.getThreadGroup()
+     */
+    public ThreadGroup getThreadGroup() {
+        ApplicationInstance app = getApplication();
+        if (app == null)
+            return super.getThreadGroup();
+
+        return app.getThreadGroup();
+    }
+
+    /**
+     * Throws a SecurityException if the permission is denied,
+     * otherwise return normally.  This method always denies
+     * permission to change the security manager or policy.
+     */
+    public void checkPermission(Permission perm) {
+        String name = perm.getName();
+
+        // Enable this manually -- it'll produce too much output for -verbose
+        // otherwise.
+        //      if (true)
+        //        System.out.println("Checking permission: " + perm.toString());
+
+        if (!JNLPRuntime.isWebstartApplication() &&
+                ("setPolicy".equals(name) || "setSecurityManager".equals(name)))
+            throw new SecurityException(R("RCantReplaceSM"));
+
+        try {
+            // deny all permissions to stopped applications
+            // The call to getApplication() below might not work if an
+            // application hasn't been fully initialized yet.
+            //            if (JNLPRuntime.isDebug()) {
+            //                if (!"getClassLoader".equals(name)) {
+            //                    ApplicationInstance app = getApplication();
+            //                    if (app != null && !app.isRunning())
+            //                        throw new SecurityException(R("RDenyStopped"));
+            //                }
+            //            }
+
+            try {
+                super.checkPermission(perm);
+            } catch (SecurityException se) {
+
+                //This section is a special case for dealing with SocketPermissions.
+                if (JNLPRuntime.isDebug())
+                    System.err.println("Requesting permission: " + perm.toString());
+
+                //Change this SocketPermission's action to connect and accept
+                //(and resolve). This is to avoid asking for connect permission
+                //on every address resolve.
+                Permission tmpPerm = null;
+                if (perm instanceof SocketPermission) {
+                    tmpPerm = new SocketPermission(perm.getName(),
+                                                        SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
+
+                    // before proceeding, check if we are trying to connect to same origin
+                    ApplicationInstance app = getApplication();
+                    JNLPFile file = app.getJNLPFile();
+
+                    String srcHost = file.getSourceLocation().getAuthority();
+                    String destHost = name;
+
+                    // host = abc.xyz.com or abc.xyz.com:<port>
+                    if (destHost.indexOf(':') >= 0)
+                        destHost = destHost.substring(0, destHost.indexOf(':'));
+
+                    // host = abc.xyz.com
+                    String[] hostComponents = destHost.split("\\.");
+
+                    int length = hostComponents.length;
+                    if (length >= 2) {
+
+                        // address is in xxx.xxx.xxx format
+                        destHost = hostComponents[length - 2] + "." + hostComponents[length - 1];
+
+                        // host = xyz.com i.e. origin
+                        boolean isDestHostName = false;
+
+                        // make sure that it is not an ip address
+                        try {
+                            Integer.parseInt(hostComponents[length - 1]);
+                        } catch (NumberFormatException e) {
+                            isDestHostName = true;
+                        }
+
+                        if (isDestHostName) {
+                            // okay, destination is hostname. Now figure out if it is a subset of origin
+                            if (srcHost.endsWith(destHost)) {
+                                addPermission(tmpPerm);
+                                return;
+                            }
+                        }
+                    }
+                } else {
+                    tmpPerm = perm;
+                }
+
+                if (tmpPerm != null) {
+                    //askPermission will only prompt the user on SocketPermission
+                    //meaning we're denying all other SecurityExceptions that may arise.
+                    if (askPermission(tmpPerm)) {
+                        addPermission(tmpPerm);
+                        //return quietly.
+                    } else {
+                        throw se;
+                    }
+                }
+            }
+        } catch (SecurityException ex) {
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Denying permission: " + perm);
+            }
+            throw ex;
+        }
+    }
+
+    /**
+     * Asks the user whether or not to grant permission.
+     * @param perm the permission to be granted
+     * @return true if the permission was granted, false otherwise.
+     */
+    private boolean askPermission(Permission perm) {
+
+        ApplicationInstance app = getApplication();
+        if (app != null && !app.isSigned()) {
+            if (perm instanceof SocketPermission
+                                && ServiceUtil.checkAccess(AccessType.NETWORK, perm.getName())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Adds a permission to the JNLPClassLoader.
+     * @param perm the permission to add to the JNLPClassLoader
+     */
+    private void addPermission(Permission perm) {
+        if (JNLPRuntime.getApplication().getClassLoader() instanceof JNLPClassLoader) {
+
+            JNLPClassLoader cl = (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader();
+            cl.addPermission(perm);
+            if (JNLPRuntime.isDebug()) {
+                if (cl.getPermissions(null).implies(perm))
+                    System.err.println("Added permission: " + perm.toString());
+                else
+                    System.err.println("Unable to add permission: " + perm.toString());
+            }
+        } else {
+            if (JNLPRuntime.isDebug())
+                System.err.println("Unable to add permission: " + perm + ", classloader not JNLP.");
+        }
+    }
+
+    /**
+     * Checks whether the window can be displayed without an applet
+     * warning banner, and adds the window to the list of windows to
+     * be disposed when the calling application exits.
+     */
+    public boolean checkTopLevelWindow(Object window) {
+        ApplicationInstance app = getApplication();
+
+        // remember window -> application mapping for focus, close on exit
+        if (app != null && window instanceof Window) {
+            Window w = (Window) window;
+
+            if (JNLPRuntime.isDebug())
+                System.err.println("SM: app: " + app.getTitle() + " is adding a window: " + window + " with appContext " + AppContext.getAppContext());
+
+            weakWindows.add(w); // for mapping window -> app
+            weakApplications.add(app);
+
+            app.addWindow(w);
+        }
+
+        // change coffee cup to netx for default icon
+        if (window instanceof Window)
+            for (Window w = (Window) window; w != null; w = w.getOwner())
+                if (window instanceof Frame)
+                    ((Frame) window).setIconImage(JNLPRuntime.getWindowIcon());
+
+        // todo: set awt.appletWarning to custom message
+        // todo: logo on with glass pane on JFrame/JWindow?
+
+        return super.checkTopLevelWindow(window);
+    }
+
+    /**
+     * Checks whether the caller can exit the system.  This method
+     * identifies whether the caller is a real call to Runtime.exec
+     * and has special behavior when returning from this method
+     * would exit the JVM and an exit class is set: if the caller is
+     * not the exit class then the calling application will be
+     * stopped and its resources destroyed (when possible), and an
+     * exception will be thrown to prevent the JVM from shutting
+     * down.<p>
+     *
+     * Calls not from Runtime.exit or with no exit class set will
+     * behave normally, and the exit class can always exit the JVM.
+     */
+    public void checkExit(int status) {
+
+        // applets are not allowed to exit, but the plugin main class (primordial loader) is
+        Class stack[] = getClassContext();
+        if (!exitAllowed) {
+            for (int i = 0; i < stack.length; i++)
+                if (stack[i].getClassLoader() != null)
+                    throw new AccessControlException("Applets may not call System.exit()");
+        }
+
+        super.checkExit(status);
+
+        boolean realCall = (stack[1] == Runtime.class);
+
+        if (isExitClass(stack)) // either exitClass called or no exitClass set
+            return; // to Runtime.exit or fake call to see if app has permission
+
+        // not called from Runtime.exit()
+        if (!realCall) {
+            // apps that can't exit should think they can exit normally
+            super.checkExit(status);
+            return;
+        }
+
+        // but when they really call, stop only the app instead of the JVM
+        ApplicationInstance app = getApplication(Thread.currentThread(), stack, 0);
+        if (app == null) {
+            throw new SecurityException(R("RExitNoApp"));
+        }
+
+        app.destroy();
+
+        throw closeAppEx;
+    }
+
+    protected void disableExit() {
+        exitAllowed = false;
+    }
+
+    /**
+     * This returns the appropriate {@link AppContext}. Hooks in AppContext
+     * check if the current {@link SecurityManager} is an instance of
+     * AWTSecurityManager and if so, call this method to give it a chance to
+     * return the appropriate appContext based on the application that is
+     * running.<p>
+     *
+     * This can be called from any thread (possibly a swing thread) to find out
+     * the AppContext for the thread (which may correspond to a particular
+     * applet).
+     */
+    @Override
+    public AppContext getAppContext() {
+        ApplicationInstance app = getApplication();
+        if (app == null) {
+            /*
+             * if we cannot find an application based on the code on the stack,
+             * then assume it is the main application
+             */
+            return mainAppContext;
+        } else {
+            return app.getAppContext();
+        }
+
+    }
+
+    /**
+     * Tests if a client can get access to the AWT event queue. This version allows
+     * complete access to the EventQueue for its own AppContext-specific EventQueue.
+     *
+     * FIXME there are probably huge security implications for this. Eg:
+     * http://hg.openjdk.java.net/jdk7/awt/jdk/rev/8022709a306d
+     *
+     * @exception  SecurityException  if the caller does not have
+     *             permission to accesss the AWT event queue.
+     */
+    public void checkAwtEventQueueAccess() {
+        /*
+         * this is the templace of the code that should allow applets access to
+         * eventqueues
+         */
+
+        // AppContext appContext = AppContext.getAppContext();
+        // ApplicationInstance instance = getApplication();
+
+        // if ((appContext == mainAppContext) && (instance != null)) {
+        // If we're about to allow access to the main EventQueue,
+        // and anything untrusted is on the class context stack,
+        // disallow access.
+        super.checkAwtEventQueueAccess();
+        // }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluator.java	(revision 403)
@@ -0,0 +1,56 @@
+/* PacEvaluator.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.net.URL;
+
+/**
+ * This interface represents an object which can evaluate Proxy Auto Config
+ * files.
+ */
+public interface PacEvaluator {
+    /**
+     * Get the proxies for accessing a given URL. The result is obtained by
+     * evaluating the PAC file with the given url (and the host) as input.
+     *
+     * @param url the url for which a proxy is desired
+     * @return a list of proxies in a string like
+     * <pre>"PROXY foo.example.com:8080; PROXY bar.example.com:8080; DIRECT"</pre>
+     */
+    public String getProxies(URL url);
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java	(revision 403)
@@ -0,0 +1,107 @@
+/* PacEvaluatorFactory.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Properties;
+
+
+public class PacEvaluatorFactory {
+
+    public static PacEvaluator getPacEvaluator(URL pacUrl) {
+        boolean useRhino = false;
+
+        ClassLoader cl = PacEvaluatorFactory.class.getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+        InputStream in = cl.getResourceAsStream("net/sourceforge/jnlp/build.properties");
+        Properties properties = null;
+        try {
+            properties = new Properties();
+            properties.load(in);
+        } catch (IOException e) {
+            if (JNLPRuntime.isDebug()) {
+                e.printStackTrace();
+            }
+        } finally {
+            try {
+                in.close();
+            } catch (IOException e) {
+                if (JNLPRuntime.isDebug()) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        if (properties == null) {
+            return new FakePacEvaluator();
+        }
+
+        String available = properties.getProperty("rhino.available");
+        useRhino = Boolean.valueOf(available);
+
+        if (useRhino) {
+            try {
+                Class<?> evaluator = Class.forName("net.sourceforge.jnlp.runtime.RhinoBasedPacEvaluator");
+                Constructor<?> constructor = evaluator.getConstructor(URL.class);
+                return (PacEvaluator) constructor.newInstance(pacUrl);
+            } catch (ClassNotFoundException e) {
+                // ignore
+            } catch (InstantiationException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            } catch (NoSuchMethodException e) {
+                e.printStackTrace();
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                if (e.getCause() != null) {
+                    e.getCause().printStackTrace();
+                }
+            }
+        }
+
+        return new FakePacEvaluator();
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java	(revision 403)
@@ -0,0 +1,263 @@
+/* RhinoBasedPacEvaluator.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.runtime;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+import net.sourceforge.jnlp.util.TimedHashMap;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * Represents a Proxy Auto Config file. This object can be used to evaluate the
+ * proxy file to find the proxy for a given url.
+ *
+ * @see http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file
+ */
+public class RhinoBasedPacEvaluator implements PacEvaluator {
+
+    private final String pacHelperFunctionContents;
+    private final String pacContents;
+    private final URL pacUrl;
+    private final TimedHashMap<String, String> cache;
+
+    /**
+     * Initialize a new object by using the PAC file located at the given URL.
+     *
+     * @param pacUrl the url of the PAC file to use
+     */
+    public RhinoBasedPacEvaluator(URL pacUrl) {
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("Using the Rhino based PAC evaluator for url " + pacUrl);
+        }
+        pacHelperFunctionContents = getHelperFunctionContents();
+        this.pacUrl = pacUrl;
+        pacContents = getPacContents(pacUrl);
+        cache = new TimedHashMap<String, String>();
+    }
+
+    /**
+     * Get the proxies for accessing a given URL. The result is obtained by
+     * evaluating the PAC file with the given url (and the host) as input.
+     *
+     * This method performs caching of the result.
+     *
+     * @param url the url for which a proxy is desired
+     * @return a list of proxies in a string like
+     * <pre>"PROXY foo.example.com:8080; PROXY bar.example.com:8080; DIRECT"</pre>
+     *
+     * @see #getProxiesWithoutCaching(URL)
+     */
+    public String getProxies(URL url) {
+        String cachedResult = getFromCache(url);
+        if (cachedResult != null) {
+            return cachedResult;
+        }
+
+        String result = getProxiesWithoutCaching(url);
+        addToCache(url, result);
+        return result;
+    }
+
+    /**
+     * Get the proxies for accessing a given URL. The result is obtained by
+     * evaluating the PAC file with the given url (and the host) as input.
+     *
+     * @param url the url for which a proxy is desired
+     * @return a list of proxies in a string like
+     * <pre>"PROXY example.com:3128; DIRECT"</pre>
+     *
+     * @see #getProxies(URL)
+     */
+    private String getProxiesWithoutCaching(URL url) {
+        if (pacHelperFunctionContents == null) {
+            System.err.println("Error loading pac functions");
+            return "DIRECT";
+        }
+
+        EvaluatePacAction evaluatePacAction = new EvaluatePacAction(pacContents, pacUrl.toString(),
+                pacHelperFunctionContents, url);
+        Permissions p = new Permissions();
+        p.add(new RuntimePermission("accessClassInPackage.org.mozilla.javascript"));
+        p.add(new SocketPermission("*", "resolve"));
+        ProtectionDomain pd = new ProtectionDomain(null, p);
+        AccessControlContext context = new AccessControlContext(new ProtectionDomain[] { pd });
+
+        return AccessController.doPrivileged(evaluatePacAction, context);
+    }
+
+    /**
+     * Returns the contents of file at pacUrl as a String.
+     */
+    private String getPacContents(URL pacUrl) {
+        StringBuilder contents = null;
+        try {
+            String line = null;
+            contents = new StringBuilder();
+            BufferedReader pacReader = new BufferedReader(new InputStreamReader(pacUrl.openStream()));
+            try {
+                while ((line = pacReader.readLine()) != null) {
+                    // System.out.println(line);
+                    contents = contents.append(line).append("\n");
+                }
+            } finally {
+                pacReader.close();
+            }
+        } catch (IOException e) {
+            contents = null;
+        }
+
+        return (contents != null) ? contents.toString() : null;
+    }
+
+    /**
+     * Returns the pac helper functions as a String. The functions are read
+     * from net/sourceforge/jnlp/resources/pac-funcs.js
+     */
+    private String getHelperFunctionContents() {
+        StringBuilder contents = null;
+        try {
+            String line;
+            ClassLoader cl = this.getClass().getClassLoader();
+            if (cl == null) {
+                cl = ClassLoader.getSystemClassLoader();
+            }
+            InputStream in = cl.getResourceAsStream("net/sourceforge/jnlp/runtime/pac-funcs.js");
+            BufferedReader pacFuncsReader = new BufferedReader(new InputStreamReader(in));
+            try {
+                contents = new StringBuilder();
+                while ((line = pacFuncsReader.readLine()) != null) {
+                    // System.out.println(line);
+                    contents = contents.append(line).append("\n");
+                }
+            } finally {
+                pacFuncsReader.close();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            contents = null;
+        }
+
+        return (contents != null) ? contents.toString() : null;
+    }
+
+    /**
+     * Gets an entry from the cache
+     */
+    private String getFromCache(URL url) {
+        String lookupString = url.getProtocol() + "://" + url.getHost();
+        String result = cache.get(lookupString);
+        return result;
+    }
+
+    /**
+     * Adds an entry to the cache
+     */
+    private void addToCache(URL url, String proxyResult) {
+        String lookupString = url.getAuthority() + "://" + url.getHost();
+        cache.put(lookupString, proxyResult);
+    }
+
+    /**
+     * Helper classs to run remote javascript code (specified by the user as
+     * PAC URL) inside a sandbox.
+     */
+    private static class EvaluatePacAction implements PrivilegedAction<String> {
+
+        private String pacContents;
+        private String pacUrl;
+        private String pacFuncsContents;
+        private URL url;
+
+        public EvaluatePacAction(String pacContents, String pacUrl, String pacFuncsContents, URL url) {
+            this.pacContents = pacContents;
+            this.pacUrl = pacUrl;
+            this.pacFuncsContents = pacFuncsContents;
+            this.url = url;
+        }
+
+        public String run() {
+            Context cx = Context.enter();
+            try {
+                /*
+                 * TODO defense in depth.
+                 *
+                 * This is already running within a sandbox, but we can (and we
+                 * should) lock it down further. Look into ClassShutter.
+                 */
+                Scriptable scope = cx.initStandardObjects();
+                // any optimization level greater than -1 will trigger code generation
+                // and this block will then need classloader permissions
+                cx.setOptimizationLevel(-1);
+                Object result = null;
+                result = cx.evaluateString(scope, pacFuncsContents, "internal", 1, null);
+                result = cx.evaluateString(scope, pacContents, pacUrl, 1, null);
+
+                Object functionObj = scope.get("FindProxyForURL", scope);
+                if (!(functionObj instanceof Function)) {
+                    System.err.println("FindProxyForURL not found");
+                    return null;
+                } else {
+                    Function findProxyFunction = (Function) functionObj;
+
+                    Object[] args = { url.toString(), url.getHost() };
+                    result = findProxyFunction.call(cx, scope, scope, args);
+                    return (String) result;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                return "DIRECT";
+            } finally {
+                Context.exit();
+            }
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Translator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Translator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/Translator.java	(revision 403)
@@ -0,0 +1,40 @@
+// Copyright (C) 2010 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.runtime;
+
+/**
+ * Utility class to provide simple methods to help localize messages
+ */
+public class Translator {
+
+    /**
+     * @return the localized string for the message
+     */
+    public static String R(String message, Object... params) {
+        return JNLPRuntime.getMessage(message, params);
+    }
+
+    /**
+     * Return a translated (localized) version of the message
+     * @param message the message to translate
+     * @return a string representing the localized message
+     */
+    public static String R(String message) {
+        return JNLPRuntime.getMessage(message);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/pac-funcs.js
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/pac-funcs.js	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/pac-funcs.js	(revision 403)
@@ -0,0 +1,830 @@
+/* pac-funcs.js
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+/*
+ * These helper functions are required to be able to parse Proxy Auto Config
+ * (PAC) files. PAC files will use these helper functions to decide the best
+ * proxy for connecting to a host.
+ *
+ * This implementation is based on the description of the functions at:
+ * http://web.archive.org/web/20060424005037/wp.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html
+ */
+
+/**
+ * Returns true if the host does not contain a domain (there are no dots)
+ */
+function isPlainHostName(host) {
+    if (host.indexOf(".") === -1) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/**
+ * Returns true if the host is part of the domain (the host ends with domain)
+ */
+function dnsDomainIs(host, domain) {
+    var loc = host.lastIndexOf(domain);
+    if (loc === -1) {
+        return false;
+    }
+    if (loc + domain.length === host.length) {
+        // host ends with domain
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Returns true if the host is an exact match of hostdom or if host is not a
+ * fully qualified name but has the same hostname as hostdom
+ */
+function localHostOrDomainIs(host, hostdom) {
+    if (host === hostdom) {
+        // exact match
+        return true;
+    }
+    var firstdot = hostdom.indexOf(".");
+    if (firstdot === -1) {
+        // hostdom has no dots
+        return false;
+    }
+    if (host === hostdom.substring(0, firstdot)) {
+        // hostname matches
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Returns true if the host name can be resolved.
+ */
+function isResolvable(host) {
+    try {
+        java.net.InetAddress.getByName(host);
+        return true;
+    } catch (e) {
+        //if (e.javaException instanceof java.net.UnknownHostException) {
+        	return false;
+        //} else {
+        // 	throw e;
+        //}
+    }
+}
+
+/**
+ * Return true if the ip address of the host matches the pattern given the mask.
+ */
+function isInNet(host, pattern, mask) {
+    if (!isResolvable(host)) {
+        return false;
+    }
+
+    var hostIp = dnsResolve(host);
+    var hostParts = hostIp.split(".");
+    var patternParts = pattern.split(".");
+    var maskParts = mask.split(".");
+
+    if (hostParts.length !== 4 ||
+        patternParts.length !== hostParts.length ||
+        maskParts.length !== hostParts.length) {
+        return false;
+    }
+
+    var matched = true;
+    for (var i = 0; i < hostParts.length; i++) {
+        var partMatches = (hostParts[i] & maskParts[i]) === (patternParts[i] & maskParts[i]);
+        matched = matched && partMatches;
+    }
+
+    return matched;
+}
+
+/**
+ * Returns the IP address of the host as a string
+ */
+function dnsResolve(host) {
+    return java.net.InetAddress.getByName(host).getHostAddress() + "";
+}
+
+/**
+ * Returns the local IP address
+ */
+function myIpAddress() {
+    return java.net.InetAddress.getLocalHost().getHostAddress() + "";
+}
+
+/**
+ * Returns the number of domains in a hostname
+ */
+function dnsDomainLevels(host) {
+    var levels = 0;
+    for (var i = 0; i < host.length; i++) {
+        if (host[i] === '.') {
+            levels++;
+        }
+    }
+    return levels;
+}
+
+/**
+ * Returns true if the shell expression matches the given input string
+ */
+function shExpMatch(str, shExp) {
+
+    // TODO support all special characters
+    // right now we support only * and ?
+
+
+    try {
+
+        // turn shExp into a regular expression
+
+        var work = "";
+
+        // escape characters
+        for (var i = 0; i < shExp.length; i++) {
+            var ch = shExp[i];
+            switch (ch) {
+                case "\\": work = work + "\\\\"; break;
+                case "^": work = work + "\\^"; break;
+                case "$": work = work + "\\$"; break;
+                case "+": work = work + "\\+"; break;
+                case ".": work = work + "\\."; break;
+                case "(": work = work + "\\("; break;
+                case ")": work = work + "\\)"; break;
+                case "{": work = work + "\\{"; break;
+                case "}": work = work + "\\}"; break;
+                case "[": work = work + "\\["; break;
+                case "]": work = work + "\\]"; break;
+
+                case "?": work = work + ".{1}"; break;
+                case "*": work = work + ".*"; break;
+
+                default:
+                    work = work + ch;
+            }
+
+        }
+
+        var regExp = "^" +  work + "$";
+
+        // match
+        //java.lang.System.out.println("")
+        //java.lang.System.out.println("Input String  : " + str);
+        //java.lang.System.out.println("Input Pattern : " + shExp);
+        //java.lang.System.out.println("RegExp        : " + regExp.toString());
+        var match = str.match(regExp);
+
+        if (match === null) {
+            return false;
+        } else {
+            return true;
+        }
+
+
+    } catch (e) {
+        return false;
+    }
+
+}
+
+
+/**
+ * Returns true if the current weekday matches the desired weekday(s)
+ *
+ * Possible ways of calling:
+ *   weekdayRange(wd1);
+ *   weekdayRange(wd1, "GMT");
+ *   weekdayRange(wd1, wd2);
+ *   weekdayRange(wd1, wd2, "GMT");
+ *
+ * Where wd1 and wd2 are one of "SUN", "MON", "TUE", "WED", "THU", "FRI" and
+ * "SAT"
+ *
+ * The argument "GMT", if present, is always the last argument
+ */
+function weekdayRange() {
+	var wd1;
+	var wd2;
+	var gmt = false;
+
+	function isWeekDay(day) {
+		if (day === "SUN" || day === "MON" || day === "TUE" || day === "WED" ||
+            day === "THU" || day === "FRI" || day === "SAT") {
+			return true;
+		}
+		return false;
+	}
+
+    function strToWeekDay(str) {
+        switch (str) {
+            case "SUN": return 0;
+            case "MON": return 1;
+            case "TUE": return 2;
+            case "WED": return 3;
+            case "THU": return 4;
+            case "FRI": return 5;
+            case "SAT": return 6;
+            default: return 0;
+        }
+    }
+
+	if (arguments.length > 1) {
+		if (arguments[arguments.length-1] === "GMT") {
+			gmt = true;
+            arguments.splice(0,arguments.length-1);
+        }
+	}
+
+    if (arguments.length === 0) { return false; }
+
+    wd1 = arguments[0];
+
+	if (!isWeekDay(wd1)) { return false; }
+
+    var today = new Date().getDay();
+    if (arguments.length >= 2) {
+        // return true if current weekday is between wd1 and wd2 (inclusive)
+        wd2 = arguments[1];
+        if (!isWeekDay(wd2)) { return false; }
+
+        var day1 = strToWeekDay(wd1);
+        var day2 = strToWeekDay(wd2);
+
+        if (day1 <= day2) {
+            if ( day1 <= today && today <= day2) {
+                return true;
+            }
+            return false;
+        } else {
+            if (day1 <= today || today <= day2) {
+                return true;
+            }
+            return false;
+        }
+    } else {
+        // return true if the current weekday is wd1
+        if (strToWeekDay(wd1) === today) {
+            return true;
+        }
+        return false;
+    }
+}
+
+/**
+ * Returns true if the current date matches the given date(s)
+ *
+ * Possible ways of calling:
+ *   dateRange(day)
+ *   dateRange(day1, day2)
+ *   dateRange(month)
+ *   dateRange(month1, month2)
+ *   dateRange(year)
+ *   dateRange(year1, year2)
+ *   dateRange(day1, month1, day2, month2)
+ *   dateRange(month1, year1, month2, year2)
+ *   dateRange(day1, month1, year1, day2, month2, year2)
+ *
+ * The parameter "GMT" may additionally be passed as the last argument in any
+ * of the above ways of calling.
+ */
+function dateRange() {
+
+    // note: watch out for wrapping around of dates. date ranges, like
+    // month=9 to month=8, wrap around and cover the entire year. this
+    // makes everything more interesting
+
+    var gmt;
+	if (arguments.length > 1) {
+		if (arguments[arguments.length-1] === "GMT") {
+			gmt = true;
+            arguments.splice(0,arguments.length-1);
+        }
+	}
+
+    function isDate(date) {
+        if (typeof(date) === 'number' && (date <= 31 && date >= 1)) {
+            return true;
+        }
+        return false;
+    }
+
+    function strToMonth(month) {
+        switch (month) {
+            case "JAN": return 0;
+            case "FEB": return 1;
+            case "MAR": return 2;
+            case "APR": return 3;
+            case "MAY": return 4;
+            case "JUN": return 5;
+            case "JUL": return 6;
+            case "AUG": return 7;
+            case "SEP": return 8;
+            case "OCT": return 9;
+            case "NOV": return 10;
+            case "DEC": return 11;
+            default: return 0;
+        }
+    }
+
+    function isMonth(month) {
+        if (month === "JAN" || month === "FEB" || month === "MAR" ||
+                month === "APR" || month === "MAY" || month === "JUN" ||
+                month === "JUL" || month === "AUG" || month === "SEP" ||
+                month === "OCT" || month === "NOV" || month === "DEC") {
+            return true;
+        }
+        return false;
+    }
+
+    function isYear(year) {
+        if (typeof(year) === 'number') {
+            return true;
+        }
+        return false;
+    }
+
+    function inDateRange(today, date1, date2) {
+        if (date1 <= date2) {
+            if (date1 <= today.getDate() && today.getDate() <= date2) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            if (date1 <= today.getDate() || today.getDate() <= date2) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    function inMonthRange(today, month1, month2) {
+        if (month1 <= month2) {
+            if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            if (month1 <= today.getMonth() || today.getMonth() <= month2) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    function inYearRange(today, year1, year2) {
+        if (year1 <= today.getYear() && today.getYear() <= year2) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    function inMonthDateRange(today, date1, month1, date2, month2) {
+        if (month1 === month2) {
+            if (today.getMonth() === month1) {
+                if (date1 <= today.getDate() && today.getDate() <= date2) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                if (date1 <= date2) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+        } else if (month1 < month2) {
+            if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+                if (today.getMonth() === month1) {
+                    if (today.getDate() >= date1) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else if (today.getMonth() === month2) {
+                    if (today.getDate() <= date2) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        } else {
+            if (month1 <= today.getMonth() || today.getMonth() <= month2) {
+                if (today.getMonth() === month1) {
+                    if (today.getDate() >= date1) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else if (today.getMonth() === month2) {
+                    if (today.getDate() <= date2) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        }
+    }
+
+    function inYearMonthRange(today, month1, year1, month2, year2) {
+        if (year1 === year2) {
+            if (today.getYear() === year1) {
+               if (month1 <= today.getMonth() && today.getMonth() <= month2) {
+                   return true;
+               } else {
+                   return false;
+               }
+            } else {
+                return false;
+            }
+        }
+        if (year1 < year2) {
+            if (year1 <= today.getYear() && today.getYear() <= year2) {
+                if (today.getYear() === year1) {
+                    if (today.getMonth() >= month1) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else if (today.getYear() === year2) {
+                    if (today.getMonth() <= month2) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+
+    }
+
+    function inYearMonthDateRange(today, date1, month1, year1, date2, month2, year2) {
+        if (year1 === year2) {
+            if (year1 === today.getYear()) {
+                if ((month1 <= today.getMonth()) && (today.getMonth() <= month2)) {
+                    if (month1 === month2) {
+                        if (date1 <= today.getDate() && today.getDate() <= date2) {
+                            return true;
+                        } else  {
+                            return false;
+                        }
+                    } else if (today.getMonth() === month1) {
+                        if (today.getDate() >= date1) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    } else if (today.getMonth() === month2) {
+                        if (today.getDate() <= date2) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    } else  {
+                        return true;
+                    }
+                } else {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        } else if (year1 < year2) {
+            if (year1 <= today.getYear() && today.getYear() <= year2) {
+                if (today.getYear() === year1) {
+                    if (today.getMonth() === month1) {
+                        if (today.getDate() >= date1) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    } else if (today.getMonth() > month1) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else if (today.getYear() === year2) {
+                    if (today.getMonth() <= month2) {
+
+                    } else {
+                        return true;
+                    }
+                } else {
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    // TODO: change date to gmt, whatever
+    var today = new Date();
+
+    var arg1;
+    var arg2;
+    var arg3;
+    var arg4;
+    var arg5;
+    var arg6;
+
+    switch (arguments.length) {
+        case 1:
+            var arg = arguments[0];
+            if (isDate(arg)) {
+                if (today.getDate() === arg) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else if (isMonth(arg)) {
+                if (strToMonth(arg) === today.getMonth()) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } else { // year
+                if (today.getYear() === arg) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        case 2:
+            arg1 = arguments[0];
+            arg2 = arguments[1];
+            if (isDate(arg1) && isDate(arg2)) {
+                var date1 = arg1;
+                var date2 = arg2;
+
+                return inDateRange(today, date1, date2);
+
+            } else if (isMonth(arg1) && isMonth(arg2)) {
+                var month1 = strToMonth(arg1);
+                var month2 = strToMonth(arg2);
+
+                return inMonthRange(today, month1, month2);
+
+            } else if (isYear(arg1) && isYear(arg2)) {
+                var year1 = arg1;
+                var year2 = arg2;
+
+                return inYearRange(today, year1, year2);
+            } else {
+                return false;
+            }
+        case 4:
+            arg1 = arguments[0];
+            arg2 = arguments[1];
+            arg3 = arguments[2];
+            arg4 = arguments[3];
+
+            if (isDate(arg1) && isMonth(arg2) && isDate(arg3) && isMonth(arg4)) {
+                var date1 = arg1;
+                var month1 = strToMonth(arg2);
+                var date2 = arg3;
+                var month2 = strToMonth(arg4);
+
+                return inMonthDateRange(today, date1, month1, date2, month2);
+
+            } else if (isMonth(arg1) && isYear(arg2) && isMonth(arg3) && isYear(arg4)) {
+                var month1 = strToMonth(arg1);
+                var year1 = arg2;
+                var month2 = strToMonth(arg3);
+                var year2 = arg4;
+
+                return inYearMonthRange(today, month1, year1, month2, year2);
+            } else {
+                return false;
+            }
+        case 6:
+            arg1 = arguments[0];
+            arg2 = arguments[1];
+            arg3 = arguments[2];
+            arg4 = arguments[3];
+            arg5 = arguments[4];
+            arg6 = arguments[5];
+            if (isDate(arg1) && isMonth(arg2) && isYear(arg3) &&
+                isDate(arg4) && isMonth(arg5) && isYear(arg6)) {
+                var day1 = arg1;
+                var month1 = strToMonth(arg2);
+                var year1 = arg3;
+                var day2 = arg4;
+                var month2 = strToMonth(arg5);
+                var year2 = arg6;
+
+                return inYearMonthDateRange(today, day1, month1, year1, day2, month2, year2);
+            } else {
+                return false;
+            }
+        default:
+            return false;
+    }
+
+}
+
+/**
+ * Returns true if the current time matches the range given
+ *
+ * timeRange(hour)
+ * timeRange(hour1, hour2)
+ * timeRange(hour1, min1, hour2, min2)
+ * timeRange(hour1, min1, sec1, hour2, min2, sec2)
+ *
+ * The string "GMT" can be used as the last additional parameter in addition to
+ * the methods listed above.
+ */
+function timeRange() {
+
+    // watch out for wrap around of times
+
+    var gmt;
+	if (arguments.length > 1) {
+		if (arguments[arguments.length-1] === "GMT") {
+			gmt = true;
+            arguments.splice(0,arguments.length-1);
+        }
+	}
+
+    function isHour(hour) {
+        if (typeof(hour) === "number" && ( 0 <= hour && hour <= 23)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    function isMin(minute) {
+        if (typeof(minute) === "number" && (0 <= minute && minute <= 59)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    function inHourRange(now, hour1, hour2) {
+        if (hour1 === hour2) {
+            if (now.getHours() === hour1) {
+                return true;
+            } else {
+                return false;
+            }
+        } else if (hour1 < hour2) {
+           if (hour1 <= now.getHours() && now.getHours() <= hour2) {
+                return true;
+           } else {
+               return false;
+           }
+        } else {
+            if (hour1 <= now.getHours() || now.getHours() <= hour2) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    function inHourMinuteRange(now, hour1, min1, hour2, min2) {
+        if (hour1 == hour2) {
+            if (now.getHours() == hour1) {
+                if (min1 <= min2) {
+                    if (min1 <= now.getMinutes() && now.getMinutes() <= min2) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    if (min1 <= now.getMinutes() || now.getMinutes() <= min2) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            } else {
+                if (min1 <= min2) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+        } else if (hour1 < hour2) {
+            if (hour1 <= now.getHours() && now.getHours() <= hour2) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            if (hour1 <= now.getHours() || now.getHours() <= hour2) {
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    var today = new Date();
+
+    switch (arguments.length) {
+        case 1:
+            var hour = arguments[0];
+            if (today.getHours() === hour) {
+                return true;
+            } else {
+                return false;
+            }
+        case 2:
+            var hour1 = arguments[0];
+            var hour2 = arguments[1];
+            if (isHour(hour1) && isHour(hour2)) {
+                return inHourRange(today, hour1, hour2);
+            } else {
+                return false;
+            }
+        case 4:
+            var hour1 = arguments[0];
+            var min1 = arguments[1];
+            var hour2 = arguments[2];
+            var min2 = arguments[3];
+
+            if (isHour(hour1) && isMin(min1) && isHour(hour2) && isMin(min2)) {
+                return inHourMinuteRange(today, hour1, min1, hour2, min2);
+            } else {
+                return false;
+            }
+
+        case 6:
+            var hour1 = arguments[0];
+            var min1 = arguments[1];
+            var sec1 = arguments[2];
+            var hour2 = arguments[3];
+            var min2 = arguments[4];
+            var sec2 = arguments[5];
+
+            // TODO handle seconds properly
+
+            return inHourMinuteRange(today, hour1, min1, hour2, min2);
+        default:
+            return false;
+    }
+}
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/package.html
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/package.html	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/runtime/package.html	(revision 403)
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the classes that manage the secure runtime
+environment for JNLP apps.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AccessWarningPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AccessWarningPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AccessWarningPane.java	(revision 403)
@@ -0,0 +1,211 @@
+/* AccessWarningPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * Provides a panel to show inside a SecurityDialog. These dialogs are
+ * used to warn the user when either signed code (with or without signing
+ * issues) is going to be run, or when service permission (file, clipboard,
+ * printer, etc) is needed with unsigned code.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+public class AccessWarningPane extends SecurityDialogPanel {
+
+    JCheckBox alwaysAllow;
+    Object[] extras;
+
+    public AccessWarningPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        addComponents();
+    }
+
+    public AccessWarningPane(SecurityDialog x, Object[] extras, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        this.extras = extras;
+        addComponents();
+    }
+
+    /**
+     * Creates the actual GUI components, and adds it to this panel
+     */
+    private void addComponents() {
+        AccessType type = parent.getAccessType();
+        JNLPFile file = parent.getFile();
+
+        String name = "";
+        String publisher = "";
+        String from = "";
+
+        //We don't worry about exceptions when trying to fill in
+        //these strings -- we just want to fill in as many as possible.
+        try {
+            name = file.getInformation().getTitle() != null ? file.getInformation().getTitle() : R("SNoAssociatedCertificate");
+        } catch (Exception e) {
+        }
+
+        try {
+            publisher = file.getInformation().getVendor() != null ? file.getInformation().getVendor() : R("SNoAssociatedCertificate");
+        } catch (Exception e) {
+        }
+
+        try {
+            from = !file.getInformation().getHomepage().toString().equals("") ? file.getInformation().getHomepage().toString() : file.getSourceLocation().getAuthority();
+        } catch (Exception e) {
+            from = file.getSourceLocation().getAuthority();
+        }
+
+        //Top label
+        String topLabelText = "";
+        switch (type) {
+            case READ_FILE:
+                if (extras != null && extras.length > 0 && extras[0] instanceof String) {
+                    topLabelText = R("SFileReadAccess", FileUtils.displayablePath((String) extras[0]));
+                } else {
+                    topLabelText = R("SFileReadAccess", R("AFileOnTheMachine"));
+                }
+                break;
+            case WRITE_FILE:
+                if (extras != null && extras.length > 0 && extras[0] instanceof String) {
+                    topLabelText = R("SFileWriteAccess", FileUtils.displayablePath((String) extras[0]));
+                } else {
+                    topLabelText = R("SFileWriteAccess", R("AFileOnTheMachine"));
+                }
+                break;
+            case CREATE_DESTKOP_SHORTCUT:
+                topLabelText = R("SDesktopShortcut");
+                break;
+            case CLIPBOARD_READ:
+                topLabelText = R("SClipboardReadAccess");
+                break;
+            case CLIPBOARD_WRITE:
+                topLabelText = R("SClipboardWriteAccess");
+                break;
+            case PRINTER:
+                topLabelText = R("SPrinterAccess");
+                break;
+            case NETWORK:
+                if (extras != null && extras.length >= 0)
+                    topLabelText = R("SNetworkAccess", extras[0]);
+                else
+                    topLabelText = R("SNetworkAccess", "(address here)");
+        }
+
+        ImageIcon icon = new ImageIcon((new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/warning.png"));
+        JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT);
+        topLabel.setFont(new Font(topLabel.getFont().toString(),
+                        Font.BOLD, 12));
+        JPanel topPanel = new JPanel(new BorderLayout());
+        topPanel.setBackground(Color.WHITE);
+        topPanel.add(topLabel, BorderLayout.CENTER);
+        topPanel.setPreferredSize(new Dimension(450, 100));
+        topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //application info
+        JLabel nameLabel = new JLabel(R("Name") + ":   " + name);
+        nameLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        JLabel publisherLabel = new JLabel(R("Publisher") + ": " + publisher);
+        publisherLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        JLabel fromLabel = new JLabel(R("From") + ":   " + from);
+        fromLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+        alwaysAllow = new JCheckBox(R("AlwaysAllowAction"));
+        alwaysAllow.setEnabled(false);
+
+        JPanel infoPanel = new JPanel(new GridLayout(4, 1));
+        infoPanel.add(nameLabel);
+        infoPanel.add(publisherLabel);
+        infoPanel.add(fromLabel);
+        infoPanel.add(alwaysAllow);
+        infoPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25));
+
+        //run and cancel buttons
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+
+        JButton run = new JButton(R("ButAllow"));
+        JButton cancel = new JButton(R("ButCancel"));
+        run.addActionListener(createSetValueListener(parent, 0));
+        run.addActionListener(new CheckBoxListener());
+        cancel.addActionListener(createSetValueListener(parent, 1));
+        initialFocusComponent = cancel;
+        buttonPanel.add(run);
+        buttonPanel.add(cancel);
+        buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //all of the above
+        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        add(topPanel);
+        add(infoPanel);
+        add(buttonPanel);
+
+    }
+
+    private class CheckBoxListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+            if (alwaysAllow != null && alwaysAllow.isSelected()) {
+                // TODO: somehow tell the ApplicationInstance
+                // to stop asking for permission
+            }
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AppletWarningPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AppletWarningPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/AppletWarningPane.java	(revision 403)
@@ -0,0 +1,114 @@
+/* AppletWarningPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class AppletWarningPane extends SecurityDialogPanel {
+
+    public AppletWarningPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        addComponents();
+    }
+
+    protected void addComponents() {
+
+        //Top label
+        String topLabelText = "While support for verifying signed code" +
+                                " has not been implemented yet, some applets will not run " +
+                                "properly under the default restricted security level.";
+        String bottomLabelText = "Do you want to run this applet under the " +
+                                "restricted security level? (clicking No will run this applet " +
+                                "without any security checking, and should only be done if you " +
+                                "trust the applet!)";
+
+        JLabel topLabel = new JLabel(htmlWrap(topLabelText));
+        topLabel.setFont(new Font(topLabel.getFont().toString(),
+                        Font.BOLD, 12));
+        JPanel topPanel = new JPanel(new BorderLayout());
+        topPanel.setBackground(Color.WHITE);
+        topPanel.add(topLabel, BorderLayout.CENTER);
+        topPanel.setPreferredSize(new Dimension(400, 80));
+        topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        JLabel bottomLabel = new JLabel(htmlWrap(bottomLabelText));
+        JPanel infoPanel = new JPanel(new BorderLayout());
+        infoPanel.add(bottomLabel, BorderLayout.CENTER);
+        infoPanel.setPreferredSize(new Dimension(400, 80));
+        infoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //run and cancel buttons
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+
+        JButton yes = new JButton("Yes");
+        JButton no = new JButton("No");
+        JButton cancel = new JButton("Cancel");
+        int buttonWidth = cancel.getMinimumSize().width;
+        int buttonHeight = cancel.getMinimumSize().height;
+        Dimension d = new Dimension(buttonWidth, buttonHeight);
+        yes.setPreferredSize(d);
+        no.setPreferredSize(d);
+        cancel.setPreferredSize(d);
+        yes.addActionListener(createSetValueListener(parent, 0));
+        no.addActionListener(createSetValueListener(parent, 1));
+        cancel.addActionListener(createSetValueListener(parent, 2));
+        initialFocusComponent = cancel;
+        buttonPanel.add(yes);
+        buttonPanel.add(no);
+        buttonPanel.add(cancel);
+        buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //all of the above
+        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        add(topPanel);
+        add(infoPanel);
+        add(buttonPanel);
+
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertVerifier.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertVerifier.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertVerifier.java	(revision 403)
@@ -0,0 +1,93 @@
+/* CertVerifier.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+
+/**
+ * An interface that provides various details about a certificate
+ */
+
+public interface CertVerifier {
+
+    /**
+     * Return if the publisher is already trusted
+     */
+    public boolean getAlreadyTrustPublisher();
+
+    /**
+     * Return if the root is in CA certs
+     */
+    public boolean getRootInCacerts();
+
+    /**
+     * Return if there are signing issues with the certificate(s) being veried
+     */
+    public boolean hasSigningIssues();
+
+    /**
+     * Return if there are no signing issues with this cert (!hasSigningIssues())
+     */
+    public boolean noSigningIssues();
+
+    /**
+     * Get the details regarding issue(s) with this certificate
+     */
+    public ArrayList<String> getDetails();
+
+    /**
+     * Return a valid certificate path to this certificate(s) being verified
+     * @return The CertPath
+     */
+    public CertPath getCertPath();
+
+    /**
+     * Returns the application's publisher's certificate.
+     */
+    public abstract Certificate getPublisher();
+
+    /**
+     * Returns the application's root's certificate. This
+     * may return the same certificate as getPublisher() in
+     * the event that the application is self signed.
+     */
+    public abstract Certificate getRoot();
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertWarningPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertWarningPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertWarningPane.java	(revision 403)
@@ -0,0 +1,272 @@
+/* CertWarningPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.PluginBridge;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.KeyStores.Level;
+import net.sourceforge.jnlp.security.KeyStores.Type;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * Provides the panel for using inside a SecurityDialog. These dialogs are
+ * used to warn the user when either signed code (with or without signing
+ * issues) is going to be run, or when service permission (file, clipboard,
+ * printer, etc) is needed with unsigned code.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+public class CertWarningPane extends SecurityDialogPanel {
+
+    JCheckBox alwaysTrust;
+    CertVerifier certVerifier;
+
+    public CertWarningPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        this.certVerifier = certVerifier;
+        addComponents();
+    }
+
+    /**
+     * Creates the actual GUI components, and adds it to this panel
+     */
+    private void addComponents() {
+        AccessType type = parent.getAccessType();
+        JNLPFile file = parent.getFile();
+        Certificate c = parent.getJarSigner().getPublisher();
+
+        String name = "";
+        String publisher = "";
+        String from = "";
+
+        //We don't worry about exceptions when trying to fill in
+        //these strings -- we just want to fill in as many as possible.
+        try {
+            if ((certVerifier instanceof HttpsCertVerifier) &&
+                             (c instanceof X509Certificate))
+                name = SecurityUtil.getCN(((X509Certificate) c)
+                                        .getSubjectX500Principal().getName());
+            else if (file instanceof PluginBridge)
+                name = file.getTitle();
+            else
+                name = file.getInformation().getTitle();
+        } catch (Exception e) {
+        }
+
+        try {
+            if (c instanceof X509Certificate) {
+                publisher = SecurityUtil.getCN(((X509Certificate) c)
+                                        .getSubjectX500Principal().getName());
+            }
+        } catch (Exception e) {
+        }
+
+        try {
+            if (file instanceof PluginBridge)
+                from = file.getCodeBase().getHost();
+            else
+                from = file.getInformation().getHomepage().toString();
+        } catch (Exception e) {
+        }
+
+        //Top label
+        String topLabelText = "";
+        String propertyName = "";
+        if (certVerifier instanceof HttpsCertVerifier) {
+            topLabelText = R("SHttpsUnverified") + " " +
+                                 R("Continue");
+            propertyName = "OptionPane.warningIcon";
+        } else
+            switch (type) {
+                case VERIFIED:
+                    topLabelText = R("SSigVerified");
+                    propertyName = "OptionPane.informationIcon";
+                    break;
+                case UNVERIFIED:
+                    topLabelText = R("SSigUnverified");
+                    propertyName = "OptionPane.warningIcon";
+                    break;
+                case SIGNING_ERROR:
+                    topLabelText = R("SSignatureError");
+                    propertyName = "OptionPane.warningIcon";
+                    break;
+            }
+        ImageIcon icon = new ImageIcon((new sun.misc.Launcher())
+                                .getClassLoader().getResource("net/sourceforge/jnlp/resources/warning.png"));
+        JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT);
+        topLabel.setFont(new Font(topLabel.getFont().toString(),
+                                Font.BOLD, 12));
+        JPanel topPanel = new JPanel(new BorderLayout());
+        topPanel.setBackground(Color.WHITE);
+        topPanel.add(topLabel, BorderLayout.CENTER);
+        topPanel.setPreferredSize(new Dimension(400, 60));
+        topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //application info
+        JLabel nameLabel = new JLabel(R("Name") + ":   " + name);
+        nameLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        JLabel publisherLabel = new JLabel(R("Publisher") + ": " + publisher);
+        publisherLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        JLabel fromLabel = new JLabel(R("From") + ":   " + from);
+        fromLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+        alwaysTrust = new JCheckBox(R("SAlwaysTrustPublisher"));
+        alwaysTrust.setEnabled(true);
+
+        JPanel infoPanel = new JPanel(new GridLayout(4, 1));
+        infoPanel.add(nameLabel);
+        infoPanel.add(publisherLabel);
+
+        if (!(certVerifier instanceof HttpsCertVerifier))
+            infoPanel.add(fromLabel);
+
+        infoPanel.add(alwaysTrust);
+        infoPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25));
+
+        //run and cancel buttons
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+        JButton run = new JButton(R("ButRun"));
+        JButton cancel = new JButton(R("ButCancel"));
+        int buttonWidth = Math.max(run.getMinimumSize().width,
+                        cancel.getMinimumSize().width);
+        int buttonHeight = run.getMinimumSize().height;
+        Dimension d = new Dimension(buttonWidth, buttonHeight);
+        run.setPreferredSize(d);
+        cancel.setPreferredSize(d);
+        run.addActionListener(createSetValueListener(parent, 0));
+        run.addActionListener(new CheckBoxListener());
+        cancel.addActionListener(createSetValueListener(parent, 1));
+        initialFocusComponent = cancel;
+        buttonPanel.add(run);
+        buttonPanel.add(cancel);
+        buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //all of the above
+        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        add(topPanel);
+        add(infoPanel);
+        add(buttonPanel);
+
+        JLabel bottomLabel;
+        JButton moreInfo = new JButton(R("ButMoreInformation"));
+        moreInfo.addActionListener(new MoreInfoButtonListener());
+
+        if (parent.getJarSigner().getRootInCacerts())
+            bottomLabel = new JLabel(htmlWrap(R("STrustedSource")));
+        else
+            bottomLabel = new JLabel(htmlWrap(R("SUntrustedSource")));
+
+        JPanel bottomPanel = new JPanel();
+        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));
+        bottomPanel.add(bottomLabel);
+        bottomPanel.add(moreInfo);
+        bottomPanel.setPreferredSize(new Dimension(500, 100));
+        bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+        add(bottomPanel);
+
+    }
+
+    private class MoreInfoButtonListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+            SecurityDialog.showMoreInfoDialog(parent.getJarSigner(),
+                                parent);
+        }
+    }
+
+    /**
+     * Updates the user's KeyStore of trusted Certificates.
+     */
+    private class CheckBoxListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+            if (alwaysTrust != null && alwaysTrust.isSelected()) {
+                try {
+                    KeyStore ks = KeyStores.getKeyStore(Level.USER, Type.CERTS);
+                    X509Certificate c = (X509Certificate) parent.getJarSigner().getPublisher();
+                    CertificateUtils.addToKeyStore(c, ks);
+                    File keyStoreFile = new File(KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS));
+                    if (!keyStoreFile.isFile()) {
+                        FileUtils.createRestrictedFile(keyStoreFile, true);
+                    }
+
+                    OutputStream os = new FileOutputStream(keyStoreFile);
+                    try {
+                        ks.store(os, KeyStores.getPassword());
+                    } finally {
+                        os.close();
+                    }
+                    if (JNLPRuntime.isDebug()) {
+                        System.out.println("certificate is now permanently trusted");
+                    }
+                } catch (Exception ex) {
+                    // TODO: Let NetX show a dialog here notifying user
+                    // about being unable to add cert to keystore
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertificateUtils.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertificateUtils.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertificateUtils.java	(revision 403)
@@ -0,0 +1,151 @@
+/* CertificateUtils.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.math.BigInteger;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Random;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+import sun.misc.BASE64Encoder;
+import sun.security.provider.X509Factory;
+
+/**
+ * Common utilities to manipulate certificates. Provides methods to add
+ * Certificates to a KeyStores, check if certificates already exist in a
+ * KeyStore and printing certificates.
+ */
+public class CertificateUtils {
+
+    /**
+     * Adds the X509Certficate in the file to the KeyStore. Note that it does
+     * not update the copy of the KeyStore on disk.
+     */
+    public static final void addToKeyStore(File file, KeyStore ks) throws CertificateException,
+            IOException, KeyStoreException {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Importing certificate from " + file + " into " + ks);
+        }
+
+        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+        CertificateFactory cf = CertificateFactory.getInstance("X509");
+        X509Certificate cert = null;
+
+        try {
+            cert = (X509Certificate) cf.generateCertificate(bis);
+        } catch (ClassCastException cce) {
+            throw new CertificateException("Input file is not an X509 Certificate", cce);
+        }
+
+        addToKeyStore(cert, ks);
+    }
+
+    /**
+     * Adds an X509Certificate to the KeyStore. Note that it does not update the
+     * copy of the KeyStore on disk.
+     */
+    public static final void addToKeyStore(X509Certificate cert, KeyStore ks)
+            throws KeyStoreException {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Importing " + cert.getSubjectX500Principal().getName());
+        }
+
+        String alias = null;
+
+        // does this certificate already exist?
+        alias = ks.getCertificateAlias(cert);
+        if (alias != null) {
+            return;
+        }
+
+        // create a unique alias for this new certificate
+        Random random = new Random();
+        do {
+            alias = new BigInteger(20, random).toString();
+        } while (ks.getCertificate(alias) != null);
+
+        ks.setCertificateEntry(alias, cert);
+    }
+
+    /**
+     * Checks whether an X509Certificate is already in one of the keystores
+     * @param c the certificate
+     * @param keyStores the KeyStores to check in
+     * @return true if the certificate is present in one of the keystores, false otherwise
+     */
+    public static final boolean inKeyStores(X509Certificate c, KeyStore[] keyStores) {
+        for (int i = 0; i < keyStores.length; i++) {
+            try {
+                if (keyStores[i].getCertificateAlias(c) != null) {
+                    if (JNLPRuntime.isDebug()) {
+                        System.out.println(c.getSubjectX500Principal().getName() + " found in cacerts");
+                    }
+                    return true;
+                }
+            } catch (KeyStoreException e) {
+                e.printStackTrace();
+                // continue
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Writes the certificate in base64 encoded from to the print stream.
+     * See http://tools.ietf.org/html/rfc4945#section-6.1 for more information
+     */
+    public static void dump(Certificate cert, PrintStream out) throws IOException,
+            CertificateException {
+
+        BASE64Encoder encoder = new BASE64Encoder();
+        out.println(X509Factory.BEGIN_CERT);
+        encoder.encodeBuffer(cert.getEncoded(), out);
+        out.println(X509Factory.END_CERT);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertsInfoPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertsInfoPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/CertsInfoPane.java	(revision 403)
@@ -0,0 +1,339 @@
+/* CertsInfoPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.util.ArrayList;
+import java.security.cert.CertPath;
+import java.security.cert.X509Certificate;
+import java.security.MessageDigest;
+
+import sun.misc.HexDumpEncoder;
+import sun.security.x509.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeSelectionModel;
+
+/**
+ * Provides the panel for the Certificate Info dialog. This dialog displays data from
+ * X509Certificate(s) used in jar signing.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+public class CertsInfoPane extends SecurityDialogPanel {
+
+    private CertPath certPath;
+    private JList list;
+    protected JTree tree;
+    private JTable table;
+    private JTextArea output;
+    private ListSelectionModel listSelectionModel;
+    private ListSelectionModel tableSelectionModel;
+    protected String[] certNames;
+    private String[] columnNames = { R("Field"), R("Value") };
+    protected ArrayList<String[][]> certsData;
+
+    public CertsInfoPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        addComponents();
+    }
+
+    /**
+     * Builds the JTree out of CertPaths.
+     */
+    void buildTree() {
+        certPath = parent.getJarSigner().getCertPath();
+        X509Certificate firstCert =
+                        ((X509Certificate) certPath.getCertificates().get(0));
+        String subjectString =
+                        SecurityUtil.getCN(firstCert.getSubjectX500Principal().getName());
+        String issuerString =
+                        SecurityUtil.getCN(firstCert.getIssuerX500Principal().getName());
+
+        DefaultMutableTreeNode top =
+                        new DefaultMutableTreeNode(subjectString
+                                + " (" + issuerString + ")");
+
+        //not self signed
+        if (!firstCert.getSubjectDN().equals(firstCert.getIssuerDN())
+                        && (certPath.getCertificates().size() > 1)) {
+            X509Certificate secondCert =
+                                ((X509Certificate) certPath.getCertificates().get(1));
+            subjectString =
+                                SecurityUtil.getCN(secondCert.getSubjectX500Principal().getName());
+            issuerString =
+                                SecurityUtil.getCN(secondCert.getIssuerX500Principal().getName());
+            top.add(new DefaultMutableTreeNode(subjectString
+                                + " (" + issuerString + ")"));
+        }
+
+        tree = new JTree(top);
+        tree.getSelectionModel().setSelectionMode
+                                (TreeSelectionModel.SINGLE_TREE_SELECTION);
+        tree.addTreeSelectionListener(new TreeSelectionHandler());
+    }
+
+    /**
+     * Fills in certsNames, certsData with data from the certificates.
+     */
+    protected void populateTable() {
+        certNames = new String[certPath.getCertificates().size()];
+        certsData = new ArrayList<String[][]>();
+
+        for (int i = 0; i < certPath.getCertificates().size(); i++) {
+
+            X509Certificate c = (X509Certificate) certPath.getCertificates().get(i);
+            certsData.add(parseCert(c));
+            certNames[i] = SecurityUtil.getCN(c.getSubjectX500Principal().getName())
+                                + " (" + SecurityUtil.getCN(c.getIssuerX500Principal().getName()) + ")";
+        }
+    }
+
+    protected String[][] parseCert(X509Certificate c) {
+
+        String version = "" + c.getVersion();
+        String serialNumber = c.getSerialNumber().toString();
+        String signatureAlg = c.getSigAlgName();
+        String issuer = c.getIssuerX500Principal().toString();
+        String validity = new CertificateValidity(c.getNotBefore(),
+                            c.getNotAfter()).toString();
+        String subject = c.getSubjectX500Principal().toString();
+
+        //convert our signature into a nice human-readable form.
+        HexDumpEncoder encoder = new HexDumpEncoder();
+        String signature = encoder.encodeBuffer(c.getSignature());
+
+        String md5Hash = "";
+        String sha1Hash = "";
+        try {
+            MessageDigest digest = MessageDigest.getInstance("MD5");
+            digest.update(c.getEncoded());
+            md5Hash = makeFingerprint(digest.digest());
+
+            digest = MessageDigest.getInstance("SHA-1");
+            digest.update(c.getEncoded());
+            sha1Hash = makeFingerprint(digest.digest());
+        } catch (Exception e) {
+            //fail quietly
+        }
+
+        String[][] cert = { { R("Version"), version },
+                            { R("SSerial"), serialNumber },
+                            { R("SSignatureAlgorithm"), signatureAlg },
+                            { R("SIssuer"), issuer },
+                            { R("SValidity"), validity },
+                            { R("SSubject"), subject },
+                            { R("SSignature"), signature },
+                                                        { R("SMD5Fingerprint"), md5Hash },
+                                                        { R("SSHA1Fingerprint"), sha1Hash }
+                                                        };
+        return cert;
+    }
+
+    /**
+     * Constructs the GUI components of this panel
+     */
+    protected void addComponents() {
+        buildTree();
+        populateTable();
+        /**
+        //List of Certs
+        list = new JList(certNames);
+        list.setSelectedIndex(0); //assuming there's at least 1 cert
+        listSelectionModel = list.getSelectionModel();
+        listSelectionModel.addListSelectionListener(new ListSelectionHandler());
+        JScrollPane listPane = new JScrollPane(list);
+        */
+        JScrollPane listPane = new JScrollPane(tree);
+
+        //Table of field-value pairs
+        DefaultTableModel tableModel = new DefaultTableModel(certsData.get(0),
+                                                            columnNames);
+        table = new JTable(tableModel);
+        table.getTableHeader().setReorderingAllowed(false);
+        tableSelectionModel = table.getSelectionModel();
+        tableSelectionModel.addListSelectionListener(new TableSelectionHandler());
+        table.setFillsViewportHeight(true);
+        JScrollPane tablePane = new JScrollPane(table);
+        tablePane.setPreferredSize(new Dimension(500, 200));
+
+        //Text area to display the larger values
+        output = new JTextArea();
+        output.setEditable(false);
+        JScrollPane outputPane = new JScrollPane(output,
+                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
+                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        outputPane.setPreferredSize(new Dimension(500, 200));
+
+        //split pane of the field-value pairs and textbox
+        JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+                        tablePane, outputPane);
+        rightSplitPane.setDividerLocation(0.50);
+        rightSplitPane.setResizeWeight(0.50);
+
+        JSplitPane mainPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+                        listPane, rightSplitPane);
+        mainPane.setDividerLocation(0.30);
+        mainPane.setResizeWeight(0.30);
+
+        JPanel buttonPane = new JPanel(new BorderLayout());
+        JButton close = new JButton(R("ButClose"));
+        JButton copyToClipboard = new JButton(R("ButCopy"));
+        close.addActionListener(createSetValueListener(parent, 0));
+        copyToClipboard.addActionListener(new CopyToClipboardHandler());
+        buttonPane.add(close, BorderLayout.EAST);
+        buttonPane.add(copyToClipboard, BorderLayout.WEST);
+        buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+        add(mainPane, BorderLayout.CENTER);
+        add(buttonPane, BorderLayout.SOUTH);
+    }
+
+    /**
+     * Copies the currently selected certificate to the system Clipboard.
+     */
+    private class CopyToClipboardHandler implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+            int certIndex = 0;
+            DefaultMutableTreeNode node = (DefaultMutableTreeNode)
+                    tree.getLastSelectedPathComponent();
+            if (node == null)
+                return;
+            if (node.isRoot())
+                certIndex = 0;
+            else if (node.isLeaf())
+                certIndex = 1;
+
+            String[][] cert = certsData.get(certIndex);
+            int rows = cert.length;
+            int cols = cert[0].length;
+
+            String certString = "";
+            for (int i = 0; i < rows; i++) {
+                for (int j = 0; j < cols; j++) {
+                    certString += cert[i][j];
+                    certString += " ";
+                }
+                certString += "\n";
+            }
+
+            clipboard.setContents(new StringSelection(certString), null);
+        }
+    }
+
+    /**
+     * Updates the JTable when the JTree selection has changed.
+     */
+    protected class TreeSelectionHandler implements TreeSelectionListener {
+        public void valueChanged(TreeSelectionEvent e) {
+            DefaultMutableTreeNode node = (DefaultMutableTreeNode)
+                                tree.getLastSelectedPathComponent();
+
+            if (node == null)
+                return;
+            if (node.isRoot()) {
+                table.setModel(new DefaultTableModel(certsData.get(0),
+                                        columnNames));
+            } else if (node.isLeaf()) {
+                table.setModel(new DefaultTableModel(certsData.get(1),
+                                        columnNames));
+            }
+        }
+    }
+
+    /**
+    * Updates the JTable when the selection on the list has changed.
+    */
+    private class ListSelectionHandler implements ListSelectionListener {
+        public void valueChanged(ListSelectionEvent e) {
+            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
+
+            int minIndex = lsm.getMinSelectionIndex();
+            int maxIndex = lsm.getMaxSelectionIndex();
+
+            for (int i = minIndex; i <= maxIndex; i++) {
+                if (lsm.isSelectedIndex(i)) {
+                    table.setModel(new DefaultTableModel(certsData.get(i),
+                                                            columnNames));
+                }
+            }
+        }
+    }
+
+    /**
+     * Updates the JTextArea output when the selection on the JTable
+     * has changed.
+     */
+    private class TableSelectionHandler implements ListSelectionListener {
+        public void valueChanged(ListSelectionEvent e) {
+            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
+
+            int minIndex = lsm.getMinSelectionIndex();
+            int maxIndex = lsm.getMaxSelectionIndex();
+
+            for (int i = minIndex; i <= maxIndex; i++) {
+                if (lsm.isSelectedIndex(i)) {
+                    output.setText((String) table.getValueAt(i, 1));
+                }
+            }
+        }
+    }
+
+    /**
+     * Makes a human readable hash fingerprint.
+     * For example: 11:22:33:44:AA:BB:CC:DD:EE:FF.
+     */
+    private String makeFingerprint(byte[] hash) {
+        String fingerprint = "";
+        for (int i = 0; i < hash.length; i++) {
+            if (!fingerprint.equals(""))
+                fingerprint += ":";
+            fingerprint += Integer.toHexString(
+                                ((hash[i] & 0xFF) | 0x100)).substring(1, 3);
+        }
+        return fingerprint.toUpperCase();
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java	(revision 403)
@@ -0,0 +1,227 @@
+/* HttpsCertVerifier.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import sun.security.util.DerValue;
+import sun.security.util.HostnameChecker;
+import sun.security.x509.X500Name;
+
+public class HttpsCertVerifier implements CertVerifier {
+
+    private VariableX509TrustManager tm;
+    private X509Certificate[] chain;
+    private String authType;
+    private String hostName;
+    private boolean isTrusted;
+    private boolean hostMatched;
+    private ArrayList<String> details = new ArrayList<String>();
+
+    public HttpsCertVerifier(VariableX509TrustManager tm,
+                             X509Certificate[] chain, String authType,
+                             boolean isTrusted, boolean hostMatched,
+                             String hostName) {
+        this.tm = tm;
+        this.chain = chain;
+        this.authType = authType;
+        this.hostName = hostName;
+        this.isTrusted = isTrusted;
+        this.hostMatched = hostMatched;
+    }
+
+    public boolean getAlreadyTrustPublisher() {
+        return isTrusted;
+    }
+
+    public CertPath getCertPath() {
+
+        ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
+        for (int i = 0; i < chain.length; i++)
+            list.add(chain[i]);
+
+        ArrayList<CertPath> certPaths = new ArrayList<CertPath>();
+
+        try {
+            certPaths.add(CertificateFactory.getInstance("X.509").generateCertPath(list));
+        } catch (CertificateException ce) {
+            ce.printStackTrace();
+
+            // carry on
+        }
+
+        return certPaths.get(0);
+    }
+
+    public ArrayList<String> getDetails() {
+
+        boolean hasExpiredCert = false;
+        boolean hasExpiringCert = false;
+        boolean notYetValidCert = false;
+        boolean isUntrusted = false;
+        boolean CNMisMatch = !hostMatched;
+
+        if (!getAlreadyTrustPublisher())
+            isUntrusted = true;
+
+        for (int i = 0; i < chain.length; i++) {
+            X509Certificate cert = chain[i];
+
+            long now = System.currentTimeMillis();
+            long SIX_MONTHS = 180 * 24 * 60 * 60 * 1000L;
+            long notAfter = cert.getNotAfter().getTime();
+            if (notAfter < now) {
+                hasExpiredCert = true;
+            } else if (notAfter < now + SIX_MONTHS) {
+                hasExpiringCert = true;
+            }
+
+            try {
+                cert.checkValidity();
+            } catch (CertificateNotYetValidException cnyve) {
+                notYetValidCert = true;
+            } catch (CertificateExpiredException cee) {
+                hasExpiredCert = true;
+            }
+        }
+
+        String altNames = getNamesForCert(chain[0]);
+
+        if (isUntrusted || hasExpiredCert || hasExpiringCert || notYetValidCert || CNMisMatch) {
+            if (isUntrusted)
+                addToDetails(R("SUntrustedCertificate"));
+            if (hasExpiredCert)
+                addToDetails(R("SHasExpiredCert"));
+            if (hasExpiringCert)
+                addToDetails(R("SHasExpiringCert"));
+            if (notYetValidCert)
+                addToDetails(R("SNotYetValidCert"));
+            if (CNMisMatch)
+                addToDetails(R("SCNMisMatch", altNames, this.hostName));
+        }
+
+        return details;
+    }
+
+    private String getNamesForCert(X509Certificate c) {
+
+        String names = "";
+
+        // We use the specification from
+        // http://java.sun.com/j2se/1.5.0/docs/api/java/security/cert/X509Certificate.html#getSubjectAlternativeNames()
+        // to determine the type of address
+        int ALTNAME_DNS = 2;
+        int ALTNAME_IP = 7;
+
+        try {
+            Collection<List<?>> subjAltNames = c.getSubjectAlternativeNames();
+            X500Name subjectName = HostnameChecker.getSubjectX500Name(c);
+            DerValue derValue = subjectName.findMostSpecificAttribute
+                                                        (X500Name.commonName_oid);
+            names += derValue.getAsString();
+
+            if (subjAltNames != null) {
+                for (List<?> next : subjAltNames) {
+                    if (((Integer) next.get(0)).intValue() == ALTNAME_IP ||
+                            ((Integer) next.get(0)).intValue() == ALTNAME_DNS) {
+                        names += ", " + (String) next.get(1);
+                    }
+                }
+            }
+
+            if (subjAltNames != null)
+                names = names.substring(2); // remove proceeding ", "
+
+        } catch (CertificateParsingException cpe) {
+            cpe.printStackTrace();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+
+        return names;
+    }
+
+    private void addToDetails(String detail) {
+        if (!details.contains(detail))
+            details.add(detail);
+    }
+
+    public Certificate getPublisher() {
+        if (chain.length > 0)
+            return (Certificate) chain[0];
+        return null;
+    }
+
+    public Certificate getRoot() {
+        if (chain.length > 0)
+            return (Certificate) chain[chain.length - 1];
+        return null;
+    }
+
+    public boolean getRootInCacerts() {
+        try {
+            KeyStore[] caCertsKeyStores = KeyStores.getCAKeyStores();
+            return CertificateUtils.inKeyStores((X509Certificate) getRoot(), caCertsKeyStores);
+        } catch (Exception e) {
+        }
+        return false;
+    }
+
+    public boolean hasSigningIssues() {
+        return false;
+    }
+
+    public boolean noSigningIssues() {
+        return false;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java	(revision 403)
@@ -0,0 +1,66 @@
+/* JNLPAuthenticator
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.security;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+
+public class JNLPAuthenticator extends Authenticator {
+
+    @Override
+    public PasswordAuthentication getPasswordAuthentication() {
+
+        // No security check is required here, because the only way to set
+        // parameters for which auth info is needed
+        // (Authenticator:requestPasswordAuthentication()), has a security check
+
+        String type = this.getRequestorType() == RequestorType.PROXY ? "proxy" : "web";
+
+        String host = getRequestingHost();
+        int port = getRequestingPort();
+        String prompt = getRequestingPrompt();
+
+        Object[] response = SecurityDialogs.showAuthenicationPrompt(host, port, prompt, type);
+        if (response == null) {
+            return null;
+        } else {
+            return new PasswordAuthentication((String) response[0], (char[]) response[1]);
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/KeyStores.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/KeyStores.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/KeyStores.java	(revision 403)
@@ -0,0 +1,383 @@
+/* KeyStores.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.AllPermission;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.Translator;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * The <code>KeyStores</code> class allows easily accessing the various KeyStores
+ * used.
+ */
+public final class KeyStores {
+
+    /* this gets turned into user-readable strings, see toUserReadableString */
+
+    public enum Level {
+        USER,
+        SYSTEM,
+    }
+
+    public enum Type {
+        CERTS,
+        JSSE_CERTS,
+        CA_CERTS,
+        JSSE_CA_CERTS,
+        CLIENT_CERTS,
+    }
+
+    private static DeploymentConfiguration config = null;
+
+    private static final String KEYSTORE_TYPE = "JKS";
+    /** the default password used to protect the KeyStores */
+    private static final String DEFAULT_PASSWORD = "changeit";
+
+    public static final char[] getPassword() {
+        return DEFAULT_PASSWORD.toCharArray();
+    }
+
+    /** Set the configuration object to use for getting KeyStore paths */
+    public static void setConfiguration(DeploymentConfiguration newConfig) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new AllPermission());
+        }
+
+        config = newConfig;
+    }
+
+    /**
+     * Returns a KeyStore corresponding to the appropriate level level (user or
+     * system) and type.
+     *
+     * @param level whether the KeyStore desired is a user-level or system-level
+     * KeyStore
+     * @param type the type of KeyStore desired
+     * @return a KeyStore containing certificates from the appropriate
+     */
+    public static final KeyStore getKeyStore(Level level, Type type) {
+        boolean create = false;
+        if (level == Level.USER) {
+            create = true;
+        } else {
+            create = false;
+        }
+        return getKeyStore(level, type, create);
+    }
+
+    /**
+     * Returns a KeyStore corresponding to the appropriate level level (user or
+     * system) and type.
+     *
+     * @param level whether the KeyStore desired is a user-level or system-level
+     * KeyStore
+     * @param type the type of KeyStore desired
+     * @return a KeyStore containing certificates from the appropriate
+     */
+    public static final KeyStore getKeyStore(Level level, Type type, boolean create) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new AllPermission());
+        }
+
+        String location = getKeyStoreLocation(level, type);
+        KeyStore ks = null;
+        try {
+            ks = createKeyStoreFromFile(new File(location), create, DEFAULT_PASSWORD);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return ks;
+    }
+
+    /**
+     * Returns an array of KeyStore that contain certificates that are trusted.
+     * The KeyStores contain certificates from different sources.
+     *
+     * @return an array of KeyStore containing trusted Certificates
+     */
+    public static final KeyStore[] getCertKeyStores() {
+        List<KeyStore> result = new ArrayList<KeyStore>(10);
+        KeyStore ks = null;
+
+        /* System-level JSSE certificates */
+        ks = getKeyStore(Level.SYSTEM, Type.JSSE_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* System-level certificates */
+        ks = getKeyStore(Level.SYSTEM, Type.CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* User-level JSSE certificates */
+        ks = getKeyStore(Level.USER, Type.JSSE_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* User-level certificates */
+        ks = getKeyStore(Level.USER, Type.CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+
+        return result.toArray(new KeyStore[result.size()]);
+    }
+
+    /**
+     * Returns an array of KeyStore that contain trusted CA certificates.
+     *
+     * @return an array of KeyStore containing trusted CA certificates
+     */
+    public static final KeyStore[] getCAKeyStores() {
+        List<KeyStore> result = new ArrayList<KeyStore>(10);
+        KeyStore ks = null;
+
+        /* System-level JSSE CA certificates */
+        ks = getKeyStore(Level.SYSTEM, Type.JSSE_CA_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* System-level CA certificates */
+        ks = getKeyStore(Level.SYSTEM, Type.CA_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* User-level JSSE CA certificates */
+        ks = getKeyStore(Level.USER, Type.JSSE_CA_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+        /* User-level CA certificates */
+        ks = getKeyStore(Level.USER, Type.CA_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+
+        return result.toArray(new KeyStore[result.size()]);
+    }
+
+    /**
+     * Returns KeyStores containing trusted client certificates
+     *
+     * @return an array of KeyStore objects that can be used to check client
+     * authentication certificates
+     */
+    public static KeyStore[] getClientKeyStores() {
+        List<KeyStore> result = new ArrayList<KeyStore>();
+        KeyStore ks = null;
+
+        ks = getKeyStore(Level.SYSTEM, Type.CLIENT_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+
+        ks = getKeyStore(Level.USER, Type.CLIENT_CERTS);
+        if (ks != null) {
+            result.add(ks);
+        }
+
+        return result.toArray(new KeyStore[result.size()]);
+    }
+
+    /**
+     * Returns the location of a KeyStore corresponding to the given level and type.
+     *
+     * @param level the specified level of the key store to be returned.
+     * @param type the specified type of the key store to be returned.
+     * @return the location of the key store.
+     */
+    public static final String getKeyStoreLocation(Level level, Type type) {
+        String configKey = null;
+        switch (level) {
+            case SYSTEM:
+                switch (type) {
+                    case JSSE_CA_CERTS:
+                        configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS;
+                        break;
+                    case CA_CERTS:
+                        configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CA_CERTS;
+                        break;
+                    case JSSE_CERTS:
+                        configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CERTS;
+                        break;
+                    case CERTS:
+                        configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CERTS;
+                        break;
+                    case CLIENT_CERTS:
+                        configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CLIENT_CERTS;
+                        break;
+                }
+                break;
+            case USER:
+                switch (type) {
+                    case JSSE_CA_CERTS:
+                        configKey = DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CA_CERTS;
+                        break;
+                    case CA_CERTS:
+                        configKey = DeploymentConfiguration.KEY_USER_TRUSTED_CA_CERTS;
+                        break;
+                    case JSSE_CERTS:
+                        configKey = DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CERTS;
+                        break;
+                    case CERTS:
+                        configKey = DeploymentConfiguration.KEY_USER_TRUSTED_CERTS;
+                        break;
+                    case CLIENT_CERTS:
+                        configKey = DeploymentConfiguration.KEY_USER_TRUSTED_CLIENT_CERTS;
+                        break;
+                }
+                break;
+        }
+
+        if (configKey == null) {
+            throw new RuntimeException("Unspported");
+        }
+
+        return config.getProperty(configKey);
+    }
+
+    /**
+     * Returns a String that can be used as a translation key to create a
+     * user-visible representation of this KeyStore. Creates a string by
+     * concatenating a level and type, converting everything to Title Case and
+     * removing the _'s. (USER,CA_CERTS) becomes UserCaCerts.
+     *
+     * @param level the level of the key store.
+     * @param type the type of the key store.
+     * @return the translation key.
+     */
+    public static final String toTranslatableString(Level level, Type type) {
+        StringBuilder response = new StringBuilder();
+
+        response.append("KS");
+
+        if (level != null) {
+            String levelString = level.toString();
+            response.append(levelString.substring(0, 1).toUpperCase());
+            response.append(levelString.substring(1).toLowerCase());
+        }
+
+        if (type != null) {
+            String typeString = type.toString();
+            StringTokenizer tokenizer = new StringTokenizer(typeString, "_");
+            while (tokenizer.hasMoreTokens()) {
+                String token = tokenizer.nextToken();
+                response.append(token.substring(0, 1).toUpperCase());
+                response.append(token.substring(1).toLowerCase());
+            }
+        }
+
+        return response.toString();
+    }
+
+    /**
+     * Returns a human readable name for this KeyStore
+     *
+     * @param level the level of the KeyStore
+     * @param type the type of KeyStore
+     * @return a localized name for this KeyStore
+     */
+    public static String toDisplayableString(Level level, Type type) {
+        return Translator.R(toTranslatableString(level, type));
+    }
+
+    /**
+     * Reads the file (using the password) and uses it to create a new
+     * {@link KeyStore}. If the file does not exist and should not be created,
+     * it returns an empty but initialized KeyStore
+     *
+     * @param file the file to load information from
+     * @param password the password to unlock the KeyStore file.
+     * @return a KeyStore containing data from the file
+     */
+    private static final KeyStore createKeyStoreFromFile(File file, boolean createIfNotFound,
+            String password) throws IOException, KeyStoreException, NoSuchAlgorithmException,
+            CertificateException {
+        FileInputStream fis = null;
+        KeyStore ks = null;
+
+        try {
+            if (createIfNotFound && !file.exists()) {
+                File parent = file.getParentFile();
+                if (!parent.isDirectory() && !parent.mkdirs()) {
+                    throw new IOException("unable to create " + parent);
+                }
+                FileUtils.createRestrictedFile(file, true);
+
+                ks = KeyStore.getInstance(KEYSTORE_TYPE);
+                ks.load(null, password.toCharArray());
+                FileOutputStream fos = new FileOutputStream(file);
+                ks.store(fos, password.toCharArray());
+                fos.close();
+            }
+
+            // TODO catch exception when password is incorrect and prompt user
+
+            if (file.exists()) {
+                fis = new FileInputStream(file);
+                ks = KeyStore.getInstance(KEYSTORE_TYPE);
+                ks.load(fis, password.toCharArray());
+            } else {
+                ks = KeyStore.getInstance(KEYSTORE_TYPE);
+                ks.load(null, password.toCharArray());
+            }
+        } finally {
+            if (fis != null) {
+                fis.close();
+            }
+        }
+
+        return ks;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/MoreInfoPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/MoreInfoPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/MoreInfoPane.java	(revision 403)
@@ -0,0 +1,112 @@
+/* MoreInfoPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+/**
+ * Provides the panel for the More Info dialog. This dialog shows details about an
+ * application's signing status.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+public class MoreInfoPane extends SecurityDialogPanel {
+
+    public MoreInfoPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+        addComponents();
+    }
+
+    /**
+     * Constructs the GUI components of this panel
+     */
+    private void addComponents() {
+        ArrayList<String> details = certVerifier.getDetails();
+
+        int numLabels = details.size();
+        JPanel errorPanel = new JPanel(new GridLayout(numLabels, 1));
+        errorPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+        errorPanel.setPreferredSize(new Dimension(400, 70 * (numLabels)));
+
+        for (int i = 0; i < numLabels; i++) {
+            ImageIcon icon = null;
+            if (details.get(i).equals(R("STrustedCertificate")))
+                icon = new ImageIcon((new sun.misc.Launcher())
+                                                .getClassLoader().getResource("net/sourceforge/jnlp/resources/info-small.png"));
+            else
+                icon = new ImageIcon((new sun.misc.Launcher())
+                                                .getClassLoader().getResource("net/sourceforge/jnlp/resources/warning-small.png"));
+
+            errorPanel.add(new JLabel(htmlWrap(details.get(i)), icon, SwingConstants.LEFT));
+        }
+
+        JPanel buttonsPanel = new JPanel(new BorderLayout());
+        JButton certDetails = new JButton(R("SCertificateDetails"));
+        certDetails.addActionListener(new CertInfoButtonListener());
+        JButton close = new JButton(R("ButClose"));
+        close.addActionListener(createSetValueListener(parent, 0));
+        buttonsPanel.add(certDetails, BorderLayout.WEST);
+        buttonsPanel.add(close, BorderLayout.EAST);
+        buttonsPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
+
+        add(errorPanel, BorderLayout.NORTH);
+        add(buttonsPanel, BorderLayout.SOUTH);
+
+    }
+
+    private class CertInfoButtonListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+            SecurityDialog.showCertInfoDialog(parent.getJarSigner(),
+                                parent);
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java	(revision 403)
@@ -0,0 +1,114 @@
+/* NotAllSignedWarningPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+public class NotAllSignedWarningPane extends SecurityDialogPanel {
+
+    public NotAllSignedWarningPane(SecurityDialog x) {
+        super(x);
+        addComponents();
+    }
+
+    /**
+     * Creates the actual GUI components, and adds it to this panel
+     */
+    private void addComponents() {
+
+        String topLabelText = R("SNotAllSignedSummary");
+        String infoLabelText = R("SNotAllSignedDetail");
+        String questionLabelText = R("SNotAllSignedQuestion");
+
+        ImageIcon icon = new ImageIcon((new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/warning.png"));
+        JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT);
+        topLabel.setFont(new Font(topLabel.getFont().toString(),
+                        Font.BOLD, 12));
+        JPanel topPanel = new JPanel(new BorderLayout());
+        topPanel.setBackground(Color.WHITE);
+        topPanel.add(topLabel, BorderLayout.CENTER);
+        topPanel.setPreferredSize(new Dimension(500, 80));
+        topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        JLabel infoLabel = new JLabel(htmlWrap(infoLabelText));
+        JPanel infoPanel = new JPanel(new BorderLayout());
+        infoPanel.add(infoLabel, BorderLayout.CENTER);
+        infoPanel.setPreferredSize(new Dimension(500, 100));
+        infoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        JLabel questionLabel = new JLabel(htmlWrap(questionLabelText));
+        JPanel questionPanel = new JPanel(new BorderLayout());
+        questionPanel.add(questionLabel, BorderLayout.CENTER);
+        questionPanel.setPreferredSize(new Dimension(500, 100));
+        questionPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //run and cancel buttons
+        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+
+        JButton run = new JButton(R("ButProceed"));
+        JButton cancel = new JButton(R("ButCancel"));
+        run.addActionListener(createSetValueListener(parent, 0));
+        cancel.addActionListener(createSetValueListener(parent, 1));
+        initialFocusComponent = cancel;
+        buttonPanel.add(run);
+        buttonPanel.add(cancel);
+        buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        //all of the above
+        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+        add(topPanel);
+        add(infoPanel);
+        add(questionPanel);
+        add(buttonPanel);
+
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java	(revision 403)
@@ -0,0 +1,182 @@
+/* PasswordAuthenticationPane -- requests authentication information from users
+   Copyright (C) 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.security;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+
+/**
+ * Modal non-minimizable dialog to request http authentication credentials
+ */
+
+public class PasswordAuthenticationPane extends SecurityDialogPanel {
+
+    private final JTextField jtfUserName = new JTextField();
+    private final JPasswordField jpfPassword = new JPasswordField();
+
+    private final String host;
+    private final int port;
+    private final String prompt;
+    private final String type;
+
+    public PasswordAuthenticationPane(SecurityDialog parent, Object[] extras) {
+        super(parent);
+        host = (String) extras[0];
+        port = (Integer) extras[1];
+        prompt = (String) extras[2];
+        type = (String) extras[3];
+
+        addComponents();
+     }
+
+    /**
+     * Initialized the dialog components
+     */
+
+    public void addComponents() {
+
+        JLabel jlInfo = new JLabel("");
+        jlInfo.setText("<html>" + R("SAuthenticationPrompt", type, host, prompt)  + "</html>");
+
+        setLayout(new GridBagLayout());
+
+        JLabel jlUserName = new JLabel(R("Username"));
+        JLabel jlPassword = new JLabel(R("Password"));
+        JButton jbOK = new JButton(R("ButOk"));
+        JButton jbCancel = new JButton(R("ButCancel"));
+
+        jtfUserName.setSize(20, 10);
+        jpfPassword.setSize(20, 10);
+
+        GridBagConstraints c;
+
+        c = new GridBagConstraints();
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.gridx = 0;
+        c.gridy = 0;
+        c.gridwidth = 2;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlInfo, c);
+
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlUserName, c);
+
+        c = new GridBagConstraints();
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jtfUserName, c);
+
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        add(jlPassword, c);
+
+        c = new GridBagConstraints();
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jpfPassword, c);
+
+        c = new GridBagConstraints();
+        c.anchor = GridBagConstraints.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 70);
+        c.weightx = 0.0;
+        add(jbCancel, c);
+
+        c = new GridBagConstraints();
+        c.anchor = GridBagConstraints.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 0.0;
+        add(jbOK, c);
+
+        setMinimumSize(new Dimension(400, 150));
+        setMaximumSize(new Dimension(1024, 150));
+
+        setSize(400, 150);
+        parent.setLocationRelativeTo(null);
+        initialFocusComponent = jtfUserName;
+
+        ActionListener acceptActionListener = new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                parent.setValue(new Object[] { jtfUserName.getText(), jpfPassword.getPassword() });
+                parent.dispose();
+            }
+        };
+
+        ActionListener cancelActionListener = new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                parent.setValue(null);
+                parent.dispose();
+            }
+        };
+
+        // OK => read supplied info and pass it on
+        jbOK.addActionListener(acceptActionListener);
+
+        // Cancel => discard supplied info and pass on an empty auth
+        jbCancel.addActionListener(cancelActionListener);
+
+        // "return" key in either user or password field => OK
+        jtfUserName.addActionListener(acceptActionListener);
+        jpfPassword.addActionListener(acceptActionListener);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialog.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialog.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialog.java	(revision 403)
@@ -0,0 +1,373 @@
+/* SecurityDialog.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.security.SecurityDialogs.DialogType;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+import java.awt.event.*;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import java.util.List;
+
+/**
+ * Provides methods for showing security warning dialogs for a wide range of
+ * JNLP security issues. Note that the security dialogs should be running in the
+ * secure AppContext - this class should not be used directly from an applet or
+ * application. See {@link SecurityDialogs} for a way to show security dialogs.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+public class SecurityDialog extends JDialog {
+
+    /** The type of dialog we want to show */
+    private final DialogType dialogType;
+
+    /** The type of access that this dialog is for */
+    private final AccessType accessType;
+
+    private SecurityDialogPanel panel;
+
+    /** The application file associated with this security warning */
+    private final JNLPFile file;
+
+    private final CertVerifier certVerifier;
+
+    private final X509Certificate cert;
+
+    /** An optional String array that's only necessary when a dialog
+     * label requires some parameters (e.g. showing which address an application
+     * is trying to connect to).
+     */
+    private final Object[] extras;
+
+    /** Whether or not this object has been fully initialized */
+    private boolean initialized = false;
+
+    /**
+     * the return value of this dialog. result: 0 = Yes, 1 = No, 2 = Cancel,
+     * null = Window closed.
+     */
+    private Object value;
+
+    SecurityDialog(DialogType dialogType, AccessType accessType,
+                JNLPFile file, CertVerifier jarSigner, X509Certificate cert, Object[] extras) {
+        super();
+        this.dialogType = dialogType;
+        this.accessType = accessType;
+        this.file = file;
+        this.certVerifier = jarSigner;
+        this.cert = cert;
+        this.extras = extras;
+        initialized = true;
+
+        initDialog();
+    }
+
+    /**
+     * Construct a SecurityDialog to display some sort of access warning
+     */
+    SecurityDialog(DialogType dialogType, AccessType accessType,
+                        JNLPFile file) {
+        this(dialogType, accessType, file, null, null, null);
+    }
+
+    /**
+     * Create a SecurityDialog to display a certificate-related warning
+     */
+    SecurityDialog(DialogType dialogType, AccessType accessType,
+                        JNLPFile file, CertVerifier jarSigner) {
+        this(dialogType, accessType, file, jarSigner, null, null);
+    }
+
+    /**
+     * Create a SecurityDialog to display a certificate-related warning
+     */
+    SecurityDialog(DialogType dialogType, AccessType accessType,
+                CertVerifier certVerifier) {
+        this(dialogType, accessType, null, certVerifier, null, null);
+    }
+
+    /**
+     * Create a SecurityDialog to display some sort of access warning
+     * with more information
+     */
+    SecurityDialog(DialogType dialogType, AccessType accessType,
+                        JNLPFile file, Object[] extras) {
+        this(dialogType, accessType, file, null, null, extras);
+    }
+
+    /**
+     * Create a SecurityWarningDailog to display information about a single
+     * certificate
+     */
+    SecurityDialog(DialogType dialogType, X509Certificate c) {
+        this(dialogType, null, null, null, c, null);
+    }
+
+    /**
+     * Returns if this dialog has been fully initialized yet.
+     * @return true if this dialog has been initialized, and false otherwise.
+     */
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * Shows more information regarding jar code signing
+     *
+     * @param jarSigner the JarSigner used to verify this application
+     * @param parent the parent option pane
+     */
+    public static void showMoreInfoDialog(
+                CertVerifier jarSigner, SecurityDialog parent) {
+
+        SecurityDialog dialog =
+                        new SecurityDialog(DialogType.MORE_INFO, null, null,
+                                jarSigner);
+        dialog.setModalityType(ModalityType.APPLICATION_MODAL);
+        dialog.setVisible(true);
+        dialog.dispose();
+    }
+
+    /**
+     * Displays CertPath information in a readable table format.
+     *
+     * @param jarSigner the JarSigner used to verify this application
+     * @param parent the parent option pane
+     */
+    public static void showCertInfoDialog(CertVerifier jarSigner,
+                SecurityDialog parent) {
+        SecurityDialog dialog = new SecurityDialog(DialogType.CERT_INFO,
+                        null, null, jarSigner);
+        dialog.setLocationRelativeTo(parent);
+        dialog.setModalityType(ModalityType.APPLICATION_MODAL);
+        dialog.setVisible(true);
+        dialog.dispose();
+    }
+
+    /**
+     * Displays a single certificate's information.
+     *
+     * @param c the X509 certificate.
+     * @param parent the parent pane.
+     */
+    public static void showSingleCertInfoDialog(X509Certificate c,
+                        JDialog parent) {
+        SecurityDialog dialog = new SecurityDialog(DialogType.SINGLE_CERT_INFO, c);
+        dialog.setLocationRelativeTo(parent);
+        dialog.setModalityType(ModalityType.APPLICATION_MODAL);
+        dialog.setVisible(true);
+        dialog.dispose();
+    }
+
+    private void initDialog() {
+        setSystemLookAndFeel();
+
+        String dialogTitle = "";
+        if (dialogType == DialogType.CERT_WARNING)
+            dialogTitle = "Warning - Security";
+        else if (dialogType == DialogType.MORE_INFO)
+            dialogTitle = "More Information";
+        else if (dialogType == DialogType.CERT_INFO)
+            dialogTitle = "Details - Certificate";
+        else if (dialogType == DialogType.ACCESS_WARNING)
+            dialogTitle = "Security Warning";
+        else if (dialogType == DialogType.APPLET_WARNING)
+            dialogTitle = "Applet Warning";
+        else if (dialogType == DialogType.NOTALLSIGNED_WARNING)
+            dialogTitle = "Security Warning";
+        else if (dialogType == DialogType.AUTHENTICATION)
+            dialogTitle = "Authentication Required";
+
+        setTitle(dialogTitle);
+        setModalityType(ModalityType.MODELESS);
+
+        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+
+        installPanel();
+
+        pack();
+
+        WindowAdapter adapter = new WindowAdapter() {
+            private boolean gotFocus = false;
+
+            @Override
+            public void windowGainedFocus(WindowEvent we) {
+                // Once window gets focus, set initial focus
+                if (!gotFocus) {
+                    selectDefaultButton();
+                    gotFocus = true;
+                }
+            }
+
+            @Override
+            public void windowOpened(WindowEvent e) {
+                if (e.getSource() instanceof SecurityDialog) {
+                    SecurityDialog dialog = (SecurityDialog) e.getSource();
+                    dialog.setResizable(true);
+                    centerDialog(dialog);
+                    dialog.setValue(null);
+                }
+            }
+        };
+        addWindowListener(adapter);
+        addWindowFocusListener(adapter);
+
+    }
+
+    public AccessType getAccessType() {
+        return accessType;
+    }
+
+    public JNLPFile getFile() {
+        return file;
+    }
+
+    public CertVerifier getJarSigner() {
+        return certVerifier;
+    }
+
+    public X509Certificate getCert() {
+        return cert;
+    }
+
+    /**
+     * Adds the appropriate JPanel to this Dialog, based on {@link DialogType}.
+     */
+    private void installPanel() {
+
+        if (dialogType == DialogType.CERT_WARNING)
+            panel = new CertWarningPane(this, this.certVerifier);
+        else if (dialogType == DialogType.MORE_INFO)
+            panel = new MoreInfoPane(this, this.certVerifier);
+        else if (dialogType == DialogType.CERT_INFO)
+            panel = new CertsInfoPane(this, this.certVerifier);
+        else if (dialogType == DialogType.SINGLE_CERT_INFO)
+            panel = new SingleCertInfoPane(this, this.certVerifier);
+        else if (dialogType == DialogType.ACCESS_WARNING)
+            panel = new AccessWarningPane(this, extras, this.certVerifier);
+        else if (dialogType == DialogType.APPLET_WARNING)
+            panel = new AppletWarningPane(this, this.certVerifier);
+        else if (dialogType == DialogType.NOTALLSIGNED_WARNING)
+            panel = new NotAllSignedWarningPane(this);
+        else if (dialogType == DialogType.AUTHENTICATION)
+            panel = new PasswordAuthenticationPane(this, extras);
+
+        add(panel, BorderLayout.CENTER);
+    }
+
+    private static void centerDialog(JDialog dialog) {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = dialog.getSize();
+
+        dialog.setLocation((screen.width - dialogSize.width) / 2,
+                        (screen.height - dialogSize.height) / 2);
+    }
+
+    private void selectDefaultButton() {
+        if (panel == null) {
+            System.out.println("initial value panel is null");
+        }
+        panel.requestFocusOnDefaultButton();
+    }
+
+    protected void setValue(Object value) {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Setting value:" + value);
+        }
+        this.value = value;
+    }
+
+    public Object getValue() {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Returning value:" + value);
+        }
+        return value;
+    }
+
+    /**
+     * Called when the SecurityDialog is hidden - either because the user
+     * made a choice (Ok, Cancel, etc) or closed the window
+     */
+    @Override
+    public void dispose() {
+        notifySelectionMade();
+        super.dispose();
+    }
+
+    /**
+     * Updates the look and feel of the window to be the system look and feel
+     */
+    protected void setSystemLookAndFeel() {
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e) {
+            //don't worry if we can't.
+        }
+    }
+
+    private final List<ActionListener> listeners = new CopyOnWriteArrayList<ActionListener>();
+
+    /**
+     * Notify all the listeners that the user has made a decision using this
+     * security dialog.
+     */
+    public void notifySelectionMade() {
+        for (ActionListener listener : listeners) {
+            listener.actionPerformed(null);
+        }
+    }
+
+    /**
+     * Adds an {@link ActionListener} which will be notified if the user makes a
+     * choice using this SecurityDialog. The listener should use {@link #getValue()}
+     * to actually get the user's response.
+     */
+    public void addActionListener(ActionListener listener) {
+        listeners.add(listener);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java	(revision 403)
@@ -0,0 +1,44 @@
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.X509Certificate;
+import java.util.concurrent.Semaphore;
+
+import javax.swing.JDialog;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.security.SecurityDialogs.DialogType;
+
+/**
+ * Represents a message to the security framework to show a specific security
+ * dialog
+ */
+final class SecurityDialogMessage {
+
+    /*
+     * These fields contain information need to display the correct dialog type
+     */
+
+    public DialogType dialogType;
+    public AccessType accessType;
+    public JNLPFile file;
+    public CertVerifier certVerifier;
+    public X509Certificate certificate;
+    public Object[] extras;
+
+    /*
+     * Volatile because this is shared between threads and we dont want threads
+     * to use a cached value of this.
+     */
+    public volatile Object userResponse;
+
+    /*
+     * These two fields are used to block/unblock the application or the applet.
+     * If either of them is not null, call release() or dispose() on it to allow
+     * the application/applet to continue.
+     */
+
+    public Semaphore lock;
+    public JDialog toDispose;
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java	(revision 403)
@@ -0,0 +1,141 @@
+/* SecurityDialogMessageHandler.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import sun.awt.AppContext;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * Handles {@link SecurityDialogMessage}s and shows appropriate security
+ * dialogs.
+ * <p>
+ * In the current architecture, {@link SecurityDialog}s are shown from a
+ * different {@link AppContext} than the {@link AppContext} that asks for a
+ * security prompt. This ensures that all security prompts are isolated and
+ * their Look and Feel is not affected by the Look and Feel of the
+ * applet/application.
+ * <p>
+ * This class contains allows a client application to post a
+ * {@link SecurityDialogMessage}. When this class finds a security message in
+ * the queue, it shows a security warning to the user, and sets
+ * {@link SecurityDialogMessage#userResponse} to the appropriate value.
+ */
+public final class SecurityDialogMessageHandler implements Runnable {
+
+    /** the queue of incoming messages to show security dialogs */
+    private BlockingQueue<SecurityDialogMessage> queue = new LinkedBlockingQueue<SecurityDialogMessage>();
+
+    /**
+     * Runs the message handler loop. This waits for incoming security messages
+     * and shows a security dialog.
+     */
+    @Override
+    public void run() {
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("Starting security dialog thread");
+        }
+        while (true) {
+            try {
+                SecurityDialogMessage msg = queue.take();
+                handleMessage(msg);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    /**
+     * Handles a single {@link SecurityDialogMessage} by showing a
+     * {@link SecurityDialog}.
+     * <p>
+     * Once the user has made a choice the
+     * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and
+     * {@link SecurityDialogMessage#lock} (in not null) is released.
+     *
+     * @param message the message indicating what type of security dialog to
+     * show
+     */
+    private void handleMessage(SecurityDialogMessage message) {
+        final SecurityDialogMessage msg = message;
+
+        final SecurityDialog dialog = new SecurityDialog(message.dialogType,
+                message.accessType, message.file, message.certVerifier, message.certificate, message.extras);
+
+        dialog.addActionListener(new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                msg.userResponse = dialog.getValue();
+                /* Allow the client to continue on the other side */
+                if (msg.toDispose != null) {
+                    msg.toDispose.dispose();
+                }
+                if (msg.lock != null) {
+                    msg.lock.release();
+                }
+            }
+        });
+        dialog.setVisible(true);
+
+    }
+
+    /**
+     * Post a message to the security event queue. This message will be picked
+     * up by the security thread and used to show the appropriate security
+     * dialog.
+     * <p>
+     * Once the user has made a choice the
+     * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and
+     * {@link SecurityDialogMessage#lock} (in not null) is released.
+     *
+     * @param message indicates the type of security dialog to show
+     */
+    public void postMessage(SecurityDialogMessage message) {
+        try {
+            queue.put(message);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java	(revision 403)
@@ -0,0 +1,119 @@
+/* SecurityDialogPanel.java
+Copyright (C) 2008-2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+/**
+ * Provides a JPanel for use in JNLP warning dialogs.
+ */
+public abstract class SecurityDialogPanel extends JPanel {
+
+    protected SecurityDialog parent;
+
+    JComponent initialFocusComponent = null;
+
+    CertVerifier certVerifier = null;
+
+    public SecurityDialogPanel(SecurityDialog dialog, CertVerifier certVerifier) {
+        this.parent = dialog;
+        this.certVerifier = certVerifier;
+        this.setLayout(new BorderLayout());
+    }
+
+    public SecurityDialogPanel(SecurityDialog dialog) {
+        this.parent = dialog;
+        this.setLayout(new BorderLayout());
+    }
+
+    /**
+     * Needed to get word wrap working in JLabels.
+     */
+    protected String htmlWrap(String s) {
+        return "<html>" + s + "</html>";
+    }
+
+    /**
+     * Create an ActionListener suitable for use with buttons. When this {@link ActionListener}
+     * is invoked, it will set the value of the {@link SecurityDialog} and then dispossed.
+     *
+     * @param buttonIndex the index of the button. By convention 0 = Yes. 1 = No, 2 = Cancel
+     * @return the ActionListener instance.
+     */
+    protected ActionListener createSetValueListener(SecurityDialog dialog, int buttonIndex) {
+        return new SetValueHandler(dialog, buttonIndex);
+    }
+
+    @Override
+    public void setVisible(boolean aFlag) {
+        super.setVisible(aFlag);
+        requestFocusOnDefaultButton();
+    }
+
+    public void requestFocusOnDefaultButton() {
+        if (initialFocusComponent != null) {
+            initialFocusComponent.requestFocusInWindow();
+        }
+    }
+
+    /**
+     * Creates a handler that sets a dialog's value and then disposes it when activated
+     *
+     */
+    private static class SetValueHandler implements ActionListener {
+
+        Integer buttonIndex;
+        SecurityDialog dialog;
+
+        public SetValueHandler(SecurityDialog dialog, int buttonIndex) {
+            this.dialog = dialog;
+            this.buttonIndex = buttonIndex;
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            dialog.setValue(buttonIndex);
+            dialog.dispose();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogs.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityDialogs.java	(revision 403)
@@ -0,0 +1,367 @@
+/* SecurityDialogs.java
+   Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.Dialog.ModalityType;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.net.NetPermission;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.Semaphore;
+
+import javax.swing.JDialog;
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * A factory for showing many possible types of security warning to the user.<p>
+ *
+ * This contains all the public methods that classes outside this package should
+ * use instead of using {@link SecurityDialog} directly.
+ *
+ * All of these methods post a message to the
+ * {@link SecurityDialogMessageHandler} and block waiting for a response.
+ */
+public class SecurityDialogs {
+    /** Types of dialogs we can create */
+    public static enum DialogType {
+        CERT_WARNING,
+        MORE_INFO,
+        CERT_INFO,
+        SINGLE_CERT_INFO,
+        ACCESS_WARNING,
+        NOTALLSIGNED_WARNING,
+        APPLET_WARNING,
+        AUTHENTICATION,
+    }
+
+    /** The types of access which may need user permission. */
+    public static enum AccessType {
+        READ_FILE,
+        WRITE_FILE,
+        CREATE_DESTKOP_SHORTCUT,
+        CLIPBOARD_READ,
+        CLIPBOARD_WRITE,
+        PRINTER,
+        NETWORK,
+        VERIFIED,
+        UNVERIFIED,
+        NOTALLSIGNED,
+        SIGNING_ERROR
+    }
+
+    /**
+     * Shows a warning dialog for different types of system access (i.e. file
+     * open/save, clipboard read/write, printing, etc).
+     *
+     * @param accessType the type of system access requested.
+     * @param file the jnlp file associated with the requesting application.
+     * @return true if permission was granted by the user, false otherwise.
+     */
+    public static boolean showAccessWarningDialog(AccessType accessType, JNLPFile file) {
+        return showAccessWarningDialog(accessType, file, null);
+    }
+
+    /**
+     * Shows a warning dialog for different types of system access (i.e. file
+     * open/save, clipboard read/write, printing, etc).
+     *
+     * @param accessType the type of system access requested.
+     * @param file the jnlp file associated with the requesting application.
+     * @param extras an optional array of Strings (typically) that gets
+     * passed to the dialog labels.
+     * @return true if permission was granted by the user, false otherwise.
+     */
+    public static boolean showAccessWarningDialog(final AccessType accessType,
+            final JNLPFile file, final Object[] extras) {
+
+        if (!shouldPromptUser()) {
+            return false;
+        }
+
+        final SecurityDialogMessage message = new SecurityDialogMessage();
+
+        message.dialogType = DialogType.ACCESS_WARNING;
+        message.accessType = accessType;
+        message.file = file;
+        message.extras = extras;
+
+        Object selectedValue = getUserResponse(message);
+
+        if (selectedValue == null) {
+            return false;
+        } else if (selectedValue instanceof Integer) {
+            if (((Integer) selectedValue).intValue() == 0)
+                return true;
+            else
+                return false;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Shows a warning dialog for when the main application jars are signed,
+     * but extensions aren't
+     *
+     * @return true if permission was granted by the user, false otherwise.
+     */
+    public static boolean showNotAllSignedWarningDialog(JNLPFile file) {
+
+        if (!shouldPromptUser()) {
+            return false;
+        }
+
+        final SecurityDialogMessage message = new SecurityDialogMessage();
+        message.dialogType = DialogType.NOTALLSIGNED_WARNING;
+        message.accessType = AccessType.NOTALLSIGNED;
+        message.file = file;
+        message.extras = new Object[0];
+
+        Object selectedValue = getUserResponse(message);
+
+        if (selectedValue == null) {
+            return false;
+        } else if (selectedValue instanceof Integer) {
+            if (((Integer) selectedValue).intValue() == 0) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Shows a security warning dialog according to the specified type of
+     * access. If <code>type</code> is one of AccessType.VERIFIED or
+     * AccessType.UNVERIFIED, extra details will be available with regards
+     * to code signing and signing certificates.
+     *
+     * @param accessType the type of warning dialog to show
+     * @param file the JNLPFile associated with this warning
+     * @param jarSigner the JarSigner used to verify this application
+     */
+    public static boolean showCertWarningDialog(AccessType accessType,
+            JNLPFile file, CertVerifier jarSigner) {
+
+        if (!shouldPromptUser()) {
+            return false;
+        }
+
+        final SecurityDialogMessage message = new SecurityDialogMessage();
+        message.dialogType = DialogType.CERT_WARNING;
+        message.accessType = accessType;
+        message.file = file;
+        message.certVerifier = jarSigner;
+
+        Object selectedValue = getUserResponse(message);
+
+        if (selectedValue == null) {
+            return false;
+        } else if (selectedValue instanceof Integer) {
+            if (((Integer) selectedValue).intValue() == 0)
+                return true;
+            else
+                return false;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Present a dialog to the user asking them for authentication information,
+     * and returns the user's response. The caller must have
+     * NetPermission("requestPasswordAuthentication") for this to work.
+     *
+     * @param host The host for with authentication is needed
+     * @param port The port being accessed
+     * @param prompt The prompt (realm) as presented by the server
+     * @param type The type of server (proxy/web)
+     * @return an array of objects representing user's authentication tokens
+     * @throws SecurityException if the caller does not have the appropriate permissions.
+     */
+    public static Object[] showAuthenicationPrompt(String host, int port, String prompt, String type) {
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            NetPermission requestPermission
+                = new NetPermission("requestPasswordAuthentication");
+            sm.checkPermission(requestPermission);
+        }
+
+        final SecurityDialogMessage message = new SecurityDialogMessage();
+
+        message.dialogType = DialogType.AUTHENTICATION;
+        message.extras = new Object[] { host, port, prompt, type };
+
+        Object response = getUserResponse(message);
+        if (response == null) {
+            return null;
+        } else {
+            return (Object[]) response;
+        }
+    }
+
+    /**
+     * FIXME This is unused. Remove it?
+     * @return (0, 1, 2) => (Yes, No, Cancel)
+     */
+    public static int showAppletWarning() {
+
+        if (!shouldPromptUser()) {
+            return 2;
+        }
+
+        SecurityDialogMessage message = new SecurityDialogMessage();
+        message.dialogType = DialogType.APPLET_WARNING;
+
+        Object selectedValue = getUserResponse(message);
+
+        // result 0 = Yes, 1 = No, 2 = Cancel
+        if (selectedValue == null) {
+            return 2;
+        } else if (selectedValue instanceof Integer) {
+            return ((Integer) selectedValue).intValue();
+        } else {
+            return 2;
+        }
+    }
+
+    /**
+     * Posts the message to the SecurityThread and gets the response. Blocks
+     * until a response has been recieved. It's safe to call this from an
+     * EventDispatchThread.
+     *
+     * @param message the SecuritDialogMessage indicating what type of dialog to
+     * display
+     * @return The user's response. Can be null. The exact answer depends on the
+     * type of message, but generally an Integer corresponding to the value 0
+     * indicates success/proceed, and everything else indicates failure
+     */
+    private static Object getUserResponse(final SecurityDialogMessage message) {
+        /*
+         * Want to show a security warning, while blocking the client
+         * application. This would be easy except there is a bug in showing
+         * modal JDialogs in a different AppContext. The source EventQueue -
+         * that sends the message to the (destination) EventQueue which is
+         * supposed to actually show the dialog - must not block. If the source
+         * EventQueue blocks, the destination EventQueue stops responding. So we
+         * have a hack here to work around it.
+         */
+
+        /*
+         * If this is the event dispatch thread the use the hack
+         */
+        if (SwingUtilities.isEventDispatchThread()) {
+            /*
+             * Create a tiny modal dialog (which creates a new EventQueue for
+             * this AppContext, but blocks the original client EventQueue) and
+             * then post the message - this makes the source EventQueue continue
+             * running - but dot not allow the actual applet/application to
+             * continue processing
+             */
+            final JDialog fakeDialog = new JDialog();
+            fakeDialog.setSize(0, 0);
+            fakeDialog.setResizable(false);
+            fakeDialog.setModalityType(ModalityType.APPLICATION_MODAL);
+            fakeDialog.addWindowListener(new WindowAdapter() {
+
+                @Override
+                public void windowOpened(WindowEvent e) {
+                    message.toDispose = fakeDialog;
+                    message.lock = null;
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                        @Override
+                        public Void run() {
+                            JNLPRuntime.getSecurityDialogHandler().postMessage(message);
+                            return null;
+                        }
+                    });
+                }
+            });
+
+            /* this dialog will be disposed/hidden when the user closes the security prompt */
+            fakeDialog.setVisible(true);
+        } else {
+            /*
+             * Otherwise do it the normal way. Post a message to the security
+             * thread to make it show the security dialog. Wait until it tells us
+             * to proceed.
+             */
+            message.toDispose = null;
+            message.lock = new Semaphore(0);
+            JNLPRuntime.getSecurityDialogHandler().postMessage(message);
+
+            boolean done = false;
+            while (!done) {
+                try {
+                    message.lock.acquire();
+                    done = true;
+                } catch (InterruptedException e) {
+                    // ignore; retry
+                }
+            }
+
+        }
+
+        return message.userResponse;
+    }
+
+    /**
+     * Returns whether the current runtime configuration allows prompting user
+     * for security warnings.
+     *
+     * @return true if security warnings should be shown to the user.
+     */
+    private static boolean shouldPromptUser() {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean >() {
+            @Override
+            public Boolean run() {
+                return Boolean.valueOf(JNLPRuntime.getConfiguration()
+                        .getProperty(DeploymentConfiguration.KEY_SECURITY_PROMPT_USER));
+            }
+        });
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityUtil.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityUtil.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SecurityUtil.java	(revision 403)
@@ -0,0 +1,279 @@
+/* SecurityUtil.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+
+import net.sourceforge.jnlp.security.KeyStores.Level;
+import net.sourceforge.jnlp.security.KeyStores.Type;
+
+public class SecurityUtil {
+
+    private static final char[] password = "changeit".toCharArray();
+
+    public static String getTrustedCertsFilename() throws Exception {
+        return KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS);
+    }
+
+    public static char[] getTrustedCertsPassword() {
+        return password;
+    }
+
+    /**
+     * Extracts the CN field from a Certificate principal string. Or, if it
+     * can't find that, return the principal unmodified.
+     *
+     * This is a simple (and hence 'wrong') version. See
+     * http://www.ietf.org/rfc/rfc2253.txt for all the gory details.
+     */
+    public static String getCN(String principal) {
+
+        /*
+         * FIXME Incomplete
+         *
+         * This does not implement RFC 2253 completely
+         *
+         * Issues:
+         * - rfc2253 talks about utf8, java uses utf16.
+         * - theoretically, java should have dealt with all byte encodings
+         *   so we shouldnt even see cases like \FF
+         * - if the above is wrong, then we need to deal with cases like
+         *   \FF\FF
+         */
+
+        int start = principal.indexOf("CN=");
+        if (start == -1) {
+            return principal;
+        }
+
+        StringBuilder commonName = new StringBuilder();
+
+        boolean inQuotes = false;
+        boolean escaped = false;
+
+        /*
+         * bit 0 = high order bit. bit 1 = low order bit
+         */
+        char[] hexBits = null;
+
+        for (int i = start + 3; i < principal.length(); i++) {
+            char ch = principal.charAt(i);
+            switch (ch) {
+                case '"':
+                    if (escaped) {
+                        commonName.append(ch);
+                        escaped = false;
+                    } else {
+                        inQuotes = !inQuotes;
+                    }
+                    break;
+
+                case '\\':
+                    if (escaped) {
+                        commonName.append(ch);
+                        escaped = false;
+                    } else {
+                        escaped = true;
+                    }
+                    break;
+
+                case ',':
+                    /* fall through */
+                case ';':
+                    /* fall through */
+                case '+':
+                    if (escaped || inQuotes) {
+                        commonName.append(ch);
+                        if (escaped) {
+                            escaped = false;
+                        }
+                    } else {
+                        return commonName.toString();
+                    }
+                    break;
+
+                default:
+                    if (escaped && isHexDigit(ch)) {
+                        hexBits = new char[2];
+                        hexBits[0] = ch;
+                    } else if (hexBits != null) {
+                        if (!isHexDigit(ch)) {
+                            /* error parsing */
+                            return "";
+                        }
+                        hexBits[1] = ch;
+                        commonName.append((char) Integer.parseInt(new String(hexBits), 16));
+                        hexBits = null;
+                    } else {
+                        commonName.append(ch);
+                    }
+                    escaped = false;
+            }
+        }
+
+        return commonName.toString();
+
+    }
+
+    private static boolean isHexDigit(char ch) {
+        return ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'));
+    }
+
+    /**
+     * Checks the user's home directory to see if the trusted.certs file exists.
+     * If it does not exist, it tries to create an empty keystore.
+     * @return true if the trusted.certs file exists or a new trusted.certs
+     * was created successfully, otherwise false.
+     */
+    public static boolean checkTrustedCertsFile() throws Exception {
+
+        File certFile = new File(getTrustedCertsFilename());
+
+        //file does not exist
+        if (!certFile.isFile()) {
+            File dir = certFile.getAbsoluteFile().getParentFile();
+            boolean madeDir = false;
+            if (!dir.isDirectory()) {
+                madeDir = dir.mkdirs();
+            }
+
+            //made directory, or directory exists
+            if (madeDir || dir.isDirectory()) {
+                KeyStore ks = KeyStore.getInstance("JKS");
+                ks.load(null, password);
+                FileOutputStream fos = new FileOutputStream(certFile);
+                ks.store(fos, password);
+                fos.close();
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Returns the keystore associated with the user's trusted.certs file,
+     * or null otherwise.
+     */
+    public static KeyStore getUserKeyStore() throws Exception {
+
+        KeyStore ks = null;
+        FileInputStream fis = null;
+
+        if (checkTrustedCertsFile()) {
+
+            try {
+                File file = new File(getTrustedCertsFilename());
+                if (file.exists()) {
+                    fis = new FileInputStream(file);
+                    ks = KeyStore.getInstance("JKS");
+                    ks.load(fis, password);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw e;
+            } finally {
+                if (fis != null)
+                    fis.close();
+            }
+        }
+        return ks;
+    }
+
+    /**
+     * Returns the keystore associated with the JDK cacerts file,
+         * or null otherwise.
+     */
+    public static KeyStore getCacertsKeyStore() throws Exception {
+
+        KeyStore caks = null;
+        FileInputStream fis = null;
+
+        try {
+            File file = new File(System.getProperty("java.home")
+                                + "/lib/security/cacerts");
+            if (file.exists()) {
+                fis = new FileInputStream(file);
+                caks = KeyStore.getInstance("JKS");
+                caks.load(fis, null);
+            }
+        } catch (Exception e) {
+            caks = null;
+        } finally {
+            if (fis != null)
+                fis.close();
+        }
+
+        return caks;
+    }
+
+    /**
+     * Returns the keystore associated with the system certs file,
+     * or null otherwise.
+     */
+    public static KeyStore getSystemCertStore() throws Exception {
+
+        KeyStore caks = null;
+        FileInputStream fis = null;
+
+        try {
+            File file = new File(System.getProperty("javax.net.ssl.trustStore"));
+            String type = System.getProperty("javax.net.ssl.trustStoreType");
+            //String provider = "SUN";
+            char[] password = System.getProperty(
+                                "javax.net.ssl.trustStorePassword").toCharArray();
+            if (file.exists()) {
+                fis = new FileInputStream(file);
+                caks = KeyStore.getInstance(type);
+                caks.load(fis, password);
+            }
+        } catch (Exception e) {
+            caks = null;
+        } finally {
+            if (fis != null)
+                fis.close();
+        }
+
+        return caks;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java	(revision 403)
@@ -0,0 +1,76 @@
+/* SingleCertInfoPane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeSelectionModel;
+
+public class SingleCertInfoPane extends CertsInfoPane {
+
+    public SingleCertInfoPane(SecurityDialog x, CertVerifier certVerifier) {
+        super(x, certVerifier);
+    }
+
+    protected void buildTree() {
+        X509Certificate cert = parent.getCert();
+        String subjectString =
+                        SecurityUtil.getCN(cert.getSubjectX500Principal().getName());
+        String issuerString =
+                        SecurityUtil.getCN(cert.getIssuerX500Principal().getName());
+
+        DefaultMutableTreeNode top = new DefaultMutableTreeNode(subjectString
+                                + " (" + issuerString + ")");
+
+        tree = new JTree(top);
+        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+        tree.addTreeSelectionListener(new TreeSelectionHandler());
+    }
+
+    protected void populateTable() {
+        X509Certificate c = parent.getCert();
+        certNames = new String[1];
+        certsData = new ArrayList<String[][]>();
+        certsData.add(parseCert(c));
+        certNames[0] = SecurityUtil.getCN(c.getSubjectX500Principal().getName())
+                + " (" + SecurityUtil.getCN(c.getIssuerX500Principal().getName()) + ")";
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java	(revision 403)
@@ -0,0 +1,403 @@
+/* VariableX509TrustManager.java
+   Copyright (C) 2009 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import sun.security.util.HostnameChecker;
+import sun.security.validator.ValidatorException;
+
+import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
+
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+
+/**
+ * This class implements an X509 Trust Manager. The certificates it trusts are
+ * "variable", in the sense that it can dynamically, and temporarily support
+ * different certificates that are not in the keystore.
+ */
+
+final public class VariableX509TrustManager extends X509ExtendedTrustManager {
+
+    /** TrustManagers containing trusted CAs */
+    private X509TrustManager[] caTrustManagers = null;
+
+    /** TrustManagers containing trusted certificates */
+    private X509TrustManager[] certTrustManagers = null;
+
+    /** TrustManagers containing trusted client certificates */
+    private X509TrustManager[] clientTrustManagers = null;
+
+    private ArrayList<Certificate> temporarilyTrusted = new ArrayList<Certificate>();
+    private ArrayList<Certificate> temporarilyUntrusted = new ArrayList<Certificate>();
+
+    private static VariableX509TrustManager instance = null;
+
+    /**
+     * Constructor initializes the system, user and custom stores
+     */
+    public VariableX509TrustManager() {
+
+        /*
+         * Load TrustManagers for trusted certificates
+         */
+        try {
+            /** KeyStores containing trusted certificates */
+            KeyStore[] trustedCertKeyStores = KeyStores.getCertKeyStores();
+            certTrustManagers = new X509TrustManager[trustedCertKeyStores.length];
+
+            for (int j = 0; j < trustedCertKeyStores.length; j++) {
+                TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+                tmFactory.init(trustedCertKeyStores[j]);
+
+                // tm factory initialized, now get the managers so we can assign the X509 one
+                TrustManager[] trustManagers = tmFactory.getTrustManagers();
+
+                for (int i = 0; i < trustManagers.length; i++) {
+                    if (trustManagers[i] instanceof X509TrustManager) {
+                        certTrustManagers[j] = (X509TrustManager) trustManagers[i];
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        /*
+         * Load TrustManagers for trusted CAs
+         */
+        try {
+            /** KeyStores containing trusted CAs */
+            KeyStore[] trustedCAKeyStores = KeyStores.getCAKeyStores();
+            caTrustManagers = new X509TrustManager[trustedCAKeyStores.length];
+
+            for (int j = 0; j < caTrustManagers.length; j++) {
+                TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+                tmFactory.init(trustedCAKeyStores[j]);
+
+                // tm factory initialized, now get the managers so we can extract the X509 one
+                TrustManager[] trustManagers = tmFactory.getTrustManagers();
+
+                for (int i = 0; i < trustManagers.length; i++) {
+                    if (trustManagers[i] instanceof X509TrustManager) {
+                        caTrustManagers[j] = (X509TrustManager) trustManagers[i];
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        /*
+         * Load TrustManagers for trusted clients certificates
+         */
+        try {
+            KeyStore[] clientKeyStores = KeyStores.getClientKeyStores();
+            clientTrustManagers = new X509TrustManager[clientKeyStores.length];
+
+            for (int j = 0; j < clientTrustManagers.length; j++) {
+                TrustManagerFactory tmFactory = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+                tmFactory.init(clientKeyStores[j]);
+
+                // tm factory initialized, now get the managers so we can extract the X509 one
+                TrustManager[] trustManagers = tmFactory.getTrustManagers();
+
+                for (int i = 0; i < trustManagers.length; i++) {
+                    if (trustManagers[i] instanceof X509TrustManager) {
+                        clientTrustManagers[j] = (X509TrustManager) trustManagers[i];
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Check if client is trusted (no support for custom here, only system/user)
+     */
+    public void checkClientTrusted(X509Certificate[] chain, String authType,
+                                   String hostName, String algorithm)
+            throws CertificateException {
+
+        boolean trusted = false;
+        ValidatorException savedException = null;
+        for (int i = 0; i < clientTrustManagers.length; i++) {
+            try {
+                clientTrustManagers[i].checkClientTrusted(chain, authType);
+                trusted = true;
+                break;
+            } catch (ValidatorException caex) {
+                savedException = caex;
+            }
+        }
+        if (trusted) {
+            return;
+        }
+
+        throw savedException;
+    }
+
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
+            throws CertificateException {
+        checkClientTrusted(chain, authType, null, null);
+    }
+
+    public void checkServerTrusted(X509Certificate[] chain, String authType,
+                                   String hostName, String algorithm)
+            throws CertificateException {
+        checkServerTrusted(chain, authType, hostName, false);
+    }
+
+    public void checkServerTrusted(X509Certificate[] chain, String authType)
+            throws CertificateException {
+        checkServerTrusted(chain, authType, null, null);
+    }
+
+    /**
+     * Check if the server is trusted
+     *
+     * @param chain The cert chain
+     * @param authType The auth type algorithm
+     * @param checkOnly Whether to "check only" i.e. no user prompt, or to prompt for permission
+     */
+    public synchronized void checkServerTrusted(X509Certificate[] chain,
+                             String authType, String hostName,
+                             boolean checkOnly) throws CertificateException {
+        CertificateException ce = null;
+        boolean trusted = true;
+        boolean CNMatched = true;
+
+        try {
+            checkAllManagers(chain, authType);
+        } catch (CertificateException e) {
+            trusted = false;
+            ce = e;
+        }
+
+        // If the certificate is not explicitly trusted, we
+        // need to prompt the user
+        if (!isExplicitlyTrusted(chain, authType)) {
+
+            if (hostName == null) {
+                CNMatched = false;
+            } else {
+                try {
+                    HostnameChecker checker = HostnameChecker
+                            .getInstance(HostnameChecker.TYPE_TLS);
+
+                    checker.match(hostName, chain[0]); // only need to match @ 0 for
+                                                       // CN
+
+                } catch (CertificateException e) {
+                    CNMatched = false;
+                    ce = e;
+                }
+            }
+        }
+
+        if (!trusted || !CNMatched) {
+            if (checkOnly) {
+                throw ce;
+            } else {
+                if (!isTemporarilyUntrusted(chain[0])) {
+                    boolean b = askUser(chain, authType, trusted, CNMatched, hostName);
+
+                    if (b) {
+                        temporarilyTrust(chain[0]);
+                    } else {
+                        temporarilyUntrust(chain[0]);
+                    }
+                }
+
+                checkAllManagers(chain, authType);
+            }
+        }
+    }
+
+    /**
+     * Check system, user and custom trust manager
+     */
+    private void checkAllManagers(X509Certificate[] chain, String authType) throws CertificateException {
+        // first try CA TrustManagers
+        boolean trusted = false;
+        ValidatorException savedException = null;
+        for (int i = 0; i < caTrustManagers.length; i++) {
+            try {
+                caTrustManagers[i].checkServerTrusted(chain, authType);
+                trusted = true;
+                break;
+            } catch (ValidatorException caex) {
+                savedException = caex;
+            }
+        }
+        if (trusted) {
+            return;
+        }
+
+        // then try certificate TrustManagers
+        for (int i = 0; i < certTrustManagers.length; i++) {
+            try {
+                certTrustManagers[i].checkServerTrusted(chain, authType);
+                trusted = true;
+                break;
+            } catch (ValidatorException caex) {
+                savedException = caex;
+            }
+        }
+        if (trusted) {
+            return;
+        }
+
+        // finally check temp trusted certs
+        if (!temporarilyTrusted.contains(chain[0])) {
+            if (savedException == null) {
+                // System.out.println("IMPOSSIBLE!");
+                throw new ValidatorException(ValidatorException.T_SIGNATURE_ERROR, chain[0]);
+            }
+            throw savedException;
+        }
+
+    }
+
+    /**
+     * Return if the user explicitly trusted this i.e. in userTrustManager or temporarilyTrusted
+     */
+    private boolean isExplicitlyTrusted(X509Certificate[] chain, String authType) {
+        boolean explicitlyTrusted = false;
+
+        for (int i = 0; i < certTrustManagers.length; i++) {
+            try {
+                certTrustManagers[i].checkServerTrusted(chain, authType);
+                explicitlyTrusted = true;
+                break;
+            } catch (ValidatorException uex) {
+                if (temporarilyTrusted.contains(chain[0])) {
+                    explicitlyTrusted = true;
+                    break;
+                }
+            } catch (CertificateException ce) {
+                // not explicitly trusted
+            }
+        }
+
+        return explicitlyTrusted;
+    }
+
+    public X509Certificate[] getAcceptedIssuers() {
+        List<X509Certificate> issuers = new ArrayList<X509Certificate>();
+
+        for (int i = 0; i < caTrustManagers.length; i++) {
+            issuers.addAll(Arrays.asList(caTrustManagers[i].getAcceptedIssuers()));
+        }
+
+        return issuers.toArray(new X509Certificate[issuers.size()]);
+    }
+
+    /**
+     * Temporarily untrust the given cert - do not ask the user to trust this
+     * certificate again
+     *
+     * @param c The certificate to trust
+     */
+    private void temporarilyUntrust(Certificate c) {
+        temporarilyUntrusted.add(c);
+    }
+
+    /**
+     * Was this certificate explicitly untrusted by user?
+     *
+     * @param c the certificate
+     * @return true if the user was presented with this certificate and chose
+     * not to trust it
+     */
+    private boolean isTemporarilyUntrusted(Certificate c) {
+        if (temporarilyUntrusted.contains(c)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Temporarily trust the given cert (runtime)
+     *
+     * @param c The certificate to trust
+     */
+    private void temporarilyTrust(Certificate c) {
+        temporarilyTrusted.add(c);
+    }
+
+    /**
+     * Ask user if the certificate should be trusted
+     *
+     * @param chain The certificate chain
+     * @param authType The authentication algorithm
+     * @return user's response
+     */
+    private boolean askUser(X509Certificate[] chain, String authType,
+                            boolean isTrusted, boolean hostMatched,
+                            String hostName) {
+        return SecurityDialogs.showCertWarningDialog(
+                        AccessType.UNVERIFIED, null,
+                        new HttpsCertVerifier(this, chain, authType,
+                                              isTrusted, hostMatched,
+                                              hostName));
+    }
+
+    /**
+     * Return an instance of this singleton
+     *
+     * @return The instance
+     */
+    public static VariableX509TrustManager getInstance() {
+        if (instance == null)
+            instance = new VariableX509TrustManager();
+
+        return instance;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java	(revision 403)
@@ -0,0 +1,500 @@
+/* CertificatePane.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security.viewer;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.table.DefaultTableModel;
+
+import net.sourceforge.jnlp.security.CertificateUtils;
+import net.sourceforge.jnlp.security.KeyStores;
+import net.sourceforge.jnlp.security.SecurityUtil;
+import net.sourceforge.jnlp.security.SecurityDialog;
+import net.sourceforge.jnlp.security.KeyStores.Level;
+import net.sourceforge.jnlp.util.FileUtils;
+
+public class CertificatePane extends JPanel {
+
+    /**
+     * The certificates stored in the certificates file.
+     */
+    private ArrayList<X509Certificate> certs = null;
+
+    private static final Dimension TABLE_DIMENSION = new Dimension(500, 200);
+
+    /**
+     * "Issued To" and "Issued By" string pairs for certs.
+     */
+    private String[][] issuedToAndBy = null;
+    private final String[] columnNames = { R("CVIssuedTo"), R("CVIssuedBy") };
+
+    private final CertificateType[] certificateTypes = new CertificateType[] {
+            new CertificateType(KeyStores.Type.CA_CERTS),
+            new CertificateType(KeyStores.Type.JSSE_CA_CERTS),
+            new CertificateType(KeyStores.Type.CERTS),
+            new CertificateType(KeyStores.Type.JSSE_CERTS),
+        };
+
+    JTabbedPane tabbedPane;
+    private final JTable userTable;
+    private final JTable systemTable;
+    private JComboBox certificateTypeCombo;
+    private KeyStores.Type currentKeyStoreType;
+    private KeyStores.Level currentKeyStoreLevel;
+
+    /** JComponents that should be disbled for system store */
+    private final List<JComponent> disableForSystem;
+
+    private JDialog parent;
+    private JComponent defaultFocusComponent = null;
+
+    /**
+     * The Current KeyStore. Only one table/tab is visible for interaction to
+     * the user. This KeyStore corresponds to that.
+     */
+    private KeyStore keyStore = null;
+
+    public CertificatePane(JDialog parent) {
+        super();
+        this.parent = parent;
+
+        userTable = new JTable(null);
+        systemTable = new JTable(null);
+        disableForSystem = new ArrayList<JComponent>();
+
+        addComponents();
+
+        currentKeyStoreType = ((CertificateType) (certificateTypeCombo.getSelectedItem())).getType();
+        if (tabbedPane.getSelectedIndex() == 0) {
+            currentKeyStoreLevel = Level.USER;
+        } else {
+            currentKeyStoreLevel = Level.SYSTEM;
+        }
+
+        repopulateTables();
+    }
+
+    /**
+     * Reads the user's trusted.cacerts keystore.
+     */
+    private void initializeKeyStore() {
+        try {
+            keyStore = KeyStores.getKeyStore(currentKeyStoreLevel, currentKeyStoreType);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //create the GUI here.
+    protected void addComponents() {
+
+        JPanel main = new JPanel(new BorderLayout());
+
+        JPanel certificateTypePanel = new JPanel(new BorderLayout());
+        certificateTypePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+        JLabel certificateTypeLabel = new JLabel(R("CVCertificateType"));
+
+        certificateTypeCombo = new JComboBox(certificateTypes);
+        certificateTypeCombo.addActionListener(new CertificateTypeListener());
+
+        certificateTypePanel.add(certificateTypeLabel, BorderLayout.LINE_START);
+        certificateTypePanel.add(certificateTypeCombo, BorderLayout.CENTER);
+
+        JPanel tablePanel = new JPanel(new BorderLayout());
+
+        // User Table
+        DefaultTableModel userTableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+        userTable.setModel(userTableModel);
+        userTable.getTableHeader().setReorderingAllowed(false);
+        userTable.setFillsViewportHeight(true);
+        JScrollPane userTablePane = new JScrollPane(userTable);
+        userTablePane.setPreferredSize(TABLE_DIMENSION);
+        userTablePane.setSize(TABLE_DIMENSION);
+        userTablePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        // System Table
+        DefaultTableModel systemTableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+        systemTable.setModel(systemTableModel);
+        systemTable.getTableHeader().setReorderingAllowed(false);
+        systemTable.setFillsViewportHeight(true);
+        JScrollPane systemTablePane = new JScrollPane(systemTable);
+        systemTablePane.setPreferredSize(TABLE_DIMENSION);
+        systemTablePane.setSize(TABLE_DIMENSION);
+        systemTablePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+        tabbedPane = new JTabbedPane();
+        tabbedPane.addTab(R("CVUser"), userTablePane);
+        tabbedPane.addTab(R("CVSystem"), systemTablePane);
+        tabbedPane.addChangeListener(new TabChangeListener());
+
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+
+        String[] buttonNames = { R("CVImport"), R("CVExport"), R("CVRemove"), R("CVDetails") };
+        char[] buttonMnemonics = { KeyEvent.VK_I,
+                                                                        KeyEvent.VK_E,
+                                                                        KeyEvent.VK_M,
+                                                                        KeyEvent.VK_D };
+        ActionListener[] listeners = { new ImportButtonListener(),
+                                                                                new ExportButtonListener(),
+                                                                                new RemoveButtonListener(),
+                                                                                new DetailsButtonListener() };
+        JButton button;
+
+        //get the max width
+        int maxWidth = 0;
+        for (int i = 0; i < buttonNames.length; i++) {
+            button = new JButton(buttonNames[i]);
+            maxWidth = Math.max(maxWidth, button.getMinimumSize().width);
+        }
+
+        for (int i = 0; i < buttonNames.length; i++) {
+            button = new JButton(buttonNames[i]);
+            button.setMnemonic(buttonMnemonics[i]);
+            button.addActionListener(listeners[i]);
+            button.setSize(maxWidth, button.getSize().height);
+            // import and remove buttons
+            if (i == 0 || i == 2) {
+                disableForSystem.add(button);
+            }
+            buttonPanel.add(button);
+        }
+
+        tablePanel.add(tabbedPane, BorderLayout.CENTER);
+        tablePanel.add(buttonPanel, BorderLayout.SOUTH);
+
+        main.add(certificateTypePanel, BorderLayout.NORTH);
+        main.add(tablePanel, BorderLayout.CENTER);
+
+        if (parent != null) {
+            JPanel closePanel = new JPanel(new BorderLayout());
+            closePanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7));
+            JButton closeButton = new JButton(R("ButClose"));
+            closeButton.addActionListener(new CloseButtonListener());
+            defaultFocusComponent = closeButton;
+            closePanel.add(closeButton, BorderLayout.EAST);
+            main.add(closePanel, BorderLayout.SOUTH);
+        }
+
+        setLayout(new GridLayout(0,1));
+        add(main);
+
+    }
+
+    /**
+     * Read in the optionPane's keystore to issuedToAndBy.
+     */
+    private void readKeyStore() {
+
+        Enumeration<String> aliases = null;
+        certs = new ArrayList<X509Certificate>();
+        try {
+
+            //Get all of the X509Certificates and put them into an ArrayList
+            aliases = keyStore.aliases();
+            while (aliases.hasMoreElements()) {
+                Certificate c = keyStore.getCertificate(aliases.nextElement());
+                if (c instanceof X509Certificate)
+                    certs.add((X509Certificate) c);
+            }
+
+            //get the publisher and root information
+            issuedToAndBy = new String[certs.size()][2];
+            for (int i = 0; i < certs.size(); i++) {
+                X509Certificate c = certs.get(i);
+                issuedToAndBy[i][0] =
+                                        SecurityUtil.getCN(c.getSubjectX500Principal().getName());
+                issuedToAndBy[i][1] =
+                                        SecurityUtil.getCN(c.getIssuerX500Principal().getName());
+            }
+        } catch (Exception e) {
+            //TODO
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Re-reads the certs file and repopulates the JTable. This is typically
+     * called after a certificate was deleted from the keystore.
+     */
+    private void repopulateTables() {
+        initializeKeyStore();
+        readKeyStore();
+        DefaultTableModel tableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+
+        userTable.setModel(tableModel);
+
+        tableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+        systemTable.setModel(tableModel);
+    }
+
+    public void focusOnDefaultButton() {
+        if (defaultFocusComponent != null) {
+            defaultFocusComponent.requestFocusInWindow();
+        }
+    }
+
+    /** Allows storing KeyStores.Types in a JComponent */
+    private static class CertificateType {
+        private final KeyStores.Type type;
+
+        public CertificateType(KeyStores.Type type) {
+            this.type = type;
+        }
+
+        public KeyStores.Type getType() {
+            return type;
+        }
+
+        public String toString() {
+            return KeyStores.toDisplayableString(null, type);
+        }
+    }
+
+    /** Invoked when a user selects a different certificate type */
+    private class CertificateTypeListener implements ActionListener {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            JComboBox source = (JComboBox) e.getSource();
+            CertificateType type = (CertificateType) source.getSelectedItem();
+            currentKeyStoreType = type.getType();
+            repopulateTables();
+        }
+    }
+
+    /**
+     * Invoked when a user selects a different tab (switches from user to system
+     * or vice versa). Changes the currentKeyStore Enables or disables buttons.
+     */
+    private class TabChangeListener implements ChangeListener {
+        @Override
+        public void stateChanged(ChangeEvent e) {
+            JTabbedPane source = (JTabbedPane) e.getSource();
+            switch (source.getSelectedIndex()) {
+                case 0:
+                    currentKeyStoreLevel = Level.USER;
+                    for (JComponent component : disableForSystem) {
+                        component.setEnabled(true);
+                    }
+                    break;
+                case 1:
+                    currentKeyStoreLevel = Level.SYSTEM;
+                    for (JComponent component : disableForSystem) {
+                        component.setEnabled(false);
+                    }
+                    break;
+            }
+            repopulateTables();
+
+        }
+    }
+
+    private class ImportButtonListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+
+            JFileChooser chooser = new JFileChooser();
+            int returnVal = chooser.showOpenDialog(parent);
+            if (returnVal == JFileChooser.APPROVE_OPTION) {
+                try {
+                    KeyStore ks = keyStore;
+                    CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks);
+                    File keyStoreFile = new File(KeyStores
+                                        .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType));
+                    if (!keyStoreFile.isFile()) {
+                        FileUtils.createRestrictedFile(keyStoreFile, true);
+                    }
+
+                    OutputStream os = new FileOutputStream(keyStoreFile);
+                    try {
+                        ks.store(os, KeyStores.getPassword());
+                    } finally {
+                        os.close();
+                    }
+                    repopulateTables();
+                } catch (Exception ex) {
+                    // TODO: handle exception
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private class ExportButtonListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+
+            JTable table = null;
+            if (currentKeyStoreLevel == Level.USER) {
+                table = userTable;
+            } else {
+                table = systemTable;
+            }
+
+            //For now, let's just export in -rfc mode as keytool does.
+            //we'll write to a file the exported certificate.
+
+            try {
+                int selectedRow = table.getSelectedRow();
+                if (selectedRow != -1) {
+                    JFileChooser chooser = new JFileChooser();
+                    int returnVal = chooser.showOpenDialog(parent);
+                    if (returnVal == JFileChooser.APPROVE_OPTION) {
+                        String alias = keyStore.getCertificateAlias(certs
+                                                        .get(selectedRow));
+                        if (alias != null) {
+                            Certificate c = keyStore.getCertificate(alias);
+                            PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
+                            CertificateUtils.dump(c, ps);
+                            repopulateTables();
+                        }
+                    }
+                }
+            } catch (Exception ex) {
+                // TODO
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    private class RemoveButtonListener implements ActionListener {
+
+        /**
+         * Removes a certificate from the keyStore and writes changes to disk.
+         */
+        public void actionPerformed(ActionEvent e) {
+
+            JTable table = null;
+            if (currentKeyStoreLevel == Level.USER) {
+                table = userTable;
+            } else {
+                table = systemTable;
+            }
+            try {
+                int selectedRow = table.getSelectedRow();
+
+                if (selectedRow != -1) {
+                    String alias = keyStore.getCertificateAlias(certs.get(selectedRow));
+                    if (alias != null) {
+
+                        int i = JOptionPane.showConfirmDialog(parent,
+                                                        R("CVRemoveConfirmMessage"),
+                                                        R("CVRemoveConfirmTitle"),
+                                                        JOptionPane.YES_NO_OPTION);
+                        if (i == 0) {
+                            keyStore.deleteEntry(alias);
+                            File keyStoreFile = new File(KeyStores
+                                                        .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType));
+                            if (!keyStoreFile.isFile()) {
+                                FileUtils.createRestrictedFile(keyStoreFile, true);
+                            }
+                            FileOutputStream fos = new FileOutputStream(keyStoreFile);
+                            keyStore.store(fos, KeyStores.getPassword());
+                            fos.close();
+                        }
+                    }
+                    repopulateTables();
+                }
+            } catch (Exception ex) {
+                // TODO
+                ex.printStackTrace();
+            }
+
+        }
+    }
+
+    private class DetailsButtonListener implements ActionListener {
+
+        /**
+         * Shows the details of a trusted certificate.
+         */
+        public void actionPerformed(ActionEvent e) {
+
+            JTable table = null;
+            if (currentKeyStoreLevel == Level.USER) {
+                table = userTable;
+            } else {
+                table = systemTable;
+            }
+
+            int selectedRow = table.getSelectedRow();
+            if (selectedRow != -1 && selectedRow >= 0) {
+                X509Certificate c = certs.get(selectedRow);
+                SecurityDialog.showSingleCertInfoDialog(c, parent);
+            }
+        }
+    }
+
+    private class CloseButtonListener implements ActionListener {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            parent.dispose();
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java	(revision 403)
@@ -0,0 +1,124 @@
+/* CertificateViewer.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security.viewer;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JDialog;
+import javax.swing.UIManager;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class CertificateViewer extends JDialog {
+
+    private boolean initialized = false;
+    private static final String dialogTitle = R("CVCertificateViewer");
+
+    CertificatePane panel;
+
+    public CertificateViewer() {
+        super((Frame) null, dialogTitle, true);
+
+        Container contentPane = getContentPane();
+        contentPane.setLayout(new BorderLayout());
+
+        panel = new CertificatePane(this);
+
+        add(panel);
+
+        pack();
+
+        WindowAdapter adapter = new WindowAdapter() {
+            private boolean gotFocus = false;
+
+            public void windowGainedFocus(WindowEvent we) {
+                // Once window gets focus, set initial focus
+                if (!gotFocus) {
+                    panel.focusOnDefaultButton();
+                    gotFocus = true;
+                }
+            }
+        };
+        addWindowFocusListener(adapter);
+
+        initialized = true;
+    }
+
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    private void centerDialog() {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = getSize();
+
+        setLocation((screen.width - dialogSize.width) / 2,
+                        (screen.height - dialogSize.height) / 2);
+    }
+
+    public static void showCertificateViewer() throws Exception {
+        JNLPRuntime.initialize(true);
+        setSystemLookAndFeel();
+
+        CertificateViewer cv = new CertificateViewer();
+        cv.setResizable(true);
+        cv.centerDialog();
+        cv.setVisible(true);
+        cv.dispose();
+    }
+
+    private static void setSystemLookAndFeel() {
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e) {
+            // don't worry if we can't.
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        CertificateViewer.showCertificateViewer();
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java	(revision 403)
@@ -0,0 +1,49 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import javax.jnlp.SingleInstanceService;
+
+import net.sourceforge.jnlp.JNLPFile;
+
+/**
+ * Extends SingleInstanceService to provide a few additional methods that are
+ * required to initialize SingleInstanceService and check things. These methods
+ * are not exposed publicly
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+interface ExtendedSingleInstanceService extends SingleInstanceService {
+
+    /**
+     * Check if the instance identified by this jnlp file is already running
+     *
+     * @param jnlpFile The JNLPFile that specifies the application
+     *
+     * @throws InstanceExistsException if an instance of this application
+     *         already exists
+     *
+     */
+    void checkSingleInstanceRunning(JNLPFile jnlpFile);
+
+    /**
+     * Start a single instance service based on the current application
+     */
+    void initializeSingleInstance();
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/InstanceExistsException.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/InstanceExistsException.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/InstanceExistsException.java	(revision 403)
@@ -0,0 +1,35 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+/**
+ *
+ * This class represents an exception indicating that an application instance
+ * already exists for this jnlp file
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+public class InstanceExistsException extends RuntimeException {
+
+    private static final long serialVersionUID = 7950552292795498272L;
+
+    public InstanceExistsException(String message) {
+        super(message);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ServiceUtil.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ServiceUtil.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/ServiceUtil.java	(revision 403)
@@ -0,0 +1,311 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.jnlp.BasicService;
+import javax.jnlp.ClipboardService;
+import javax.jnlp.DownloadService;
+import javax.jnlp.ExtensionInstallerService;
+import javax.jnlp.FileOpenService;
+import javax.jnlp.FileSaveService;
+import javax.jnlp.PersistenceService;
+import javax.jnlp.PrintService;
+import javax.jnlp.ServiceManager;
+import javax.jnlp.SingleInstanceService;
+import javax.jnlp.UnavailableServiceException;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityDialogs;
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+
+/**
+ * Provides static methods to interact useful for using the JNLP
+ * services.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ * @version $Revision: 1.8 $
+ */
+public class ServiceUtil {
+
+    /**
+     * Returns the BasicService reference, or null if the service is
+     * unavailable.
+     */
+    public static BasicService getBasicService() {
+        return (BasicService) getService("javax.jnlp.BasicService");
+    }
+
+    /**
+     * Returns the ClipboardService reference, or null if the service is
+     * unavailable.
+     */
+    public static ClipboardService getClipboardService() {
+        return (ClipboardService) getService("javax.jnlp.ClipboardService");
+    }
+
+    /**
+     * Returns the DownloadService reference, or null if the service is
+     * unavailable.
+     */
+    public static DownloadService getDownloadService() {
+        return (DownloadService) getService("javax.jnlp.DownloadService");
+    }
+
+    /**
+     * Returns the ExtensionInstallerService reference, or null if the service is
+     * unavailable.
+     */
+    public static ExtensionInstallerService getExtensionInstallerService() {
+        return (ExtensionInstallerService) getService("javax.jnlp.ExtensionInstallerService");
+    }
+
+    /**
+     * Returns the FileOpenService reference, or null if the service is
+     * unavailable.
+     */
+    public static FileOpenService getFileOpenService() {
+        return (FileOpenService) getService("javax.jnlp.FileOpenService");
+    }
+
+    /**
+     * Returns the FileSaveService reference, or null if the service is
+     * unavailable.
+     */
+    public static FileSaveService getFileSaveService() {
+        return (FileSaveService) getService("javax.jnlp.FileSaveService");
+    }
+
+    /**
+     * Returns the PersistenceService reference, or null if the service is
+     * unavailable.
+     */
+    public static PersistenceService getPersistenceService() {
+        return (PersistenceService) getService("javax.jnlp.PersistenceService");
+    }
+
+    /**
+     * Returns the PrintService reference, or null if the service is
+     * unavailable.
+     */
+    public static PrintService getPrintService() {
+        return (PrintService) getService("javax.jnlp.PrintService");
+    }
+
+    /**
+     * Returns the SingleInstanceService reference, or null if the service is
+     * unavailable.
+     */
+    public static SingleInstanceService getSingleInstanceService() {
+        return (SingleInstanceService) getService("javax.jnlp.SingleInstanceService");
+    }
+
+    /**
+     * Checks that this application (represented by the jnlp) isnt already running
+     * @param jnlpFile the {@link JNLPFile} that specifies the application
+     *
+     * @throws InstanceExistsException if an instance of this application already exists
+     */
+    public static void checkExistingSingleInstance(JNLPFile jnlpFile) {
+        ExtendedSingleInstanceService esis = (ExtendedSingleInstanceService) getSingleInstanceService();
+        esis.checkSingleInstanceRunning(jnlpFile);
+    }
+
+    /**
+     * Returns the service, or null instead of an UnavailableServiceException
+     */
+    private static Object getService(String name) {
+        try {
+            return ServiceManager.lookup(name);
+        } catch (UnavailableServiceException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Creates a Proxy object implementing the specified interface
+     * when makes all calls in the security context of the system
+     * classes (ie, AllPermissions).  This means that the services
+     * must be more than extremely careful in the operations they
+     * perform.
+     */
+    static Object createPrivilegedProxy(Class iface, final Object receiver) {
+        return java.lang.reflect.Proxy.newProxyInstance(XServiceManagerStub.class.getClassLoader(),
+                new Class[] { iface },
+                new PrivilegedHandler(receiver));
+    }
+
+    /**
+     * calls the object's method using privileged access
+     */
+    private static class PrivilegedHandler implements InvocationHandler {
+        private final Object receiver;
+
+        PrivilegedHandler(Object receiver) {
+            this.receiver = receiver;
+        }
+
+        public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("call privileged method: " + method.getName());
+                if (args != null)
+                    for (int i = 0; i < args.length; i++)
+                        System.err.println("           arg: " + args[i]);
+            }
+
+            PrivilegedExceptionAction<Object> invoker = new PrivilegedExceptionAction<Object>() {
+                public Object run() throws Exception {
+                    return method.invoke(receiver, args);
+                }
+            };
+
+            try {
+                Object result = AccessController.doPrivileged(invoker);
+
+                if (JNLPRuntime.isDebug())
+                    System.err.println("        result: " + result);
+
+                return result;
+            } catch (PrivilegedActionException e) {
+                // Any exceptions thrown by the actual methods are wrapped by a
+                // InvocationTargetException, which is further wrapped by the
+                // PrivilegedActionException. Lets unwrap them to make the
+                // proxy transparent to the callers
+                if (e.getCause() instanceof InvocationTargetException) {
+                    throw e.getCause().getCause();
+                } else {
+                    throw e.getCause();
+                }
+            }
+
+        }
+    };
+
+    /**
+     * Returns whether the app requesting a JNLP service has the right permissions.
+     * If it doesn't, user is prompted for permissions. This method should only be
+     * used for JNLP API related permissions.
+     *
+     * @param type the type of access being requested
+     * @param extras extra Strings (usually) that are passed to the dialog for
+     * message formatting.
+     * @return true if the access was granted, false otherwise.
+     */
+    public static boolean checkAccess(AccessType type, Object... extras) {
+        return checkAccess(null, type, extras);
+    }
+
+    /**
+     * Returns whether the app requesting a JNLP service has the right permissions.
+     * If it doesn't, user is prompted for permissions. This method should only be
+     * used for JNLP API related permissions.
+     *
+     * @param app the application which is requesting the check. If null, the current
+     * application is used.
+     * @param type the type of access being requested
+     * @param extras extra Strings (usually) that are passed to the dialog for
+     * message formatting.
+     * @return true if the access was granted, false otherwise.
+     */
+    public static boolean checkAccess(ApplicationInstance app, AccessType type,
+                Object... extras) {
+
+        if (app == null)
+            app = JNLPRuntime.getApplication();
+
+        boolean codeTrusted = true;
+
+        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+
+        for (int i = 0; i < stack.length; i++) {
+
+            Class c = null;
+
+            try {
+                c = Class.forName(stack[i].getClassName());
+            } catch (Exception e1) {
+                try {
+                    c = Class.forName(stack[i].getClassName(), false, app.getClassLoader());
+                } catch (Exception e2) {
+                    System.err.println(e2.getMessage());
+                }
+            }
+
+            // Everything up to the desired class/method must be trusted
+            if (c == null || // class not found
+                    (c.getProtectionDomain().getCodeSource() != null && // class is not in bootclasspath
+                    c.getProtectionDomain().getCodeSource().getCodeSigners() == null) // class is trusted
+            ) {
+                codeTrusted = false;
+            }
+        }
+
+        if (!codeTrusted) {
+
+            if (!shouldPromptUser()) {
+                return false;
+            }
+
+            final AccessType tmpType = type;
+            final Object[] tmpExtras = extras;
+            final ApplicationInstance tmpApp = app;
+
+            //We need to do this to allow proper icon loading for unsigned
+            //applets, otherwise permissions won't be granted to load icons
+            //from resources.jar.
+            Boolean b = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    boolean b = SecurityDialogs.showAccessWarningDialog(tmpType,
+                                tmpApp.getJNLPFile(), tmpExtras);
+                    return Boolean.valueOf(b);
+                }
+            });
+
+            return b.booleanValue();
+        }
+
+        return true; //allow
+    }
+
+    /**
+     * Returns whether the current runtime configuration allows prompting the
+     * user for JNLP permissions.
+     *
+     * @return true if the user should be prompted for JNLP API related permissions.
+     */
+    private static boolean shouldPromptUser() {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean >() {
+            @Override
+            public Boolean run() {
+                return Boolean.valueOf(JNLPRuntime.getConfiguration()
+                        .getProperty(DeploymentConfiguration.KEY_SECURITY_PROMPT_USER_FOR_JNLP));
+            }
+        });
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java	(revision 403)
@@ -0,0 +1,199 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * This class represents a Lock for single instance jnlp applications
+ *
+ * The lock is per-session, per user.
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ */
+class SingleInstanceLock {
+
+    JNLPFile jnlpFile;
+    File lockFile = null;
+
+    public static final int INVALID_PORT = Integer.MIN_VALUE;
+
+    int port = INVALID_PORT;
+
+    /**
+     * Create an object to manage the instance lock for the specified JNLP file.
+     *
+     * @param jnlpFile the jnlpfile to create the lock for
+     */
+    public SingleInstanceLock(JNLPFile jnlpFile) {
+        this.jnlpFile = jnlpFile;
+        lockFile = getLockFile();
+
+    }
+
+    /**
+     * Create/overwrite the instance lock for the jnlp file.
+     *
+     * @param localPort the network port for the lock
+     * @throws IOException on any io problems
+     */
+    public void createWithPort(int localPort) throws IOException {
+
+        FileUtils.createRestrictedFile(lockFile, true);
+        BufferedWriter lockFileWriter = new BufferedWriter(new FileWriter(lockFile, false));
+        lockFileWriter.write(String.valueOf(localPort));
+        lockFileWriter.newLine();
+        lockFileWriter.flush();
+        lockFileWriter.close();
+
+    }
+
+    /**
+     * Returns true if the lock if valid. That is, the lock exists, and port it
+     * points to is listening for incoming messages.
+     */
+    public boolean isValid() {
+        return (exists() && getPort() != INVALID_PORT && !isPortFree(getPort()));
+    }
+
+    /**
+     * Returns the port in this lock file.
+     */
+    public int getPort() {
+        if (!exists()) {
+            return INVALID_PORT;
+        }
+
+        try {
+            parseFile();
+        } catch (NumberFormatException e) {
+            port = INVALID_PORT;
+        } catch (IOException e) {
+            port = INVALID_PORT;
+        }
+        return port;
+
+    }
+
+    /**
+     * Returns true if the lock file already exists.
+     */
+    private boolean exists() {
+        return lockFile.exists();
+    }
+
+    /**
+     * Returns true if the port is free.
+     */
+    private boolean isPortFree(int port) {
+        try {
+            ServerSocket socket = new ServerSocket(port);
+            socket.close();
+            return true;
+        } catch (BindException e) {
+            return false;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Return a file object that represents the lock file. The lock file itself
+     * may or may not exist.
+     */
+    private File getLockFile() {
+        File baseDir = new File(JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_USER_LOCKS_DIR));
+
+        if (!baseDir.isDirectory()) {
+            if (!baseDir.getParentFile().isDirectory() && !baseDir.getParentFile().mkdirs()) {
+                throw new RuntimeException(R("RNoLockDir", baseDir));
+            }
+            try {
+                FileUtils.createRestrictedDirectory(baseDir);
+            } catch (IOException e) {
+                throw new RuntimeException(R("RNoLockDir", baseDir));
+            }
+        }
+
+        String lockFileName = getLockFileName();
+        File applicationLockFile = new File(baseDir, lockFileName);
+        return applicationLockFile;
+    }
+
+    /**
+     * Returns the name of the lock file.
+     */
+    private String getLockFileName() {
+        String initialName = "";
+
+        if (jnlpFile.getSourceLocation() != null) {
+            initialName = initialName + jnlpFile.getSourceLocation();
+        } else {
+            initialName = initialName + jnlpFile.getFileLocation();
+        }
+
+        if (jnlpFile.getFileVersion() != null) {
+            initialName = initialName + jnlpFile.getFileVersion().toString();
+        }
+
+        initialName = initialName + getCurrentDisplay();
+        return FileUtils.sanitizeFileName(initialName);
+
+    }
+
+    /**
+     * Parse the lock file.
+     *
+     * @throws NumberFormatException
+     * @throws IOException
+     */
+    private void parseFile() throws NumberFormatException, IOException {
+        BufferedReader lockFileReader = new BufferedReader(new FileReader(lockFile));
+        int port = Integer.valueOf(lockFileReader.readLine());
+        lockFileReader.close();
+        this.port = port;
+    }
+
+    /**
+     * Returns a string identifying this display.
+     *
+     * Implementation note: On systems with X support, this is the DISPLAY
+     * variable
+     *
+     * @return a string that is guaranteed to be not null.
+     */
+    private String getCurrentDisplay() {
+        String display = System.getenv("DISPLAY");
+        return (display == null) ? "" : display;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XBasicService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XBasicService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XBasicService.java	(revision 403)
@@ -0,0 +1,297 @@
+// Copyright (C) 2001 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.jnlp.BasicService;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import net.sourceforge.jnlp.InformationDesc;
+import net.sourceforge.jnlp.JARDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.Launcher;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * The BasicService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.10 $
+ */
+class XBasicService implements BasicService {
+
+    /** command used to exec the native browser */
+    private String command = null;
+
+    /** whether the command was loaded / prompted for */
+    private boolean initialized = false;
+
+    protected XBasicService() {
+    }
+
+    /**
+     * Returns the codebase of the application, applet, or
+     * installer.  If the codebase was not specified in the JNLP
+     * element then the main JAR's location is returned.  If no main
+     * JAR was specified then the location of the JAR containing the
+     * main class is returned.
+     */
+    public URL getCodeBase() {
+        ApplicationInstance app = JNLPRuntime.getApplication();
+
+        if (app != null) {
+            JNLPFile file = app.getJNLPFile();
+
+            // return the codebase.
+            if (file.getCodeBase() != null)
+                return file.getCodeBase();
+
+            // else return the main JAR's URL.
+            JARDesc mainJar = file.getResources().getMainJAR();
+            if (mainJar != null)
+                return mainJar.getLocation();
+
+            // else find JAR where main class was defined.
+            //
+            // JNLPFile file = app.getJNLPFile();
+            // String mainClass = file.getLaunchInfo().getMainClass()+".class";
+            // URL jarUrl = app.getClassLoader().getResource(mainClass);
+            // go through list of JARDesc to find one matching jarUrl
+        }
+
+        return null;
+    }
+
+    /**
+     * Return true if the Environment is Offline
+     */
+    public boolean isOffline() {
+
+        URL url = findFirstURLFromJNLPFile();
+
+        try {
+            url.openConnection().getInputStream().close();
+            return false;
+        } catch (IOException exception) {
+            return true;
+        }
+    }
+
+    /**
+     * Return the first URL from the jnlp file
+     * Or a default URL if no url found in JNLP file
+     */
+    private URL findFirstURLFromJNLPFile() {
+
+        ApplicationInstance app = JNLPRuntime.getApplication();
+
+        if (app != null) {
+            JNLPFile jnlpFile = app.getJNLPFile();
+
+            URL sourceURL = jnlpFile.getSourceLocation();
+            if (sourceURL != null) {
+                return sourceURL;
+            }
+
+            URL codeBaseURL = jnlpFile.getCodeBase();
+            if (codeBaseURL != null) {
+                return codeBaseURL;
+            }
+
+            InformationDesc informationDesc = jnlpFile.getInformation();
+            URL homePage = informationDesc.getHomepage();
+            if (homePage != null) {
+                return homePage;
+            }
+
+            JARDesc[] jarDescs = jnlpFile.getResources().getJARs();
+            for (JARDesc jarDesc : jarDescs) {
+                return jarDesc.getLocation();
+            }
+        }
+
+        // this section is only reached if the jnlp file has no jars.
+        // that doesnt seem very likely.
+        URL arbitraryURL;
+        try {
+            arbitraryURL = new URL("http://icedtea.classpath.org");
+        } catch (MalformedURLException malformedURL) {
+            throw new RuntimeException(malformedURL);
+        }
+
+        return arbitraryURL;
+    }
+
+    /**
+     * Return true if a Web Browser is Supported
+     */
+    public boolean isWebBrowserSupported() {
+        initialize();
+
+        return command != null;
+    }
+
+    /**
+     * Show a document.
+     *
+     * @return whether the document was opened
+     */
+    public boolean showDocument(URL url) {
+        initialize();
+
+        if (url.toString().endsWith(".jnlp")) {
+            try {
+                new Launcher().launchExternal(url);
+                return true;
+            } catch (Exception ex) {
+                return false;
+            }
+        }
+
+        if (command != null) {
+            try {
+                // this is bogus because the command may require options;
+                // should use a StreamTokenizer or similar to get tokens
+                // outside of quotes.
+                Runtime.getRuntime().exec(command + " " + url.toString());
+                //Runtime.getRuntime().exec(new String[]{command,url.toString()});
+
+                return true;
+            } catch (IOException ex) {
+                if (JNLPRuntime.isDebug())
+                    ex.printStackTrace();
+            }
+        }
+
+        return false;
+    }
+
+    private void initialize() {
+        if (initialized)
+            return;
+        initialized = true;
+        initializeBrowserCommand();
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("browser is " + command);
+        }
+    }
+
+    /**
+     * Initializes {@link #command} to launch a browser
+     */
+    private void initializeBrowserCommand() {
+        if (JNLPRuntime.isWindows()) {
+            command = "rundll32 url.dll,FileProtocolHandler ";
+        } else if (JNLPRuntime.isUnix()) {
+            DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+            command = config.getProperty(DeploymentConfiguration.KEY_BROWSER_PATH);
+            if (command != null) {
+                return;
+            }
+
+            if (posixCommandExists("xdg-open")) {
+                command = "xdg-open";
+                return;
+            }
+
+            if (posixCommandExists(System.getenv("BROWSER"))) {
+                command = System.getenv("BROWSER");
+                return;
+            }
+
+            while (true) {
+                command = promptForCommand(command);
+                if (command != null && posixCommandExists(command)) {
+                    config.setProperty(DeploymentConfiguration.KEY_BROWSER_PATH, command);
+                    try {
+                        config.save();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    break;
+                }
+            }
+        } else {
+            DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+            command = config.getProperty(DeploymentConfiguration.KEY_BROWSER_PATH);
+
+            if (command == null) { // prompt & store
+                command = promptForCommand(null);
+
+                if (command != null) {
+                    config.setProperty(DeploymentConfiguration.KEY_BROWSER_PATH, command);
+                    try {
+                        config.save();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Check that a command exists on a posix-like system
+     * @param command the command to check
+     * @return true if the command exists
+     */
+    private boolean posixCommandExists(String command) {
+        if (command == null || command.trim().length() == 0) {
+            return false;
+        }
+
+        command = command.trim();
+        if (command.contains("\n") || command.contains("\r")) {
+            return false;
+        }
+
+        try {
+            Process p = Runtime.getRuntime().exec(new String[] { "bash", "-c", "type " + command });
+            p.waitFor();
+            return (p.exitValue() == 0);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    private String promptForCommand(String previousCommand) {
+        String message = null;
+        if (previousCommand == null) {
+            message = R("RBrowserLocationPromptMessage");
+        } else {
+            message = R("RBrowserLocationPromptMessageWithReason", previousCommand);
+        }
+        return JOptionPane.showInputDialog(new JPanel(),
+                                           R("RBrowserLocationPromptTitle"),
+                                           message,
+                                           JOptionPane.PLAIN_MESSAGE
+                                          );
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XClipboardService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XClipboardService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XClipboardService.java	(revision 403)
@@ -0,0 +1,81 @@
+/* XClipboardService.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+
+import java.awt.datatransfer.Transferable;
+import java.awt.Toolkit;
+
+/**
+ * The ClipboardService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XClipboardService implements ClipboardService {
+
+    protected XClipboardService() {
+    }
+
+    /**
+     * Returns the contents of the system clipboard.
+     */
+    public java.awt.datatransfer.Transferable getContents() {
+
+        if (ServiceUtil.checkAccess(AccessType.CLIPBOARD_READ)) {
+            Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+            return (Transferable) ServiceUtil.createPrivilegedProxy(
+                                Transferable.class, t);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Sets the contents of the system clipboard.
+     */
+    public void setContents(java.awt.datatransfer.Transferable contents) {
+        if (ServiceUtil.checkAccess(AccessType.CLIPBOARD_WRITE)) {
+            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
+                                contents, null);
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XDownloadService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XDownloadService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XDownloadService.java	(revision 403)
@@ -0,0 +1,174 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import java.net.*;
+import javax.jnlp.*;
+
+/**
+ * The DownloadService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+class XDownloadService implements DownloadService {
+
+    protected XDownloadService() {
+    }
+
+    // comments copied from DownloadService interface
+
+    /**
+     * Returns a listener that will automatically display download
+     * progress to the user.
+     */
+    public DownloadServiceListener getDefaultProgressWindow() {
+        return null;
+    }
+
+    /**
+     * Returns whether the part in an extension (specified by the
+     * url and version) is cached locally.
+     */
+    public boolean isExtensionPartCached(URL ref, String version, String part) {
+        return true;
+    }
+
+    /**
+     * Returns whether the parts in an extension (specified by the
+     * url and version) are cached locally.
+     */
+    public boolean isExtensionPartCached(URL ref, String version, String[] parts) {
+        return true;
+    }
+
+    /**
+     * Returns whether the part of the calling application is cached
+     * locally.  If called by code specified by an extension
+     * descriptor, the specified part refers to the extension not
+     * the application.
+     */
+    public boolean isPartCached(String part) {
+        return true;
+    }
+
+    /**
+     * Returns whether all of the parts of the calling application
+     * are cached locally.  If called by code in an extension, the
+     * part refers the the part of the extension not the
+     * application.
+     */
+    public boolean isPartCached(String[] parts) {
+        return true;
+    }
+
+    /**
+     * Returns whether the resource is cached locally.  This method
+     * only returns true if the resource is specified by the calling
+     * application or extension.
+     */
+    public boolean isResourceCached(URL ref, String version) {
+        return true;
+    }
+
+    /**
+     * Downloads the parts of an extension.
+     *
+     * @throws IOException
+     */
+    public void loadExtensionPart(URL ref, String version, String[] parts, DownloadServiceListener progress) throws IOException {
+    }
+
+    /**
+     * Downloads a part of an extension.
+     *
+     * @throws IOException
+     */
+    public void loadExtensionPart(URL ref, String version, String part, DownloadServiceListener progress) throws IOException {
+    }
+
+    /**
+     * Downloads the parts.
+     *
+     * @throws IOException
+     */
+    public void loadPart(String[] parts, DownloadServiceListener progress) throws IOException {
+    }
+
+    /**
+     * Downloads the part.
+     *
+     * @throws IOException
+     */
+    public void loadPart(String part, DownloadServiceListener progress) throws IOException {
+    }
+
+    /**
+     * Downloads a resource.
+     *
+     * @throws IOException
+     */
+    public void loadResource(URL ref, String version, DownloadServiceListener progress) throws IOException {
+    }
+
+    /**
+     * Notify the system that an extension's part is no longer
+     * important to cache.
+     *
+     * @throws IOException
+     */
+    public void removeExtensionPart(URL ref, String version, String part) throws IOException {
+    }
+
+    /**
+     * Notify the system that an extension's parts are no longer
+     * important to cache.
+     *
+     * @throws IOException
+     */
+    public void removeExtensionPart(URL ref, String version, String[] parts) throws IOException {
+    }
+
+    /**
+     * Notifies the system that a part  is no longer important to
+     * cache.
+     *
+     * @throws IOException
+     */
+    public void removePart(String part) throws IOException {
+    }
+
+    /**
+     * Notifies the system that the parts  is no longer important to
+     * cache.
+     *
+     * @throws IOException
+     */
+    public void removePart(String[] parts) throws IOException {
+    }
+
+    /**
+     * Notifies the system that the resource is no longer important
+     * to cache.
+     *
+     * @throws IOException
+     */
+    public void removeResource(URL ref, String version) throws IOException {
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtendedService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtendedService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtendedService.java	(revision 403)
@@ -0,0 +1,57 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.jnlp.ExtendedService;
+import javax.jnlp.FileContents;
+
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+
+/**
+ * Implementation of ExtendedService
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+public class XExtendedService implements ExtendedService {
+
+    public FileContents openFile(File file) throws IOException {
+
+        File secureFile = new File(file.getPath());
+
+        /* FIXME: this opens a file with read/write mode, not just read or write */
+        if (ServiceUtil.checkAccess(AccessType.READ_FILE, new Object[] { secureFile.getAbsolutePath() })) {
+            return (FileContents) ServiceUtil.createPrivilegedProxy(FileContents.class,
+                    new XFileContents(secureFile));
+        } else {
+            return null;
+        }
+
+    }
+
+    public FileContents[] openFiles(File[] files) throws IOException {
+        FileContents[] contents = new FileContents[files.length];
+        for (int i = 0; i < files.length; i++) {
+            contents[i] = openFile(files[i]);
+        }
+        return contents;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java	(revision 403)
@@ -0,0 +1,116 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.net.*;
+import javax.jnlp.*;
+
+
+/**
+ * The ExtensionInstallerService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+class XExtensionInstallerService implements ExtensionInstallerService {
+
+    protected XExtensionInstallerService() {
+    }
+
+    /**
+     *
+     */
+    public URL getExtensionLocation() {
+        return null;
+    }
+
+    /**
+     *
+     */
+    public String getExtensionVersion() {
+        return null;
+    }
+
+    /**
+     *
+     */
+    public String getInstalledJRE(java.net.URL url, java.lang.String version) {
+        return null;
+    }
+
+    /**
+     *
+     */
+    public String getInstallPath() {
+        return null;
+    }
+
+    /**
+     *
+     */
+    public void hideProgressBar() {
+    }
+
+    /**
+     *
+     */
+    public void hideStatusWindow() {
+    }
+
+    /**
+     *
+     */
+    public void installFailed() {
+    }
+
+    /**
+     *
+     */
+    public void installSucceeded(boolean needsReboot) {
+    }
+
+    /**
+     *
+     */
+    public void setHeading(java.lang.String heading) {
+    }
+
+    /**
+     *
+     */
+    public void setJREInfo(java.lang.String platformVersion, java.lang.String jrePath) {
+    }
+
+    /**
+     *
+     */
+    public void setNativeLibraryInfo(java.lang.String path) {
+    }
+
+    /**
+     *
+     */
+    public void setStatus(java.lang.String status) {
+    }
+
+    /**
+     *
+     */
+    public void updateProgress(int value) {
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileContents.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileContents.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileContents.java	(revision 403)
@@ -0,0 +1,114 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import javax.jnlp.*;
+
+/**
+ * File contents.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+class XFileContents implements FileContents {
+
+    /** the file */
+    private File file;
+
+    /**
+     * Create a file contents implementation for the file.
+     */
+    protected XFileContents(File file) {
+        // create a safe copy
+        this.file = new File(file.getPath());
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public boolean canRead() throws IOException {
+        return file.canRead();
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public boolean canWrite() throws IOException {
+        return file.canWrite();
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public InputStream getInputStream() throws IOException {
+        return new FileInputStream(file);
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public long getLength() throws IOException {
+        return file.length();
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public long getMaxLength() throws IOException {
+        return Long.MAX_VALUE;
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public String getName() throws IOException {
+        return file.getName();
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public OutputStream getOutputStream(boolean overwrite) throws IOException {
+        // file.getPath compatible with pre-1.4 JREs
+        return new FileOutputStream(file.getPath(), !overwrite);
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public JNLPRandomAccessFile getRandomAccessFile(String mode) throws IOException {
+        return new XJNLPRandomAccessFile(file, mode);
+    }
+
+    /**
+     *
+     * @throws IOException if an I/O exception occurs.
+     */
+    public long setMaxLength(long maxlength) throws IOException {
+        return maxlength;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileOpenService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileOpenService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileOpenService.java	(revision 403)
@@ -0,0 +1,106 @@
+/* XFileOpenService.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+
+import javax.swing.JFileChooser;
+
+/**
+ * The FileOpenService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XFileOpenService implements FileOpenService {
+
+    protected XFileOpenService() {
+    }
+
+    /**
+     * Prompts the user to select a single file.
+     */
+    public FileContents openFileDialog(java.lang.String pathHint,
+            java.lang.String[] extensions) throws java.io.IOException {
+
+        if (ServiceUtil.checkAccess(AccessType.READ_FILE)) {
+
+            //open a file dialog here, let the user choose the file.
+            JFileChooser chooser = new JFileChooser();
+            int chosen = chooser.showOpenDialog(null);
+            if (chosen == JFileChooser.APPROVE_OPTION) {
+                return (FileContents) ServiceUtil.createPrivilegedProxy(
+                           FileContents.class,
+                           new XFileContents(chooser.getSelectedFile()));
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Prompts the user to select one or more files.
+     */
+    public FileContents[] openMultiFileDialog(java.lang.String pathHint,
+            java.lang.String[] extensions) throws java.io.IOException {
+
+        if (ServiceUtil.checkAccess(AccessType.WRITE_FILE)) {
+            JFileChooser chooser = new JFileChooser();
+            chooser.setMultiSelectionEnabled(true);
+            int chosen = chooser.showOpenDialog(null);
+
+            if (chosen == JFileChooser.APPROVE_OPTION) {
+                File[] files = chooser.getSelectedFiles();
+                int length = files.length;
+                XFileContents[] xfiles = new XFileContents[length];
+                for (int i = 0; i < length; i++)
+                    xfiles[i] = new XFileContents(files[i]);
+                return (FileContents[]) ServiceUtil.createPrivilegedProxy(
+                           FileContents.class, xfiles);
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileSaveService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileSaveService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XFileSaveService.java	(revision 403)
@@ -0,0 +1,136 @@
+/* XFileSaveService.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;
+import net.sourceforge.jnlp.util.FileUtils;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+/**
+ * The FileSaveService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XFileSaveService implements FileSaveService {
+
+    protected XFileSaveService() {
+    }
+
+    /**
+     * Prompts the user to save a file.
+     */
+    public FileContents saveFileDialog(java.lang.String pathHint,
+            java.lang.String[] extensions, java.io.InputStream stream,
+            java.lang.String name) throws java.io.IOException {
+
+        if (ServiceUtil.checkAccess(AccessType.WRITE_FILE)) {
+            JFileChooser chooser = new JFileChooser();
+            int chosen = chooser.showSaveDialog(null);
+
+            if (chosen == JFileChooser.APPROVE_OPTION) {
+                writeToFile(stream, chooser.getSelectedFile());
+                return (FileContents) ServiceUtil.createPrivilegedProxy(
+                           FileContents.class,
+                           new XFileContents(chooser.getSelectedFile()));
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Prompts the user to save a file, with an optional pre-set filename.
+     */
+    public FileContents saveAsFileDialog(java.lang.String pathHint,
+            java.lang.String[] extensions, FileContents contents) throws java.io.IOException {
+
+        if (ServiceUtil.checkAccess(AccessType.WRITE_FILE)) {
+            JFileChooser chooser = new JFileChooser();
+            chooser.setSelectedFile(new File(contents.getName()));
+            int chosen = chooser.showSaveDialog(null);
+
+            if (chosen == JFileChooser.APPROVE_OPTION) {
+                writeToFile(contents.getInputStream(),
+                            chooser.getSelectedFile());
+
+                return (FileContents) ServiceUtil.createPrivilegedProxy(
+                           FileContents.class,
+                           new XFileContents(chooser.getSelectedFile()));
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Writes actual file to disk.
+     */
+    private void writeToFile(InputStream stream, File file) throws IOException {
+        if (!file.createNewFile()) { //file exists
+            boolean replace = (JOptionPane.showConfirmDialog(null,
+                                file.getAbsolutePath() + " already exists.\n"
+                                        + "Do you want to replace it?",
+                                "Warning - File Exists", JOptionPane.YES_NO_OPTION) == 0);
+            if (!replace)
+                return;
+        } else {
+            FileUtils.createRestrictedFile(file, true);
+        }
+
+        if (file.canWrite()) {
+            FileOutputStream out = new FileOutputStream(file);
+            byte[] b = new byte[256];
+            int read = 0;
+            while ((read = stream.read(b)) > 0)
+                out.write(b, 0, read);
+            out.flush();
+            out.close();
+        } else {
+            throw new IOException("Unable to open file for writing");
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java	(revision 403)
@@ -0,0 +1,203 @@
+/* XJNLPRandomAccessFile.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.services;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import javax.jnlp.JNLPRandomAccessFile;
+
+public class XJNLPRandomAccessFile implements JNLPRandomAccessFile {
+
+    private RandomAccessFile raf;
+
+    public XJNLPRandomAccessFile(File file, String mode) throws IOException {
+        raf = new RandomAccessFile(file, mode);
+
+    }
+
+    public void close() throws IOException {
+        raf.close();
+    }
+
+    public long getFilePointer() throws IOException {
+        return raf.getFilePointer();
+    }
+
+    public long length() throws IOException {
+        return raf.length();
+    }
+
+    public int read() throws IOException {
+        return raf.read();
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        return raf.read(b, off, len);
+    }
+
+    public int read(byte[] b) throws IOException {
+        return raf.read(b);
+    }
+
+    public boolean readBoolean() throws IOException {
+        return raf.readBoolean();
+    }
+
+    public byte readByte() throws IOException {
+        return raf.readByte();
+    }
+
+    public char readChar() throws IOException {
+        return raf.readChar();
+    }
+
+    public double readDouble() throws IOException {
+        return raf.readDouble();
+    }
+
+    public float readFloat() throws IOException {
+        return raf.readFloat();
+    }
+
+    public void readFully(byte[] b) throws IOException {
+        raf.readFully(b);
+    }
+
+    public void readFully(byte[] b, int off, int len) throws IOException {
+        raf.readFully(b, off, len);
+    }
+
+    public int readInt() throws IOException {
+        return raf.readInt();
+    }
+
+    public String readLine() throws IOException {
+        return raf.readLine();
+    }
+
+    public long readLong() throws IOException {
+        return raf.readLong();
+    }
+
+    public short readShort() throws IOException {
+        return raf.readShort();
+    }
+
+    public String readUTF() throws IOException {
+        return raf.readUTF();
+    }
+
+    public int readUnsignedByte() throws IOException {
+        return raf.readUnsignedByte();
+    }
+
+    public int readUnsignedShort() throws IOException {
+        return raf.readUnsignedShort();
+    }
+
+    public void seek(long pos) throws IOException {
+        raf.seek(pos);
+    }
+
+    public void setLength(long newLength) throws IOException {
+        raf.setLength(newLength);
+    }
+
+    public int skipBytes(int n) throws IOException {
+        return raf.skipBytes(n);
+    }
+
+    public void write(int b) throws IOException {
+        raf.write(b);
+
+    }
+
+    public void write(byte[] b) throws IOException {
+        raf.write(b);
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException {
+        raf.write(b, off, len);
+    }
+
+    public void writeBoolean(boolean v) throws IOException {
+        raf.writeBoolean(v);
+    }
+
+    public void writeByte(int v) throws IOException {
+        raf.writeByte(v);
+    }
+
+    public void writeBytes(String s) throws IOException {
+        raf.writeBytes(s);
+    }
+
+    public void writeChar(int v) throws IOException {
+        raf.writeChar(v);
+    }
+
+    public void writeChars(String s) throws IOException {
+        raf.writeChars(s);
+    }
+
+    public void writeDouble(double v) throws IOException {
+        raf.writeDouble(v);
+    }
+
+    public void writeFloat(float v) throws IOException {
+        raf.writeFloat(v);
+    }
+
+    public void writeInt(int v) throws IOException {
+        raf.writeInt(v);
+    }
+
+    public void writeLong(long v) throws IOException {
+        raf.writeLong(v);
+    }
+
+    public void writeShort(int v) throws IOException {
+        raf.writeShort(v);
+    }
+
+    public void writeUTF(String str) throws IOException {
+        raf.writeUTF(str);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPersistenceService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPersistenceService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPersistenceService.java	(revision 403)
@@ -0,0 +1,181 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.cache.*;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * The BasicService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+class XPersistenceService implements PersistenceService {
+
+    // todo: recheck delete, etc to make sure security is tight
+
+    protected XPersistenceService() {
+    }
+
+    /**
+     * Checks whether the application has access to URL area
+     * requested.  If the method returns normally then the specified
+     * location can be accessed by the current application.
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    protected void checkLocation(URL location) throws MalformedURLException {
+        ApplicationInstance app = JNLPRuntime.getApplication();
+        if (app == null)
+            throw new MalformedURLException("Cannot determine the current application.");
+
+        URL source = app.getJNLPFile().getCodeBase();
+
+        if (!source.getHost().equalsIgnoreCase(location.getHost()))
+            throw new MalformedURLException("Cannot access data from a different host.");
+
+        // test for above codebase, not perfect but works for now
+
+        String requestPath = location.getFile();
+        if (-1 != requestPath.lastIndexOf("/"))
+            requestPath = requestPath.substring(0, requestPath.lastIndexOf("/"));
+        else
+            requestPath = "";
+
+        if (JNLPRuntime.isDebug()) {
+            System.out.println("codebase path: " + source.getFile());
+            System.out.println("request path: " + requestPath);
+        }
+
+        if (!source.getFile().startsWith(requestPath))
+            throw new MalformedURLException("Cannot access data below source URL path.");
+    }
+
+    /**
+     * Converts a URL into a file in the persistence store.
+     *
+     * @return the file
+     */
+    protected File toCacheFile(URL location) throws MalformedURLException {
+        String pcache = JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_USER_PERSISTENCE_CACHE_DIR);
+        return CacheUtil.urlToPath(location, pcache);
+    }
+
+    /**
+     *
+     * @return the maximum size of storage that got granted, in bytes
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public long create(URL location, long maxsize) throws MalformedURLException, IOException {
+        checkLocation(location);
+
+        File file = toCacheFile(location);
+        FileUtils.createParentDir(file, "Persistence store for "
+                    + location.toString());
+
+        if (file.exists())
+            throw new IOException("File already exists.");
+
+        FileUtils.createRestrictedFile(file, true);
+
+        return maxsize;
+    }
+
+    /**
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public void delete(URL location) throws MalformedURLException, IOException {
+        checkLocation(location);
+
+        FileUtils.deleteWithErrMesg(toCacheFile(location), " tocache");
+    }
+
+    /**
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public FileContents get(URL location) throws MalformedURLException, IOException, FileNotFoundException {
+        checkLocation(location);
+
+        File file = toCacheFile(location);
+        if (!file.exists())
+            throw new FileNotFoundException("Persistence store for "
+                    + location.toString() + " is not found.");
+        FileUtils.createParentDir(file, "Persistence store for "
+                    + location.toString());
+
+        return (FileContents) ServiceUtil.createPrivilegedProxy(FileContents.class, new XFileContents(file));
+    }
+
+    /**
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public String[] getNames(URL location) throws MalformedURLException, IOException {
+        checkLocation(location);
+
+        File file = toCacheFile(location);
+        if (!file.isDirectory())
+            return new String[0];
+
+        List<String> result = new ArrayList<String>();
+
+        // check whether this is right: only add files and not directories.
+        File entries[] = file.listFiles();
+        for (int i = 0; i < entries.length; i++)
+            if (entries[i].isFile())
+                result.add(entries[i].getName());
+
+        return result.toArray(new String[result.size()]);
+    }
+
+    /**
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public int getTag(URL location) throws MalformedURLException, IOException {
+        checkLocation(location);
+
+        // todo: actually implement tags
+
+        if (toCacheFile(location).exists())
+            return PersistenceService.CACHED;
+
+        return PersistenceService.CACHED;
+    }
+
+    /**
+     *
+     * @throws MalformedURLException if the application cannot access the location
+     */
+    public void setTag(URL location, int tag) throws MalformedURLException, IOException {
+        checkLocation(location);
+
+        // todo: actually implement tags
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPrintService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPrintService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XPrintService.java	(revision 403)
@@ -0,0 +1,123 @@
+/* XPrintService.java
+   Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp.services;
+
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+
+import javax.jnlp.*;
+import javax.swing.JOptionPane;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class XPrintService implements PrintService {
+
+    // If pj is null, then we do not have a printer to use.
+    private PrinterJob pj;
+
+    public XPrintService() {
+        pj = PrinterJob.getPrinterJob();
+    }
+
+    public PageFormat getDefaultPage() {
+        if (pj != null)
+            return pj.defaultPage();
+        else {
+            showWarning();
+            return new PageFormat(); // might not have default settings.
+        }
+    }
+
+    public PageFormat showPageFormatDialog(PageFormat page) {
+        if (pj != null)
+            return pj.pageDialog(page);
+        else {
+            showWarning();
+            return page;
+        }
+
+    }
+
+    public boolean print(Pageable document) {
+        if (pj != null) {
+            pj.setPageable(document);
+            if (pj.printDialog()) {
+                try {
+                    pj.print();
+                    return true;
+                } catch (PrinterException pe) {
+                    System.err.println("Could not print: " + pe);
+                    return false;
+                }
+            }
+        } else
+            showWarning();
+
+        return false;
+    }
+
+    public boolean print(Printable painter) {
+        if (pj != null) {
+            pj.setPrintable(painter);
+            if (pj.printDialog()) {
+                try {
+                    pj.print();
+                    return true;
+                } catch (PrinterException pe) {
+                    System.err.println("Could not print: " + pe);
+                    return false;
+                }
+
+            }
+        } else
+            showWarning();
+
+        return false;
+    }
+
+    private void showWarning() {
+        JOptionPane.showMessageDialog(null,
+                                "Unable to find a default printer.",
+                                "Warning",
+                                JOptionPane.WARNING_MESSAGE);
+        System.err.println("Unable to print: Unable to find default printer.");
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java	(revision 403)
@@ -0,0 +1,104 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import java.lang.reflect.*;
+import java.security.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+
+/**
+ * Lookup table for services.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class XServiceManagerStub implements ServiceManagerStub {
+
+    // todo: only include ExtensionInstallerService if an installer
+    // is getting the service, otherwise return null.
+
+    // todo: fix services to do their own privileged actions that
+    // run less code in the secure environment (or avoid privileged
+    // actions by giving permission to the code source).
+
+    private static String serviceNames[] = {
+            "javax.jnlp.BasicService", // required
+            "javax.jnlp.DownloadService", // required
+            "javax.jnlp.ExtendedService",
+            "javax.jnlp.ExtensionInstallerService", // required
+            "javax.jnlp.PersistenceService",
+            "javax.jnlp.FileOpenService",
+            "javax.jnlp.FileSaveService",
+            "javax.jnlp.ClipboardService",
+            "javax.jnlp.PrintService",
+            "javax.jnlp.SingleInstanceService"
+    };
+
+    private static Object services[] = {
+            ServiceUtil.createPrivilegedProxy(BasicService.class, new XBasicService()),
+            ServiceUtil.createPrivilegedProxy(DownloadService.class, new XDownloadService()),
+            ServiceUtil.createPrivilegedProxy(ExtendedService.class, new XExtendedService()),
+            ServiceUtil.createPrivilegedProxy(ExtensionInstallerService.class, new XExtensionInstallerService()),
+            ServiceUtil.createPrivilegedProxy(PersistenceService.class, new XPersistenceService()),
+            ServiceUtil.createPrivilegedProxy(FileOpenService.class, new XFileOpenService()),
+            ServiceUtil.createPrivilegedProxy(FileSaveService.class, new XFileSaveService()),
+            ServiceUtil.createPrivilegedProxy(ClipboardService.class, new XClipboardService()),
+            ServiceUtil.createPrivilegedProxy(PrintService.class, new XPrintService()),
+            ServiceUtil.createPrivilegedProxy(ExtendedSingleInstanceService.class, new XSingleInstanceService())
+    };
+
+    public XServiceManagerStub() {
+    }
+
+    /**
+     * Returns the service names.
+     */
+    public String[] getServiceNames() {
+        // make sure it is a copy because we might be returning to
+        // code we don't own.
+        String result[] = new String[serviceNames.length];
+        System.arraycopy(serviceNames, 0, result, 0, serviceNames.length);
+
+        return result;
+    }
+
+    /**
+     * Returns the service.
+     *
+     * @throws UnavailableServiceException if service is not available
+     */
+    public Object lookup(String name) throws UnavailableServiceException {
+        // exact match
+        for (int i = 0; i < serviceNames.length; i++)
+            if (serviceNames[i].equals(name))
+                return services[i];
+
+        // substring match
+        for (int i = 0; i < serviceNames.length; i++)
+            if (-1 != serviceNames[i].indexOf(name))
+                return services[i];
+
+        throw new UnavailableServiceException("" + name);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java	(revision 403)
@@ -0,0 +1,236 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.services;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.jnlp.SingleInstanceListener;
+import javax.management.InstanceAlreadyExistsException;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * This class implements SingleInstanceService
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ */
+public class XSingleInstanceService implements ExtendedSingleInstanceService {
+
+    boolean initialized = false;
+    List<SingleInstanceListener> listeners = new LinkedList<SingleInstanceListener>();
+
+    /**
+     * Implements a server that listens for arguments from new instances of this
+     * application
+     *
+     */
+    class SingleInstanceServer implements Runnable {
+
+        SingleInstanceLock lockFile = null;
+
+        public SingleInstanceServer(SingleInstanceLock lockFile) {
+            this.lockFile = lockFile;
+        }
+
+        public void run() {
+            ServerSocket listeningSocket = null;
+            try {
+                listeningSocket = new ServerSocket(0);
+                lockFile.createWithPort(listeningSocket.getLocalPort());
+
+                if (JNLPRuntime.isDebug()) {
+                    System.out.println("Starting SingleInstanceServer on port" + listeningSocket);
+                }
+
+                while (true) {
+                    try {
+                        Socket communicationSocket = listeningSocket.accept();
+                        ObjectInputStream ois = new ObjectInputStream(communicationSocket
+                                .getInputStream());
+                        String[] arguments = (String[]) ois.readObject();
+                        notifySingleInstanceListeners(arguments);
+                    } catch (Exception exception) {
+                        // not much to do here...
+                        exception.printStackTrace();
+                    }
+
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                if (listeningSocket != null) {
+                    try {
+                        listeningSocket.close();
+                    } catch (IOException e) {
+                        // Give up.
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a new XSingleInstanceService
+     */
+    protected XSingleInstanceService() {
+    }
+
+    /**
+     * Initialize the new SingleInstanceService
+     *
+     * @throws InstanceAlreadyExistsException if the instance already exists
+     */
+    public void initializeSingleInstance() {
+        if (!initialized) {
+            // this is called after the application has started. so safe to use
+            // JNLPRuntime.getApplication()
+            checkSingleInstanceRunning(JNLPRuntime.getApplication().getJNLPFile());
+            initialized = true;
+            SingleInstanceLock lockFile;
+            JNLPFile jnlpFile = JNLPRuntime.getApplication().getJNLPFile();
+            lockFile = new SingleInstanceLock(jnlpFile);
+            if (!lockFile.isValid()) {
+                startListeningServer(lockFile);
+            }
+        }
+
+    }
+
+    /**
+     * Check if another instance of this application is already running
+     *
+     * @param jnlpFile The {@link JNLPFile} that specifies the application
+     *
+     * @throws InstanceExistsException if an instance of this application
+     *         already exists
+     */
+    public void checkSingleInstanceRunning(JNLPFile jnlpFile) {
+        SingleInstanceLock lockFile = new SingleInstanceLock(jnlpFile);
+        if (lockFile.isValid()) {
+            int port = lockFile.getPort();
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Lock file is valid (port=" + port + "). Exiting.");
+            }
+            try {
+                sendProgramArgumentsToExistingApplication(port, jnlpFile.getApplication()
+                        .getArguments());
+                throw new InstanceExistsException(String.valueOf(port));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
+     * Start the listening server to accept arguments from new instances of
+     * applications
+     *
+     * @param lockFile
+     *            the {@link SingleInstanceLock} that the server should use
+     */
+    private void startListeningServer(SingleInstanceLock lockFile) {
+        SingleInstanceServer server = new SingleInstanceServer(lockFile);
+        Thread serverThread = new Thread(server);
+        /*
+         * mark as daemon so the JVM can shutdown if the server is the only
+         * thread running
+         */
+        serverThread.setDaemon(true);
+        serverThread.start();
+    }
+
+    /**
+     * Send the arguments for this application to the main instance
+     *
+     * @param port the port at which the SingleInstanceServer is listening at
+     * @param arguments the new arguments
+     * @throws IOException on any io exception
+     */
+    private void sendProgramArgumentsToExistingApplication(int port, String[] arguments)
+            throws IOException {
+        try {
+            Socket serverCommunicationSocket = new Socket((String) null, port);
+            ObjectOutputStream argumentStream = new ObjectOutputStream(serverCommunicationSocket
+                    .getOutputStream());
+            argumentStream.writeObject(arguments);
+            argumentStream.close();
+            serverCommunicationSocket.close();
+
+        } catch (UnknownHostException unknownHost) {
+            if (JNLPRuntime.isDebug()) {
+                System.out.println("Unable to find localhost");
+            }
+            throw new RuntimeException(unknownHost);
+        }
+    }
+
+    /**
+     * Notify any SingleInstanceListener with new arguments
+     *
+     * @param arguments the new arguments to the application
+     */
+    private void notifySingleInstanceListeners(String[] arguments) {
+        for (SingleInstanceListener listener : listeners) {
+            // TODO this proxy is privileged. should i worry about security in
+            // methods being called?
+            listener.newActivation(arguments);
+        }
+    }
+
+    /**
+     * Add the specified SingleInstanceListener
+     *
+     * @throws InstanceExistsException, which is likely to terminate the
+     *         application but not guaranteed to
+     */
+    public void addSingleInstanceListener(SingleInstanceListener sil) {
+        initializeSingleInstance();
+
+        if (sil == null) {
+            return;
+        }
+
+        listeners.add(sil);
+    }
+
+    /**
+     * Remove the specified SingleInstanceListener
+     *
+     * @throws InstanceExistsException if an instance of this single instance
+     *         application already exists
+     *
+     */
+    public void removeSingleInstanceListener(SingleInstanceListener sil) {
+        initializeSingleInstance();
+
+        if (sil == null) {
+            return;
+        }
+
+        listeners.remove(sil);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/package.html
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/package.html	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/services/package.html	(revision 403)
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the classes that implement the standard
+services defined by the JNLP specification.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/JarSigner.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/JarSigner.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/JarSigner.java	(revision 403)
@@ -0,0 +1,543 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package net.sourceforge.jnlp.tools;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertPath;
+import java.security.*;
+import sun.security.x509.*;
+import sun.security.util.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.cache.*;
+import net.sourceforge.jnlp.security.*;
+
+/**
+ * <p>The jarsigner utility.
+ *
+ * @author Roland Schemers
+ * @author Jan Luehe
+ */
+
+public class JarSigner implements CertVerifier {
+
+    private static final String META_INF = "META-INF/";
+
+    // prefix for new signature-related files in META-INF directory
+    private static final String SIG_PREFIX = META_INF + "SIG-";
+
+    private static final long SIX_MONTHS = 180 * 24 * 60 * 60 * 1000L; //milliseconds
+
+    static enum verifyResult {
+        UNSIGNED, SIGNED_OK, SIGNED_NOT_OK
+    }
+
+    // signer's certificate chain (when composing)
+    X509Certificate[] certChain;
+
+    boolean verbose = false; // verbose output when signing/verifying
+    boolean showcerts = false; // show certs when verifying
+
+    private boolean hasExpiredCert = false;
+    private boolean hasExpiringCert = false;
+    private boolean notYetValidCert = false;
+
+    private boolean badKeyUsage = false;
+    private boolean badExtendedKeyUsage = false;
+    private boolean badNetscapeCertType = false;
+
+    private boolean alreadyTrustPublisher = false;
+    private boolean rootInCacerts = false;
+
+    /**
+     * The single certPath used in this JarSiging. We're only keeping
+     * track of one here, since in practice there's only one signer
+     * for a JNLP Application.
+     */
+    private CertPath certPath = null;
+
+    private boolean noSigningIssues = true;
+
+    private boolean anyJarsSigned = false;
+
+    /** all of the jar files that were verified */
+    private ArrayList<String> verifiedJars = null;
+
+    /** all of the jar files that were not verified */
+    private ArrayList<String> unverifiedJars = null;
+
+    /** the certificates used for jar verification */
+    private HashMap<CertPath, Integer> certs = new HashMap<CertPath, Integer>();
+
+    /** details of this signing */
+    private ArrayList<String> details = new ArrayList<String>();
+
+    private int totalSignableEntries = 0;
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getAlreadyTrustPublisher()
+     */
+    public boolean getAlreadyTrustPublisher() {
+        return alreadyTrustPublisher;
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getRootInCacerts()
+     */
+    public boolean getRootInCacerts() {
+        return rootInCacerts;
+    }
+
+    public CertPath getCertPath() {
+        return certPath;
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#hasSigningIssues()
+     */
+    public boolean hasSigningIssues() {
+        return hasExpiredCert || notYetValidCert || badKeyUsage
+                || badExtendedKeyUsage || badNetscapeCertType;
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#noSigningIssues()
+     */
+    public boolean noSigningIssues() {
+        return noSigningIssues;
+    }
+
+    public boolean anyJarsSigned() {
+        return anyJarsSigned;
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getDetails()
+     */
+    public ArrayList<String> getDetails() {
+        return details;
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getCerts()
+     */
+    public ArrayList<CertPath> getCerts() {
+        return new ArrayList<CertPath>(certs.keySet());
+    }
+
+    /**
+     * Returns whether or not all entries have a common signer.
+     *  
+     * It is possible to create jars where only some entries are signed. In 
+     * such cases, we should not prompt the user to accept anything, as the whole 
+     * application must be treated as unsigned. This method should be called by a 
+     * caller before it is about to ask the user to accept a cert and determine 
+     * whether the application is trusted or not.
+     *  
+     * @return Whether or not all entries have a common signer
+     */
+    public boolean isFullySignedByASingleCert() {
+
+        for (CertPath cPath : certs.keySet()) {
+            // If this cert has signed everything, return true
+            if (certs.get(cPath) == totalSignableEntries)
+                return true;
+        }
+
+        // No cert found that signed all entries. Return false.
+        return false;
+    }
+
+    public void verifyJars(List<JARDesc> jars, ResourceTracker tracker)
+            throws Exception {
+
+        verifiedJars = new ArrayList<String>();
+        unverifiedJars = new ArrayList<String>();
+
+        for (int i = 0; i < jars.size(); i++) {
+
+            JARDesc jar = jars.get(i);
+
+            try {
+
+                File jarFile = tracker.getCacheFile(jar.getLocation());
+
+                // some sort of resource download/cache error. Nothing to add
+                // in that case ... but don't fail here
+                if (jarFile == null) {
+                    return;
+                }
+
+                String localFile = jarFile.getAbsolutePath();
+                verifyResult result = verifyJar(localFile);
+
+                if (result == verifyResult.UNSIGNED) {
+                    unverifiedJars.add(localFile);
+                } else if (result == verifyResult.SIGNED_NOT_OK) {
+                    noSigningIssues = false;
+                    verifiedJars.add(localFile);
+                } else if (result == verifyResult.SIGNED_OK) {
+                    verifiedJars.add(localFile);
+                }
+            } catch (Exception e) {
+                // We may catch exceptions from using verifyJar()
+                // or from checkTrustedCerts
+                throw e;
+            }
+        }
+
+        //we really only want the first certPath
+        for (CertPath cPath : certs.keySet()) {
+
+            if (certs.get(cPath) != totalSignableEntries)
+                continue;
+            else
+                certPath = cPath;
+
+            // check if the certs added above are in the trusted path
+            checkTrustedCerts();
+
+            if (alreadyTrustPublisher || rootInCacerts)
+                break;
+        }
+
+    }
+
+    private verifyResult verifyJar(String jarName) throws Exception {
+        boolean anySigned = false;
+        boolean hasUnsignedEntry = false;
+        JarFile jarFile = null;
+
+        try {
+            jarFile = new JarFile(jarName, true);
+            Vector<JarEntry> entriesVec = new Vector<JarEntry>();
+            byte[] buffer = new byte[8192];
+
+            JarEntry je;
+            Enumeration<JarEntry> entries = jarFile.entries();
+            while (entries.hasMoreElements()) {
+                je = entries.nextElement();
+                entriesVec.addElement(je);
+
+                InputStream is = jarFile.getInputStream(je);
+                try {
+                    int n;
+                    while ((n = is.read(buffer, 0, buffer.length)) != -1) {
+                        // we just read. this will throw a SecurityException
+                        // if  a signature/digest check fails.
+                    }
+                } finally {
+                    if (is != null) {
+                        is.close();
+                    }
+                }
+            }
+
+            if (jarFile.getManifest() != null) {
+                if (verbose)
+                    System.out.println();
+                Enumeration<JarEntry> e = entriesVec.elements();
+
+                long now = System.currentTimeMillis();
+
+                while (e.hasMoreElements()) {
+                    je = e.nextElement();
+                    String name = je.getName();
+                    CodeSigner[] signers = je.getCodeSigners();
+                    boolean isSigned = (signers != null);
+                    anySigned |= isSigned;
+
+                    boolean shouldHaveSignature = !je.isDirectory()
+                                                && !signatureRelated(name);
+
+                    hasUnsignedEntry |= shouldHaveSignature &&  !isSigned;
+
+                    if (shouldHaveSignature)
+                        totalSignableEntries++;
+
+                    if (shouldHaveSignature && isSigned) {
+                        for (int i = 0; i < signers.length; i++) {
+                            CertPath certPath = signers[i].getSignerCertPath();
+                            if (!certs.containsKey(certPath))
+                                certs.put(certPath, 1);
+                            else
+                                certs.put(certPath, certs.get(certPath) + 1);
+
+                            Certificate cert = signers[i].getSignerCertPath()
+                                    .getCertificates().get(0);
+                            if (cert instanceof X509Certificate) {
+                                checkCertUsage((X509Certificate) cert, null);
+                                if (!showcerts) {
+                                    long notAfter = ((X509Certificate) cert)
+                                                    .getNotAfter().getTime();
+
+                                    if (notAfter < now) {
+                                        hasExpiredCert = true;
+                                    } else if (notAfter < now + SIX_MONTHS) {
+                                        hasExpiringCert = true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } //while e has more elements
+            } else { //if man not null
+
+                // Else increment totalEntries by 1 so that unsigned jars with 
+                // no manifests can't sneak in
+                totalSignableEntries++;
+            }
+
+            //Alert the user if any of the following are true.
+            if (!anySigned) {
+                return verifyResult.UNSIGNED;
+            } else {
+                anyJarsSigned = true;
+
+                //warnings
+                if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert ||
+                        badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+                        notYetValidCert) {
+
+                    addToDetails(R("SRunWithoutRestrictions"));
+
+                    if (badKeyUsage)
+                        addToDetails(R("SBadKeyUsage"));
+                    if (badExtendedKeyUsage)
+                        addToDetails(R("SBadExtendedKeyUsage"));
+                    if (badNetscapeCertType)
+                        addToDetails(R("SBadNetscapeCertType"));
+                    if (hasUnsignedEntry)
+                        addToDetails(R("SHasUnsignedEntry"));
+                    if (hasExpiredCert)
+                        addToDetails(R("SHasExpiredCert"));
+                    if (hasExpiringCert)
+                        addToDetails(R("SHasExpiringCert"));
+                    if (notYetValidCert)
+                        addToDetails(R("SNotYetValidCert"));
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw e;
+        } finally { // close the resource
+            if (jarFile != null) {
+                jarFile.close();
+            }
+        }
+
+        //anySigned does not guarantee that all files were signed.
+        return (anySigned && !(hasUnsignedEntry || hasExpiredCert
+                              || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || notYetValidCert)) ? verifyResult.SIGNED_OK : verifyResult.SIGNED_NOT_OK;
+    }
+
+    /**
+     * Checks the user's trusted.certs file and the cacerts file to see
+     * if a publisher's and/or CA's certificate exists there.
+     */
+    private void checkTrustedCerts() throws Exception {
+        if (certPath != null) {
+            try {
+                X509Certificate publisher = (X509Certificate) getPublisher();
+                KeyStore[] certKeyStores = KeyStores.getCertKeyStores();
+                alreadyTrustPublisher = CertificateUtils.inKeyStores(publisher, certKeyStores);
+                X509Certificate root = (X509Certificate) getRoot();
+                KeyStore[] caKeyStores = KeyStores.getCAKeyStores();
+                rootInCacerts = CertificateUtils.inKeyStores(root, caKeyStores);
+            } catch (Exception e) {
+                // TODO: Warn user about not being able to
+                // look through their cacerts/trusted.certs
+                // file depending on exception.
+                throw e;
+            }
+
+            if (!rootInCacerts)
+                addToDetails(R("SUntrustedCertificate"));
+            else
+                addToDetails(R("STrustedCertificate"));
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getPublisher()
+     */
+    public Certificate getPublisher() {
+        if (certPath != null) {
+            List<? extends Certificate> certList = certPath.getCertificates();
+            if (certList.size() > 0) {
+                return certList.get(0);
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see net.sourceforge.jnlp.tools.CertVerifier2#getRoot()
+     */
+    public Certificate getRoot() {
+        if (certPath != null) {
+            List<? extends Certificate> certList = certPath.getCertificates();
+            if (certList.size() > 0) {
+                return certList.get(certList.size() - 1);
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private void addToDetails(String detail) {
+        if (!details.contains(detail))
+            details.add(detail);
+    }
+
+    /**
+     * signature-related files include:
+     * . META-INF/MANIFEST.MF
+     * . META-INF/SIG-*
+     * . META-INF/*.SF
+     * . META-INF/*.DSA
+     * . META-INF/*.RSA
+     *
+     * Required for verifyJar()
+     */
+    private boolean signatureRelated(String name) {
+        String ucName = name.toUpperCase();
+        if (ucName.equals(JarFile.MANIFEST_NAME) ||
+                ucName.equals(META_INF) ||
+                (ucName.startsWith(SIG_PREFIX) &&
+                 ucName.indexOf("/") == ucName.lastIndexOf("/"))) {
+            return true;
+        }
+
+        if (ucName.startsWith(META_INF) &&
+                SignatureFileVerifier.isBlockOrSF(ucName)) {
+            // .SF/.DSA/.RSA files in META-INF subdirs
+            // are not considered signature-related
+            return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if userCert is designed to be a code signer
+     * @param userCert the certificate to be examined
+     * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage,
+     *            NetscapeCertType has codeSigning flag turned on.
+     *            If null, the class field badKeyUsage, badExtendedKeyUsage,
+     *            badNetscapeCertType will be set.
+     *
+     * Required for verifyJar()
+     */
+    void checkCertUsage(X509Certificate userCert, boolean[] bad) {
+
+        // Can act as a signer?
+        // 1. if KeyUsage, then [0] should be true
+        // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING
+        // 3. if NetscapeCertType, then should contains OBJECT_SIGNING
+        // 1,2,3 must be true
+
+        if (bad != null) {
+            bad[0] = bad[1] = bad[2] = false;
+        }
+
+        boolean[] keyUsage = userCert.getKeyUsage();
+        if (keyUsage != null) {
+            if (keyUsage.length < 1 || !keyUsage[0]) {
+                if (bad != null) {
+                    bad[0] = true;
+                } else {
+                    badKeyUsage = true;
+                }
+            }
+        }
+
+        try {
+            List<String> xKeyUsage = userCert.getExtendedKeyUsage();
+            if (xKeyUsage != null) {
+                if (!xKeyUsage.contains("2.5.29.37.0") // anyExtendedKeyUsage
+                        && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) { // codeSigning
+                    if (bad != null) {
+                        bad[1] = true;
+                    } else {
+                        badExtendedKeyUsage = true;
+                    }
+                }
+            }
+        } catch (java.security.cert.CertificateParsingException e) {
+            // shouldn't happen
+        }
+
+        try {
+            // OID_NETSCAPE_CERT_TYPE
+            byte[] netscapeEx = userCert.getExtensionValue
+                                ("2.16.840.1.113730.1.1");
+            if (netscapeEx != null) {
+                DerInputStream in = new DerInputStream(netscapeEx);
+                byte[] encoded = in.getOctetString();
+                encoded = new DerValue(encoded).getUnalignedBitString()
+                        .toByteArray();
+
+                NetscapeCertTypeExtension extn =
+                        new NetscapeCertTypeExtension(encoded);
+
+                Boolean val = (Boolean) extn.get(
+                                  NetscapeCertTypeExtension.OBJECT_SIGNING);
+                if (!val) {
+                    if (bad != null) {
+                        bad[2] = true;
+                    } else {
+                        badNetscapeCertType = true;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            //
+        }
+    }
+
+    /**
+     * Returns if all jars are signed.
+     *
+     * @return True if all jars are signed, false if there are one or more unsigned jars
+     */
+    public boolean allJarsSigned() {
+        return this.unverifiedJars.size() == 0;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java	(revision 403)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package net.sourceforge.jnlp.tools;
+
+/**
+ * <p> This class provides several utilities to <code>KeyStore</code>.
+ *
+ * @since 1.6.0
+ */
+public class KeyStoreUtil {
+
+    // Class and methods marked as public so that they can be
+    // accessed by JarSigner, which although lies in a package
+    // with the same name, but bundled in tools.jar and loaded
+    // by another class loader, hence in a different *runtime*
+    // package.
+    //
+    // See JVM Spec, 5.3 and 5.4.4
+
+    private KeyStoreUtil() {
+        // this class is not meant to be instantiated
+    }
+
+    /**
+     * Returns true if KeyStore has a password. This is true except for
+     * MSCAPI KeyStores
+     */
+    public static boolean isWindowsKeyStore(String storetype) {
+        return storetype.equalsIgnoreCase("Windows-MY")
+                || storetype.equalsIgnoreCase("Windows-ROOT");
+    }
+
+    /**
+     * Returns standard-looking names for storetype
+     */
+    public static String niceStoreTypeName(String storetype) {
+        if (storetype.equalsIgnoreCase("Windows-MY")) {
+            return "Windows-MY";
+        } else if (storetype.equalsIgnoreCase("Windows-ROOT")) {
+            return "Windows-ROOT";
+        } else {
+            return storetype.toUpperCase();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java	(revision 403)
@@ -0,0 +1,129 @@
+/* BasicExceptionDialog.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.util;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+/**
+ * A dialog that displays some basic information about an exception
+ */
+public class BasicExceptionDialog {
+
+    private static String exceptionToString(Exception exception) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(stringWriter);
+        exception.printStackTrace(printWriter);
+        return stringWriter.toString();
+    }
+
+    /**
+     * Must be invoked from the Swing EDT.
+     *
+     * @param exception the exception to indicate
+     */
+    public static void show(Exception exception) {
+        String detailsText = exceptionToString(exception);
+
+        final JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+        JOptionPane optionPane = new JOptionPane(mainPanel, JOptionPane.ERROR_MESSAGE);
+        final JDialog errorDialog = optionPane.createDialog(R("Error"));
+
+        final JPanel quickInfoPanel = new JPanel();
+        BoxLayout layout = new BoxLayout(quickInfoPanel, BoxLayout.Y_AXIS);
+        quickInfoPanel.setLayout(layout);
+        mainPanel.add(quickInfoPanel, BorderLayout.PAGE_START);
+
+        JLabel errorLabel = new JLabel(exception.getMessage());
+        errorLabel.setAlignmentY(JComponent.LEFT_ALIGNMENT);
+        quickInfoPanel.add(errorLabel);
+
+        final JButton viewDetails = new JButton(R("ButShowDetails"));
+        viewDetails.setAlignmentY(JComponent.LEFT_ALIGNMENT);
+        viewDetails.setActionCommand("show");
+        quickInfoPanel.add(viewDetails);
+
+        JTextArea textArea = new JTextArea();
+        textArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        textArea.setEditable(false);
+        textArea.setText(detailsText);
+        final JScrollPane scrollPane = new JScrollPane(textArea);
+        scrollPane.setPreferredSize(new Dimension(100, 200));
+
+        viewDetails.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                if (viewDetails.getActionCommand().equals("show")) {
+                    mainPanel.add(scrollPane, BorderLayout.CENTER);
+                    viewDetails.setActionCommand("hide");
+                    viewDetails.setText(R("ButHideDetails"));
+                    errorDialog.pack();
+                } else {
+                    mainPanel.remove(scrollPane);
+                    viewDetails.setActionCommand("show");
+                    viewDetails.setText(R("ButShowDetails"));
+                    errorDialog.pack();
+                }
+            }
+        });
+
+        errorDialog.pack();
+        errorDialog.setResizable(true);
+        errorDialog.setVisible(true);
+        errorDialog.dispose();
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/FileUtils.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/FileUtils.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/FileUtils.java	(revision 403)
@@ -0,0 +1,348 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.util;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import net.sourceforge.jnlp.config.Defaults;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * This class contains a few file-related utility functions.
+ *
+ * @author Omair Majid
+ */
+
+public final class FileUtils {
+
+    /**
+     * list of characters not allowed in filenames
+     */
+    private static final char INVALID_CHARS[] = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' };
+
+    private static final char SANITIZED_CHAR = '_';
+
+    /**
+     * Clean up a string by removing characters that can't appear in a local
+     * file name.
+     *
+     * @param path
+     *        the path to sanitize
+     * @return a sanitized version of the input which is suitable for using as a
+     *         file path
+     */
+    public static String sanitizePath(String path) {
+
+        for (int i = 0; i < INVALID_CHARS.length; i++)
+            if (INVALID_CHARS[i] != File.separatorChar)
+                if (-1 != path.indexOf(INVALID_CHARS[i]))
+                    path = path.replace(INVALID_CHARS[i], SANITIZED_CHAR);
+
+        return path;
+    }
+
+    /**
+     * Given an input, return a sanitized form of the input suitable for use as
+     * a file/directory name
+     *
+     * @param filename the filename to sanitize.
+     * @return a sanitized version of the input
+     */
+    public static String sanitizeFileName(String filename) {
+
+        for (int i = 0; i < INVALID_CHARS.length; i++)
+            if (-1 != filename.indexOf(INVALID_CHARS[i]))
+                filename = filename.replace(INVALID_CHARS[i], SANITIZED_CHAR);
+
+        return filename;
+    }
+
+    /**
+     * Creates a new directory with minimum permissions. The directory is not
+     * readable or writable by anyone other than the owner. The parent
+     * directories are not created; they must exist before this is called.
+     *
+     * @throws IOException
+     */
+    public static void createRestrictedDirectory(File directory) throws IOException {
+        createRestrictedFile(directory, true, true);
+    }
+
+    /**
+     * Creates a new file with minimum permissions. The file is not readable or
+     * writable by anyone other than the owner. If writeableByOnwer is false,
+     * even the owner can not write to it.
+     *
+     * @throws IOException
+     */
+    public static void createRestrictedFile(File file, boolean writableByOwner) throws IOException {
+        createRestrictedFile(file, false, writableByOwner);
+    }
+
+    /**
+     * Tries to create the ancestor directories of file f. Throws
+     * an IOException if it can't be created (but not if it was
+     * already there).
+     * @param f
+     * @param eMsg - the message to use for the exception. null
+     * if the file name is to be used.
+     * @throws IOException if the directory can't be created and doesn't exist.
+     */
+    public static void createParentDir(File f, String eMsg) throws IOException {
+        File parent = f.getParentFile();
+        if (!parent.isDirectory() && !parent.mkdirs()) {
+            throw new IOException(R("RCantCreateDir",
+                    eMsg == null ? parent : eMsg));
+        }
+    }
+
+    /**
+     * Tries to create the ancestor directories of file f. Throws
+     * an IOException if it can't be created (but not if it was
+     * already there).
+     * @param f
+     * @throws IOException if the directory can't be created and doesn't exist.
+     */
+    public static void createParentDir(File f) throws IOException {
+        createParentDir(f, null);
+    }
+
+    /**
+     * Tries to delete file f. If the file exists but couldn't be deleted,
+     * print an error message to stderr with the file name, or eMsg if eMsg
+     * is not null.
+     * @param f the file to be deleted
+     * @param eMsg the message to print on failure (or null to print the
+     * the file name).
+     */
+    public static void deleteWithErrMesg(File f, String eMsg) {
+        if (f.exists()) {
+            if (!f.delete()) {
+                System.err.println(R("RCantDeleteFile", eMsg == null ? f : eMsg));
+            }
+        }
+    }
+
+    /**
+     * Tries to delete file f. If the file exists but couldn't be deleted,
+     * print an error message to stderr with the file name.
+     * @param f the file to be deleted
+     */
+    public static void deleteWithErrMesg(File f) {
+        deleteWithErrMesg(f, null);
+    }
+
+    /**
+     * Creates a new file or directory with minimum permissions. The file is not
+     * readable or writable by anyone other than the owner. If writeableByOnwer
+     * is false, even the owner can not write to it. If isDir is true, then the
+     * directory can be executed by the owner
+     *
+     * @throws IOException
+     */
+    private static void createRestrictedFile(File file, boolean isDir, boolean writableByOwner) throws IOException {
+
+        File tempFile = null;
+
+        tempFile = new File(file.getCanonicalPath() + ".temp");
+
+        if (isDir) {
+            if (!tempFile.mkdir()) {
+                throw new IOException(R("RCantCreateDir", tempFile));
+            }
+        } else {
+            if (!tempFile.createNewFile()) {
+                throw new IOException(R("RCantCreateFile", tempFile));
+            }
+        }
+
+        // remove all permissions
+        if (!Defaults.OS_DOS_LIKE) {
+            if (!tempFile.setExecutable(false, false)) {
+                throw new IOException(R("RRemoveXPermFailed", tempFile));
+            }
+            if (!tempFile.setReadable(false, false)) {
+                throw new IOException(R("RRemoveRPermFailed", tempFile));
+            }
+        }
+        if (!tempFile.setWritable(false, false)) {
+            throw new IOException(R("RRemoveWPermFailed", tempFile));
+        }
+
+        // allow owner to read
+        if (!tempFile.setReadable(true, true)) {
+            throw new IOException(R("RGetRPermFailed", tempFile));
+        }
+
+        // allow owner to write
+        if (writableByOwner && !tempFile.setWritable(true, true)) {
+            throw new IOException(R("RGetWPermFailed", tempFile));
+        }
+
+        // allow owner to enter directories
+        if (isDir && !tempFile.setExecutable(true, true)) {
+            throw new IOException(R("RGetXPermFailed", tempFile));
+        }
+
+        // rename this file. Unless the file is moved/renamed, any program that
+        // opened the file right after it was created might still be able to
+        // read the data.
+        if (Defaults.OS_DOS_LIKE) {
+            // On OS/2 and Windows, renameTo() fails if the target exists
+            // so delete it first
+            file.delete();
+        }
+        if (!tempFile.renameTo(file)) {
+            throw new IOException(R("RCantRename", tempFile, file));
+        }
+
+    }
+
+    /**
+     * Returns a String that is suitable for using in GUI elements for
+     * displaying (long) paths to users.
+     *
+     * @param path a path that should be shortened
+     * @return a shortened path suitable for displaying to the user
+     */
+    public static String displayablePath(String path) {
+        final int DEFAULT_LENGTH = 40;
+        return displayablePath(path, DEFAULT_LENGTH);
+    }
+
+    /**
+     * Return a String that is suitable for using in GUI elements for displaying
+     * paths to users. If the path is longer than visibleChars, it is truncated
+     * in a display-friendly way
+     *
+     * @param path a path that should be shorted
+     * @param visibleChars the maximum number of characters that path should fit
+     *        into. Also the length of the returned string
+     * @return a shortened path that contains limited number of chars
+     */
+    public static String displayablePath(String path, int visibleChars) {
+        /*
+         * use a very simple method: prefix + "..." + suffix
+         *
+         * where prefix is the beginning part of path (as much as we can squeeze in)
+         * and suffix is the end path of path
+         */
+
+        if (path == null || path.length() <= visibleChars) {
+            return path;
+        }
+
+        final String OMITTED = "...";
+        final int OMITTED_LENGTH = OMITTED.length();
+        final int MIN_PREFIX_LENGTH = 4;
+        final int MIN_SUFFIX_LENGTH = 4;
+        /*
+         * we want to show things other than OMITTED. if we have too few for
+         * suffix and prefix, then just return as much as we can of the filename
+         */
+        if (visibleChars < (OMITTED_LENGTH + MIN_PREFIX_LENGTH + MIN_SUFFIX_LENGTH)) {
+            return path.substring(path.length() - visibleChars);
+        }
+
+        int affixLength = (visibleChars - OMITTED_LENGTH) / 2;
+        String prefix = path.substring(0, affixLength);
+        String suffix = path.substring(path.length() - affixLength);
+
+        return prefix + OMITTED + suffix;
+    }
+
+    /**
+     * Recursively delete everything under a directory. Works on either files or
+     * directories
+     *
+     * @param file the file object representing what to delete. Can be either a
+     *        file or a directory.
+     * @param base the directory under which the file and its subdirectories must be located
+     * @throws IOException on an io exception or if trying to delete something
+     *         outside the base
+     */
+    public static void recursiveDelete(File file, File base) throws IOException {
+        if (JNLPRuntime.isDebug()) {
+            System.err.println("Deleting: " + file);
+        }
+
+        if (!(file.getCanonicalPath().startsWith(base.getCanonicalPath()))) {
+            throw new IOException("Trying to delete a file outside Netx's basedir: "
+                    + file.getCanonicalPath());
+        }
+
+        if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            for (int i = 0; i < children.length; i++) {
+                recursiveDelete(children[i], base);
+            }
+        }
+        if (!file.delete()) {
+            throw new IOException("Unable to delete file: " + file);
+        }
+
+    }
+
+    /**
+     * This will return a lock to the file specified.
+     * 
+     * @param path File path to file we want to lock.
+     * @param shared Specify if the lock will be a shared lock.
+     * @param allowBlock Specify if we should block when we can not get the
+     *            lock. Getting a shared lock will always block.
+     * @return FileLock if we were successful in getting a lock, otherwise null.
+     * @throws FileNotFoundException If the file does not exist.
+     */
+    public static FileLock getFileLock(String path, boolean shared, boolean allowBlock) throws FileNotFoundException {
+        // @todo temporary solution, see http://svn.netlabs.org/java/ticket/169
+        if (Defaults.OS_DOS_LIKE)
+            return null;
+        RandomAccessFile rafFile = new RandomAccessFile(path, "rw");
+        FileChannel fc = rafFile.getChannel();
+        FileLock lock = null;
+        try {
+            if (!shared) {
+                if (allowBlock) {
+                    lock = fc.lock(0, Long.MAX_VALUE, false);
+                } else {
+                    lock = fc.tryLock(0, Long.MAX_VALUE, false);
+                }
+            } else { // We want shared lock. This will block regardless if allowBlock is true or not.
+                // Test to see if we can get a shared lock.
+                lock = fc.lock(0, 1, true); // Block if a non exclusive lock is being held.
+                if (!lock.isShared()) { // This lock is an exclusive lock. Use alternate solution.
+                    FileLock tempLock = null;
+                    for (long pos = 1; tempLock == null && pos < Long.MAX_VALUE - 1; pos++) {
+                        tempLock = fc.tryLock(pos, 1, false);
+                    }
+                    lock.release();
+                    lock = tempLock; // Get the unique exclusive lock.
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return lock;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/PropertiesFile.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/PropertiesFile.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/PropertiesFile.java	(revision 403)
@@ -0,0 +1,147 @@
+// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.util;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * A properties object backed by a specified file without throwing
+ * exceptions.  The properties are automatically loaded from the
+ * file when the first property is requested, but the save method
+ * must be called before changes are saved to the file.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.4 $
+ */
+public class PropertiesFile extends Properties {
+
+    /** the file to save to */
+    File file;
+
+    /** the header string */
+    String header = "netx file";
+
+    /** lazy loaded on getProperty */
+    boolean loaded = false;
+
+    /**
+     * Create a properties object backed by the specified file.
+     *
+     * @param file the file to save and load to
+     */
+    public PropertiesFile(File file) {
+        this.file = file;
+    }
+
+    /**
+     * Create a properties object backed by the specified file.
+     *
+     * @param file the file to save and load to
+     * @param header the file header
+     */
+    public PropertiesFile(File file, String header) {
+        this.file = file;
+        this.header = header;
+    }
+
+    /**
+     * Returns the value of the specified key, or null if the key
+     * does not exist.
+     */
+    public String getProperty(String key) {
+        if (!loaded)
+            load();
+
+        return super.getProperty(key);
+    }
+
+    /**
+     * Returns the value of the specified key, or the default value
+     * if the key does not exist.
+     */
+    public String getProperty(String key, String defaultValue) {
+        if (!loaded)
+            load();
+
+        return super.getProperty(key, defaultValue);
+    }
+
+    /**
+     * Sets the value for the specified key.
+     *
+     * @return the previous value
+     */
+    public Object setProperty(String key, String value) {
+        if (!loaded)
+            load();
+
+        return super.setProperty(key, value);
+    }
+
+    /**
+     * Returns the file backing this properties object.
+     */
+    public File getStoreFile() {
+        return file;
+    }
+
+    /**
+     * Ensures that the file backing these properties has been
+     * loaded; call this method before calling any method defined by
+     * a superclass.
+     */
+    public void load() {
+        loaded = true;
+
+        InputStream s = null;
+        try {
+            if (!file.exists())
+                return;
+
+            try {
+                s = new FileInputStream(file);
+                load(s);
+            } finally {
+                if (s != null) s.close();
+            }
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * Saves the properties to the file.
+     */
+    public void store() {
+        if (!loaded)
+            return; // nothing could have changed so save unnecessary load/save
+
+        OutputStream s = null;
+        try {
+            try {
+                s = new FileOutputStream(file);
+                store(s, header);
+            } finally {
+                if (s != null) s.close();
+            }
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/Reflect.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/Reflect.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/Reflect.java	(revision 403)
@@ -0,0 +1,140 @@
+// Copyright (C) 2003 Jon A. Maxwell (JAM)
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program 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 for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.util;
+
+import java.lang.reflect.*;
+
+/**
+ * Provides simply, convenient methods to invoke methods by
+ * name.  This class is used to consolidate reflection needed to
+ * access methods specific to Sun's JVM or to remain backward
+ * compatible while supporting method in newer JVMs.<p>
+ *
+ * Most methods of this class invoke the first method on the
+ * specified object that matches the name and number of
+ * parameters.  The type of the parameters are not considered, so
+ * do not attempt to use this class to invoke overloaded
+ * methods.<p>
+ *
+ * Instances of this class are not synchronized.<p>
+ *
+ * @author <a href="mailto:jon.maxwell@acm.org">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.1 $
+ */
+public class Reflect {
+
+    // todo: check non-null parameter types, try to send to proper
+    // method if overloaded ones exist on the target object
+
+    // todo: optimize slightly using hashtable of Methods
+
+    private boolean accessible;
+
+    private static Object zero[] = new Object[0];
+
+    /**
+     * Create a new Reflect instance.
+     */
+    public Reflect() {
+        //
+    }
+
+    /**
+     * Create a new Reflect instance.
+     *
+     * @param accessible whether to bypass access permissions
+     */
+    public Reflect(boolean accessible) {
+        this.accessible = accessible;
+    }
+
+    /**
+     * Invoke a zero-parameter static method by name.
+     */
+    public Object invokeStatic(String className, String method) {
+        return invokeStatic(className, method, zero);
+    }
+
+    /**
+     * Invoke the static method using the specified parameters.
+     */
+    public Object invokeStatic(String className, String method, Object args[]) {
+        try {
+            Class c = Class.forName(className, true, Reflect.class.getClassLoader());
+
+            Method m = getMethod(c, method, args);
+            if (m.isAccessible() != accessible)
+                m.setAccessible(accessible);
+
+            return m.invoke(null, args);
+        } catch (Exception ex) { // eat
+            return null;
+        }
+    }
+
+    /**
+     * Invoke a zero-parameter method by name on the specified
+     * object.
+     */
+    public Object invoke(Object object, String method) {
+        return invoke(object, method, zero);
+    }
+
+    /**
+     * Invoke a method by name with the specified parameters.
+     *
+     * @return the result of the method, or null on exception.
+     */
+    public Object invoke(Object object, String method, Object args[]) {
+        try {
+            Method m = getMethod(object.getClass(), method, args);
+            if (m.isAccessible() != accessible)
+                m.setAccessible(accessible);
+
+            return m.invoke(object, args);
+        } catch (Exception ex) { // eat
+            ex.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * Return the Method matching the specified name and number of
+     * arguments.
+     */
+    public Method getMethod(Class type, String method, Object args[]) {
+        try {
+            for (Class c = type; c != null; c = c.getSuperclass()) {
+                Method methods[] = c.getMethods();
+
+                for (int i = 0; i < methods.length; i++) {
+                    if (methods[i].getName().equals(method)) {
+                        Class parameters[] = methods[i].getParameterTypes();
+
+                        if (parameters.length == args.length)
+                            return methods[i];
+                    }
+                }
+            }
+        } catch (Exception ex) { // eat
+            ex.printStackTrace();
+        }
+
+        return null;
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TeeOutputStream.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TeeOutputStream.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TeeOutputStream.java	(revision 403)
@@ -0,0 +1,95 @@
+/* TeeOutputStream.java
+   Copyright (C) 2010 Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.util;
+
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+/**
+ * Behaves like the 'tee' command, sends output to both actual std stream and a
+ * file
+ */
+public final class TeeOutputStream extends PrintStream {
+
+    // Everthing written to TeeOutputStream is written to this file
+    PrintStream logFile;
+
+    public TeeOutputStream(FileOutputStream fileOutputStream,
+            PrintStream stdStream) {
+        super(stdStream);
+        logFile = new PrintStream(fileOutputStream);
+    }
+
+    @Override
+    public boolean checkError() {
+        boolean thisError = super.checkError();
+        boolean fileError = logFile.checkError();
+
+        return thisError || fileError;
+    }
+
+    @Override
+    public void close() {
+        logFile.close();
+        super.close();
+    }
+
+    @Override
+    public void flush() {
+        logFile.flush();
+        super.flush();
+    }
+
+    /*
+     * The big ones: these do the actual writing
+     */
+
+    @Override
+    public void write(byte[] buf, int off, int len) {
+        logFile.write(buf, off, len);
+
+        super.write(buf, off, len);
+    }
+
+    @Override
+    public void write(int b) {
+        logFile.write(b);
+
+        super.write(b);
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TimedHashMap.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TimedHashMap.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/TimedHashMap.java	(revision 403)
@@ -0,0 +1,100 @@
+/* TimedHashMap.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package net.sourceforge.jnlp.util;
+
+import java.util.HashMap;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * Simple utility class that extends HashMap by adding an expiry to the entries.
+ *
+ * This map stores entries, and returns them only if the entries were last accessed within time t=10 seconds
+ *
+ * @param K The key type
+ * @param V The Object type
+ */
+public class TimedHashMap<K, V> {
+
+    HashMap<K,V> actualMap = new HashMap<K,V>();
+    HashMap<K, Long> timeStamps = new HashMap<K, Long>();
+    Long expiry = 10000000000L;
+
+    /**
+     * Store the item in the map and associate a timestamp with it
+     *
+     * @param key The key
+     * @param value The value to store
+     */
+    public V put(K key, V value) {
+        timeStamps.put(key, System.nanoTime());
+        return actualMap.put(key, value);
+    }
+
+    /**
+     * Return cached item if it has not already expired.
+     *
+     * Before returning, this method also resets the "last accessed"
+     * time for this entry, so it is good for another 10 seconds
+     *
+     * @param key The key
+     */
+    public V get(K key) {
+        Long now = System.nanoTime();
+
+        if (actualMap.containsKey(key)) {
+            Long age = now - timeStamps.get(key);
+
+            // Item exists. If it has not expired, renew its access time and return it
+            if (age <= expiry) {
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("Returning proxy " + actualMap.get(key) + " from cache for " + key);
+                }
+                timeStamps.put(key, System.nanoTime());
+                return actualMap.get(key);
+            } else {
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("Proxy cache for " + key + " has expired (age=" + (age * 1e-9) + " seconds)");
+                }
+            }
+        }
+
+        return null;
+    }
+}
+
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/UrlUtils.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/UrlUtils.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/UrlUtils.java	(revision 403)
@@ -0,0 +1,53 @@
+/* UrlUtils.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.util;
+
+import java.net.URL;
+
+public class UrlUtils {
+
+    public static boolean isLocalFile(URL url) {
+
+        if (url.getProtocol().equals("file") &&
+                (url.getAuthority() == null || url.getAuthority().equals("")) &&
+                (url.getHost() == null || url.getHost().equals(("")))) {
+            return true;
+        }
+        return false;
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/WeakList.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/WeakList.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/WeakList.java	(revision 403)
@@ -0,0 +1,123 @@
+// Copyright (C) 2002-2003 Jon A. Maxwell (JAM)
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.util;
+
+import java.lang.ref.*;
+import java.util.*;
+
+/**
+ * This list stores objects automatically using weak references.
+ * Objects are added and removed from the list as normal, but may
+ * turn to null at any point (ie, indexOf(x) followed by get(x)
+ * may return null).  The weak references are only removed when
+ * the trimToSize method is called so that the indices remain
+ * constant otherwise.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.3 $
+ */
+public class WeakList<E> extends AbstractList<E> {
+
+    /* list of weak references */
+    private ArrayList<WeakReference<E>> refs = new ArrayList<WeakReference<E>>();
+
+    /**
+     * Create a weak random-access list.
+     */
+    public WeakList() {
+    }
+
+    /**
+     * Extract the hard reference out of a weak reference.
+     */
+    private E deref(WeakReference<E> o) {
+        if (o != null)
+            return o.get();
+        else
+            return null;
+    }
+
+    /**
+     * Returns the object at the specified index, or null if the
+     * object has been collected.
+     */
+    public E get(int index) {
+        return deref(refs.get(index));
+    }
+
+    /**
+     * Returns the size of the list, including already collected
+     * objects.
+     */
+    public int size() {
+        return refs.size();
+    }
+
+    /**
+     * Sets the object at the specified position and returns the
+     * previous object at that position or null if it was already
+     * collected.
+     */
+    public E set(int index, E element) {
+        return deref(refs.set(index, new WeakReference<E>(element)));
+    }
+
+    /**
+     * Inserts the object at the specified position in the list.
+     * Automatically creates a weak reference to the object.
+     */
+    public void add(int index, E element) {
+        refs.add(index, new WeakReference<E>(element));
+    }
+
+    /**
+     * Removes the object at the specified position and returns it
+     * or returns null if it was already collected.
+     */
+    public E remove(int index) {
+        return deref(refs.remove(index));
+    }
+
+    /**
+     * Returns a list of hard references to the objects.  The
+     * returned list does not include the collected elements, so its
+     * indices do not necessarily correlate with those of this list.
+     */
+    public List<E> hardList() {
+        List<E> result = new ArrayList<E>();
+
+        for (int i = 0; i < size(); i++) {
+            E tmp = get(i);
+
+            if (tmp != null)
+                result.add(tmp);
+        }
+
+        return result;
+    }
+
+    /**
+     * Compacts the list by removing references to collected
+     * objects.
+     */
+    public void trimToSize() {
+        for (int i = size(); i-- > 0;)
+            if (get(i) == null)
+                remove(i);
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/XDesktopEntry.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/XDesktopEntry.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/jnlp/util/XDesktopEntry.java	(revision 403)
@@ -0,0 +1,237 @@
+// Copyright (C) 2009 Red Hat, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+package net.sourceforge.jnlp.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import net.sourceforge.jnlp.IconDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.StreamEater;
+import net.sourceforge.jnlp.cache.CacheUtil;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * This class builds a (freedesktop.org) desktop entry out of a {@link JNLPFile}
+ * . This entry can be used to install desktop shortcuts. See xdg-desktop-icon
+ * (1) and http://standards.freedesktop.org/desktop-entry-spec/latest/ for more
+ * information
+ *
+ * @author Omair Majid
+ *
+ */
+public class XDesktopEntry {
+
+    public static final String JAVA_ICON_NAME = "java";
+
+    private JNLPFile file = null;
+    private int iconSize = -1;
+    private String iconLocation = null;
+
+    private int[] VALID_ICON_SIZES = new int[] { 16, 22, 32, 48, 64, 128 };
+
+    /**
+     * Create a XDesktopEntry for the given JNLP file
+     *
+     * @param file a {@link JNLPFile} that indicates the application to launch
+     */
+    public XDesktopEntry(JNLPFile file) {
+        this.file = file;
+
+        /* looks like a good initial value */
+        iconSize = VALID_ICON_SIZES[2];
+    }
+
+    /**
+     * Returns the contents of the {@link XDesktopEntry} through the
+     * {@link Reader} interface.
+     */
+    public Reader getContentsAsReader() {
+
+        String cacheDir = JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR);
+        File cacheFile = CacheUtil.getCacheFile(file.getSourceLocation(), null);
+
+        String fileContents = "[Desktop Entry]\n";
+        fileContents += "Version=1.0\n";
+        fileContents += "Name=" + sanitize(file.getTitle()) + "\n";
+        fileContents += "GenericName=Java Web Start Application\n";
+        fileContents += "Comment=" + sanitize(file.getInformation().getDescription()) + "\n";
+        fileContents += "Type=Application\n";
+        if (iconLocation != null) {
+            fileContents += "Icon=" + iconLocation + "\n";
+        } else {
+            fileContents += "Icon=" + JAVA_ICON_NAME + "\n";
+
+        }
+        if (file.getInformation().getVendor() != null) {
+            fileContents += "Vendor=" + sanitize(file.getInformation().getVendor()) + "\n";
+        }
+
+        //Shortcut executes the jnlp from cache and system preferred java..
+        fileContents += "Exec=" + "javaws" + " \"" + cacheFile.getAbsolutePath() + "\"\n";
+
+        return new StringReader(fileContents);
+
+    }
+
+    /**
+     * Sanitizes a string so that it can be used safely in a key=value pair in a
+     * desktop entry file.
+     *
+     * @param input a String to sanitize
+     * @return a string safe to use as either the key or the value in the
+     * key=value pair in a desktop entry file
+     */
+    private static String sanitize(String input) {
+        if (input == null) {
+            return "";
+        }
+        /* key=value pairs must be a single line */
+        return input.split("\n")[0];
+    }
+
+    /**
+     * Get the size of the icon (in pixels) for the desktop shortcut
+     */
+    public int getIconSize() {
+        return iconSize;
+    }
+
+    /**
+     * Set the icon size to use for the desktop shortcut
+     *
+     * @param size the size (in pixels) of the icon to use. Commonly used sizes
+     *        are of 16, 22, 32, 48, 64 and 128
+     */
+    public void setIconSize(int size) {
+        iconSize = size;
+    }
+
+    /**
+     * Create a desktop shortcut for this desktop entry
+     */
+    public void createDesktopShortcut() {
+        try {
+            cacheIcon();
+            installDesktopLauncher();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Install this XDesktopEntry into the user's desktop as a launcher
+     */
+    private void installDesktopLauncher() {
+        File shortcutFile = new File(JNLPRuntime.getConfiguration()
+                .getProperty(DeploymentConfiguration.KEY_USER_TMP_DIR)
+                + File.separator + FileUtils.sanitizeFileName(file.getTitle()) + ".desktop");
+        try {
+
+            if (!shortcutFile.getParentFile().isDirectory() && !shortcutFile.getParentFile().mkdirs()) {
+                throw new IOException(shortcutFile.getParentFile().toString());
+            }
+
+            FileUtils.createRestrictedFile(shortcutFile, true);
+
+            /*
+             * Write out a Java String (UTF-16) as a UTF-8 file
+             */
+
+            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(shortcutFile),
+                    Charset.forName("UTF-8"));
+            Reader reader = getContentsAsReader();
+
+            char[] buffer = new char[1024];
+            int ret = 0;
+            while (-1 != (ret = reader.read(buffer))) {
+                writer.write(buffer, 0, ret);
+            }
+
+            reader.close();
+            writer.close();
+
+            /*
+             * Install the desktop entry
+             */
+
+            String[] execString = new String[] { "xdg-desktop-icon", "install", "--novendor",
+                    shortcutFile.getCanonicalPath() };
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Execing: " + Arrays.toString(execString));
+            }
+            Process installer = Runtime.getRuntime().exec(execString);
+            new StreamEater(installer.getInputStream()).start();
+            new StreamEater(installer.getErrorStream()).start();
+
+            try {
+                installer.waitFor();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            if (!shortcutFile.delete()) {
+                throw new IOException("Unable to delete temporary file:" + shortcutFile);
+            }
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Cache the icon for the desktop entry
+     */
+    private void cacheIcon() {
+
+        URL iconLocation = file.getInformation().getIconLocation(IconDesc.SHORTCUT, iconSize,
+                iconSize);
+
+        if (iconLocation == null) {
+            iconLocation = file.getInformation().getIconLocation(IconDesc.DEFAULT, iconSize,
+                    iconSize);
+        }
+
+        if (iconLocation != null) {
+            String location = CacheUtil.getCachedResource(iconLocation, null, UpdatePolicy.SESSION)
+                    .toString();
+            if (!location.startsWith("file:")) {
+                throw new RuntimeException("Unable to cache icon");
+            }
+
+            this.iconLocation = location.substring("file:".length());
+
+            if (JNLPRuntime.isDebug()) {
+                System.err.println("Cached desktop shortcut icon: " + this.iconLocation);
+            }
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLElement.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLElement.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLElement.java	(revision 403)
@@ -0,0 +1,1253 @@
+/* XMLElement.java
+ *
+ * $Revision: 1.2 $
+ * $Date: 2002/08/03 04:36:34 $
+ * $Name:  $
+ *
+ * This file is part of NanoXML 2 Lite.
+ * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from the
+ * use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ *  1. The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software in
+ *     a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *
+ *  2. Altered source versions must be plainly marked as such, and must not be
+ *     misrepresented as being the original software.
+ *
+ *  3. This notice may not be removed or altered from any source distribution.
+ *****************************************************************************/
+
+/* JAM: hacked the source to remove unneeded methods and comments. */
+
+package net.sourceforge.nanoxml;
+
+import java.io.*;
+import java.util.*;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * XMLElement is a representation of an XML object. The object is able to parse
+ * XML code.
+ * <P><DL>
+ * <DT><B>Parsing XML Data</B></DT>
+ * <DD>
+ * You can parse XML data using the following code:
+ * <UL><CODE>
+ * XMLElement xml = new XMLElement();<BR>
+ * FileReader reader = new FileReader("filename.xml");<BR>
+ * xml.parseFromReader(reader);
+ * </CODE></UL></DD></DL>
+ * <DL><DT><B>Retrieving Attributes</B></DT>
+ * <DD>
+ * You can enumerate the attributes of an element using the method
+ * {@link #enumerateAttributeNames() enumerateAttributeNames}.
+ * The attribute values can be retrieved using the method
+ * {@link #getAttribute(java.lang.String) getAttribute}.
+ * The following example shows how to list the attributes of an element:
+ * <UL><CODE>
+ * XMLElement element = ...;<BR>
+ * Enumeration enum = element.enumerateAttributeNames();<BR>
+ * while (enum.hasMoreElements()) {<BR>
+ * &nbsp;&nbsp;&nbsp;&nbsp;String key = (String) enum.nextElement();<BR>
+ * &nbsp;&nbsp;&nbsp;&nbsp;String value = (String) element.getAttribute(key);<BR>
+ * &nbsp;&nbsp;&nbsp;&nbsp;System.out.println(key + " = " + value);<BR>
+ * }
+ * </CODE></UL></DD></DL>
+ * <DL><DT><B>Retrieving Child Elements</B></DT>
+ * <DD>
+ * You can enumerate the children of an element using
+ * {@link #enumerateChildren() enumerateChildren}.
+ * The number of child elements can be retrieved using
+ * {@link #countChildren() countChildren}.
+ * </DD></DL>
+ * <DL><DT><B>Elements Containing Character Data</B></DT>
+ * <DD>
+ * If an elements contains character data, like in the following example:
+ * <UL><CODE>
+ * &lt;title&gt;The Title&lt;/title&gt;
+ * </CODE></UL>
+ * you can retrieve that data using the method
+ * {@link #getContent() getContent}.
+ * </DD></DL>
+ * <DL><DT><B>Subclassing XMLElement</B></DT>
+ * <DD>
+ * When subclassing XMLElement, you need to override the method
+ * {@link #createAnotherElement() createAnotherElement}
+ * which has to return a new copy of the receiver.
+ * </DD></DL>
+ * <P>
+ *
+ * @see net.sourceforge.nanoxml.XMLParseException
+ *
+ * @author Marc De Scheemaecker
+ *         &lt;<A href="mailto:cyberelf@mac.com">cyberelf@mac.com</A>&gt;
+ * @version $Name:  $, $Revision: 1.2 $
+ */
+public class XMLElement {
+
+    /**
+     * The attributes given to the element.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field can be empty.
+     *     <li>The field is never <code>null</code>.
+     *     <li>The keys and the values are strings.
+     * </ul></dd></dl>
+     */
+    private Hashtable<String, Object> attributes;
+
+    /**
+     * Child elements of the element.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field can be empty.
+     *     <li>The field is never <code>null</code>.
+     *     <li>The elements are instances of <code>XMLElement</code>
+     *         or a subclass of <code>XMLElement</code>.
+     * </ul></dd></dl>
+     */
+    private Vector<XMLElement> children;
+
+    /**
+     * The name of the element.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field is <code>null</code> iff the element is not
+     *         initialized by either parse or setName.
+     *     <li>If the field is not <code>null</code>, it's not empty.
+     *     <li>If the field is not <code>null</code>, it contains a valid
+     *         XML identifier.
+     * </ul></dd></dl>
+     */
+    private String name;
+
+    /**
+     * The #PCDATA content of the object.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field is <code>null</code> iff the element is not a
+     *         #PCDATA element.
+     *     <li>The field can be any string, including the empty string.
+     * </ul></dd></dl>
+     */
+    private String contents;
+
+    /**
+     * Conversion table for &amp;...; entities. The keys are the entity names
+     * without the &amp; and ; delimiters.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field is never <code>null</code>.
+     *     <li>The field always contains the following associations:
+     *         "lt"&nbsp;=&gt;&nbsp;"&lt;", "gt"&nbsp;=&gt;&nbsp;"&gt;",
+     *         "quot"&nbsp;=&gt;&nbsp;"\"", "apos"&nbsp;=&gt;&nbsp;"'",
+     *         "amp"&nbsp;=&gt;&nbsp;"&amp;"
+     *     <li>The keys are strings
+     *     <li>The values are char arrays
+     * </ul></dd></dl>
+     */
+    private Hashtable<String, char[]> entities;
+
+    /**
+     * The line number where the element starts.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li><code>lineNr &gt= 0</code>
+     * </ul></dd></dl>
+     */
+    private int lineNr;
+
+    /**
+     * <code>true</code> if the case of the element and attribute names
+     * are case insensitive.
+     */
+    private boolean ignoreCase;
+
+    /**
+     * <code>true</code> if the leading and trailing whitespace of #PCDATA
+     * sections have to be ignored.
+     */
+    private boolean ignoreWhitespace;
+
+    /**
+     * Character read too much.
+     * This character provides push-back functionality to the input reader
+     * without having to use a PushbackReader.
+     * If there is no such character, this field is '\0'.
+     */
+    private char charReadTooMuch;
+
+    /**
+     * Character read too much for the comment remover.
+     */
+    private char sanitizeCharReadTooMuch;
+
+    /**
+     * The reader provided by the caller of the parse method.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>The field is not <code>null</code> while the parse method
+     *         is running.
+     * </ul></dd></dl>
+     */
+    private Reader reader;
+
+    /**
+     * The current line number in the source content.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li>parserLineNr &gt; 0 while the parse method is running.
+     * </ul></dd></dl>
+     */
+    private int parserLineNr;
+
+    /**
+     * Creates and initializes a new XML element.
+     * Calling the construction is equivalent to:
+     * <ul><code>new XMLElement(new Hashtable(), false, true)
+     * </code></ul>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>countChildren() => 0
+     *     <li>enumerateChildren() => empty enumeration
+     *     <li>enumeratePropertyNames() => empty enumeration
+     *     <li>getChildren() => empty vector
+     *     <li>getContent() => ""
+     *     <li>getLineNr() => 0
+     *     <li>getName() => null
+     * </ul></dd></dl>
+     *
+     */
+    public XMLElement() {
+        this(new Hashtable<String, char[]>(), false, true, true);
+    }
+
+    /**
+     * Creates and initializes a new XML element.
+     * <P>
+     * This constructor should <I>only</I> be called from
+     * {@link #createAnotherElement() createAnotherElement}
+     * to create child elements.
+     *
+     * @param entities
+     *     The entity conversion table.
+     * @param skipLeadingWhitespace
+     *     <code>true</code> if leading and trailing whitespace in PCDATA
+     *     content has to be removed.
+     * @param fillBasicConversionTable
+     *     <code>true</code> if the basic entities need to be added to
+     *     the entity list (client code calling this constructor).
+     * @param ignoreCase
+     *     <code>true</code> if the case of element and attribute names have
+     *     to be ignored.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>entities != null</code>
+     *     <li>if <code>fillBasicConversionTable == false</code>
+     *         then <code>entities</code> contains at least the following
+     *         entries: <code>amp</code>, <code>lt</code>, <code>gt</code>,
+     *         <code>apos</code> and <code>quot</code>
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>countChildren() => 0
+     *     <li>enumerateChildren() => empty enumeration
+     *     <li>enumeratePropertyNames() => empty enumeration
+     *     <li>getChildren() => empty vector
+     *     <li>getContent() => ""
+     *     <li>getLineNr() => 0
+     *     <li>getName() => null
+     * </ul></dd></dl><dl>
+     *
+     */
+    protected XMLElement(Hashtable<String, char[]> entities,
+                         boolean skipLeadingWhitespace,
+                         boolean fillBasicConversionTable,
+                         boolean ignoreCase) {
+        this.ignoreWhitespace = skipLeadingWhitespace;
+        this.ignoreCase = ignoreCase;
+        this.name = null;
+        this.contents = "";
+        this.attributes = new Hashtable<String, Object>();
+        this.children = new Vector<XMLElement>();
+        this.entities = entities;
+        this.lineNr = 0;
+        Enumeration<String> e = this.entities.keys();
+        while (e.hasMoreElements()) {
+            String key = e.nextElement();
+            Object value = this.entities.get(key);
+            if (value instanceof String) {
+                entities.put(key, ((String) value).toCharArray());
+            }
+        }
+        if (fillBasicConversionTable) {
+            this.entities.put("amp", new char[] { '&' });
+            this.entities.put("quot", new char[] { '"' });
+            this.entities.put("apos", new char[] { '\'' });
+            this.entities.put("lt", new char[] { '<' });
+            this.entities.put("gt", new char[] { '>' });
+        }
+    }
+
+    /**
+     * Adds a child element.
+     *
+     * @param child
+     *     The child element to add.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>child != null</code>
+     *     <li><code>child.getName() != null</code>
+     *     <li><code>child</code> does not have a parent element
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>countChildren() => old.countChildren() + 1
+     *     <li>enumerateChildren() => old.enumerateChildren() + child
+     *     <li>getChildren() => old.enumerateChildren() + child
+     * </ul></dd></dl><dl>
+     *
+     */
+    public void addChild(XMLElement child) {
+        this.children.addElement(child);
+    }
+
+    /**
+     * Adds or modifies an attribute.
+     *
+     * @param name
+     *     The name of the attribute.
+     * @param value
+     *     The value of the attribute.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     *     <li><code>name</code> is a valid XML identifier
+     *     <li><code>value != null</code>
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>enumerateAttributeNames()
+     *         => old.enumerateAttributeNames() + name
+     *     <li>getAttribute(name) => value
+     * </ul></dd></dl><dl>
+     *
+     */
+    public void setAttribute(String name,
+                             Object value) {
+        if (this.ignoreCase) {
+            name = name.toUpperCase();
+        }
+        this.attributes.put(name, value.toString());
+    }
+
+    /**
+     * Returns the number of child elements of the element.
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li><code>result >= 0</code>
+     * </ul></dd></dl>
+     *
+     */
+    public int countChildren() {
+        return this.children.size();
+    }
+
+    /**
+     * Enumerates the attribute names.
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li><code>result != null</code>
+     * </ul></dd></dl>
+     *
+     */
+    public Enumeration enumerateAttributeNames() {
+        return this.attributes.keys();
+    }
+
+    /**
+     * Enumerates the child elements.
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li><code>result != null</code>
+     * </ul></dd></dl>
+     *
+     */
+    public Enumeration enumerateChildren() {
+        return this.children.elements();
+    }
+
+    /**
+     * Returns the PCDATA content of the object. If there is no such content,
+     * <CODE>null</CODE> is returned.
+     *
+     */
+    public String getContent() {
+        return this.contents;
+    }
+
+    /**
+     * Returns the line nr in the source data on which the element is found.
+     * This method returns <code>0</code> there is no associated source data.
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li><code>result >= 0</code>
+     * </ul></dd></dl>
+     */
+    public int getLineNr() {
+        return this.lineNr;
+    }
+
+    /**
+     * Returns an attribute of the element.
+     * If the attribute doesn't exist, <code>null</code> is returned.
+     *
+     * @param name The name of the attribute.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     *     <li><code>name</code> is a valid XML identifier
+     * </ul></dd></dl><dl>
+     *
+     */
+    public Object getAttribute(String name) {
+        if (this.ignoreCase) {
+            name = name.toUpperCase();
+        }
+        Object value = this.attributes.get(name);
+        return value;
+    }
+
+    /**
+     * Returns the name of the element.
+     *
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Reads one XML element from a java.io.Reader and parses it.
+     *
+     * @param reader
+     *     The reader from which to retrieve the XML data.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>reader != null</code>
+     *     <li><code>reader</code> is not closed
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>the state of the receiver is updated to reflect the XML element
+     *         parsed from the reader
+     *     <li>the reader points to the first character following the last
+     *         '&gt;' character of the XML element
+     * </ul></dd></dl><dl>
+     *
+     * @throws java.io.IOException
+     *     If an error occured while reading the input.
+     * @throws net.sourceforge.nanoxml.XMLParseException
+     *     If an error occured while parsing the read data.
+     */
+    public void parseFromReader(Reader reader)
+            throws IOException, XMLParseException {
+        this.parseFromReader(reader, /*startingLineNr*/1);
+    }
+
+    /**
+     * Reads one XML element from a java.io.Reader and parses it.
+     *
+     * @param reader
+     *     The reader from which to retrieve the XML data.
+     * @param startingLineNr
+     *     The line number of the first line in the data.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>reader != null</code>
+     *     <li><code>reader</code> is not closed
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>the state of the receiver is updated to reflect the XML element
+     *         parsed from the reader
+     *     <li>the reader points to the first character following the last
+     *         '&gt;' character of the XML element
+     * </ul></dd></dl><dl>
+     *
+     * @throws java.io.IOException
+     *     If an error occured while reading the input.
+     * @throws net.sourceforge.nanoxml.XMLParseException
+     *     If an error occured while parsing the read data.
+     */
+    public void parseFromReader(Reader reader,
+                                int startingLineNr)
+            throws IOException, XMLParseException {
+        this.charReadTooMuch = '\0';
+        this.reader = reader;
+        this.parserLineNr = startingLineNr;
+
+        for (;;) {
+            char ch = this.scanWhitespace();
+
+            if (ch != '<') {
+                throw this.expectedInput("<", ch);
+            }
+
+            ch = this.readChar();
+
+            if ((ch == '!') || (ch == '?')) {
+                this.skipSpecialTag(0);
+            } else {
+                this.unreadChar(ch);
+                this.scanElement(this);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Creates a new similar XML element.
+     * <P>
+     * You should override this method when subclassing XMLElement.
+     */
+    protected XMLElement createAnotherElement() {
+        return new XMLElement(this.entities,
+                              this.ignoreWhitespace,
+                              false,
+                              this.ignoreCase);
+    }
+
+    /**
+     * Changes the content string.
+     *
+     * @param content
+     *     The new content string.
+     */
+    public void setContent(String content) {
+        this.contents = content;
+    }
+
+    /**
+     * Changes the name of the element.
+     *
+     * @param name
+     *     The new name.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     *     <li><code>name</code> is a valid XML identifier
+     * </ul></dd></dl>
+     *
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Scans an identifier from the current reader.
+     * The scanned identifier is appended to <code>result</code>.
+     *
+     * @param result
+     *     The buffer in which the scanned identifier will be put.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>result != null</code>
+     *     <li>The next character read from the reader is a valid first
+     *         character of an XML identifier.
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>The next character read from the reader won't be an identifier
+     *         character.
+     * </ul></dd></dl><dl>
+     */
+    protected void scanIdentifier(StringBuffer result)
+            throws IOException {
+        for (;;) {
+            char ch = this.readChar();
+            if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z'))
+                    && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.')
+                    && (ch != ':') && (ch != '-') && (ch <= '\u007E')) {
+                this.unreadChar(ch);
+                return;
+            }
+            result.append(ch);
+        }
+    }
+
+    /**
+     * This method scans an identifier from the current reader.
+     *
+     * @return the next character following the whitespace.
+     */
+    protected char scanWhitespace()
+            throws IOException {
+        for (;;) {
+            char ch = this.readChar();
+            switch (ch) {
+                case ' ':
+                case '\t':
+                case '\n':
+                case '\r':
+                    break;
+                default:
+                    return ch;
+            }
+        }
+    }
+
+    /**
+     * This method scans an identifier from the current reader.
+     * The scanned whitespace is appended to <code>result</code>.
+     *
+     * @return the next character following the whitespace.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>result != null</code>
+     * </ul></dd></dl>
+     */
+    protected char scanWhitespace(StringBuffer result)
+            throws IOException {
+        for (;;) {
+            char ch = this.readChar();
+            switch (ch) {
+                case ' ':
+                case '\t':
+                case '\n':
+                    result.append(ch);
+                    break;
+                case '\r':
+                    break;
+                default:
+                    return ch;
+            }
+        }
+    }
+
+    /**
+     * This method scans a delimited string from the current reader.
+     * The scanned string without delimiters is appended to
+     * <code>string</code>.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>string != null</code>
+     *     <li>the next char read is the string delimiter
+     * </ul></dd></dl>
+     */
+    protected void scanString(StringBuffer string)
+            throws IOException {
+        char delimiter = this.readChar();
+        if ((delimiter != '\'') && (delimiter != '"')) {
+            throw this.expectedInput("' or \"");
+        }
+        for (;;) {
+            char ch = this.readChar();
+            if (ch == delimiter) {
+                return;
+            } else if (ch == '&') {
+                this.resolveEntity(string);
+            } else {
+                string.append(ch);
+            }
+        }
+    }
+
+    /**
+     * Scans a #PCDATA element. CDATA sections and entities are resolved.
+     * The next &lt; char is skipped.
+     * The scanned data is appended to <code>data</code>.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>data != null</code>
+     * </ul></dd></dl>
+     */
+    protected void scanPCData(StringBuffer data)
+            throws IOException {
+        for (;;) {
+            char ch = this.readChar();
+            if (ch == '<') {
+                ch = this.readChar();
+                if (ch == '!') {
+                    this.checkCDATA(data);
+                } else {
+                    this.unreadChar(ch);
+                    return;
+                }
+            } else if (ch == '&') {
+                this.resolveEntity(data);
+            } else {
+                data.append(ch);
+            }
+        }
+    }
+
+    /**
+     * Scans a special tag and if the tag is a CDATA section, append its
+     * content to <code>buf</code>.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>buf != null</code>
+     *     <li>The first &lt; has already been read.
+     * </ul></dd></dl>
+     */
+    protected boolean checkCDATA(StringBuffer buf)
+            throws IOException {
+        char ch = this.readChar();
+        if (ch != '[') {
+            this.unreadChar(ch);
+            this.skipSpecialTag(0);
+            return false;
+        } else if (!this.checkLiteral("CDATA[")) {
+            this.skipSpecialTag(1); // one [ has already been read
+            return false;
+        } else {
+            int delimiterCharsSkipped = 0;
+            while (delimiterCharsSkipped < 3) {
+                ch = this.readChar();
+                switch (ch) {
+                    case ']':
+                        if (delimiterCharsSkipped < 2) {
+                            delimiterCharsSkipped += 1;
+                        } else {
+                            buf.append(']');
+                            buf.append(']');
+                            delimiterCharsSkipped = 0;
+                        }
+                        break;
+                    case '>':
+                        if (delimiterCharsSkipped < 2) {
+                            for (int i = 0; i < delimiterCharsSkipped; i++) {
+                                buf.append(']');
+                            }
+                            delimiterCharsSkipped = 0;
+                            buf.append('>');
+                        } else {
+                            delimiterCharsSkipped = 3;
+                        }
+                        break;
+                    default:
+                        for (int i = 0; i < delimiterCharsSkipped; i += 1) {
+                            buf.append(']');
+                        }
+                        buf.append(ch);
+                        delimiterCharsSkipped = 0;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Skips a comment.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li>The first &lt;!-- has already been read.
+     * </ul></dd></dl>
+     */
+    protected void skipComment()
+            throws IOException {
+        int dashesToRead = 2;
+        while (dashesToRead > 0) {
+            char ch = this.readChar();
+            if (ch == '-') {
+                dashesToRead -= 1;
+            } else {
+                dashesToRead = 2;
+            }
+
+            // Be more tolerant of extra -- (double dashes)
+            // in comments.
+            if (dashesToRead == 0) {
+                ch = this.readChar();
+                if (ch == '>') {
+                    return;
+                } else {
+                    dashesToRead = 2;
+                    this.unreadChar(ch);
+                }
+            }
+        }
+        /*
+        if (this.readChar() != '>') {
+            throw this.expectedInput(">");
+        }
+        */
+    }
+
+    /**
+     * Skips a special tag or comment.
+     *
+     * @param bracketLevel The number of open square brackets ([) that have
+     *                     already been read.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li>The first &lt;! has already been read.
+     *     <li><code>bracketLevel >= 0</code>
+     * </ul></dd></dl>
+     */
+    protected void skipSpecialTag(int bracketLevel)
+            throws IOException {
+        int tagLevel = 1; // <
+        char stringDelimiter = '\0';
+        if (bracketLevel == 0) {
+            char ch = this.readChar();
+            if (ch == '[') {
+                bracketLevel += 1;
+            } else if (ch == '-') {
+                ch = this.readChar();
+                if (ch == '[') {
+                    bracketLevel += 1;
+                } else if (ch == ']') {
+                    bracketLevel -= 1;
+                } else if (ch == '-') {
+                    this.skipComment();
+                    return;
+                }
+            }
+        }
+        while (tagLevel > 0) {
+            char ch = this.readChar();
+            if (stringDelimiter == '\0') {
+                if ((ch == '"') || (ch == '\'')) {
+                    stringDelimiter = ch;
+                } else if (bracketLevel <= 0) {
+                    if (ch == '<') {
+                        tagLevel += 1;
+                    } else if (ch == '>') {
+                        tagLevel -= 1;
+                    }
+                }
+                if (ch == '[') {
+                    bracketLevel += 1;
+                } else if (ch == ']') {
+                    bracketLevel -= 1;
+                }
+            } else {
+                if (ch == stringDelimiter) {
+                    stringDelimiter = '\0';
+                }
+            }
+        }
+    }
+
+    /**
+     * Scans the data for literal text.
+     * Scanning stops when a character does not match or after the complete
+     * text has been checked, whichever comes first.
+     *
+     * @param literal the literal to check.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>literal != null</code>
+     * </ul></dd></dl>
+     */
+    protected boolean checkLiteral(String literal)
+            throws IOException {
+        int length = literal.length();
+        for (int i = 0; i < length; i += 1) {
+            if (this.readChar() != literal.charAt(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Reads a character from a reader.
+     */
+    protected char readChar()
+            throws IOException {
+        if (this.charReadTooMuch != '\0') {
+            char ch = this.charReadTooMuch;
+            this.charReadTooMuch = '\0';
+            return ch;
+        } else {
+            int i = this.reader.read();
+            if (i < 0) {
+                throw this.unexpectedEndOfData();
+            } else if (i == 10) {
+                this.parserLineNr += 1;
+                return '\n';
+            } else {
+                return (char) i;
+            }
+        }
+    }
+
+    /**
+     * Scans an XML element.
+     *
+     * @param elt The element that will contain the result.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li>The first &lt; has already been read.
+     *     <li><code>elt != null</code>
+     * </ul></dd></dl>
+     */
+    protected void scanElement(XMLElement elt)
+            throws IOException {
+        StringBuffer buf = new StringBuffer();
+        this.scanIdentifier(buf);
+        String name = buf.toString();
+        elt.setName(name);
+        char ch = this.scanWhitespace();
+        while ((ch != '>') && (ch != '/')) {
+            buf.setLength(0);
+            this.unreadChar(ch);
+            this.scanIdentifier(buf);
+            String key = buf.toString();
+            ch = this.scanWhitespace();
+            if (ch != '=') {
+                throw this.expectedInput("=");
+            }
+            this.unreadChar(this.scanWhitespace());
+            buf.setLength(0);
+            this.scanString(buf);
+            elt.setAttribute(key, buf);
+            ch = this.scanWhitespace();
+        }
+        if (ch == '/') {
+            ch = this.readChar();
+            if (ch != '>') {
+                throw this.expectedInput(">");
+            }
+            return;
+        }
+        buf.setLength(0);
+        ch = this.scanWhitespace(buf);
+        if (ch != '<') {
+            this.unreadChar(ch);
+            this.scanPCData(buf);
+        } else {
+            for (;;) {
+                ch = this.readChar();
+                if (ch == '!') {
+                    if (this.checkCDATA(buf)) {
+                        this.scanPCData(buf);
+                        break;
+                    } else {
+                        ch = this.scanWhitespace(buf);
+                        if (ch != '<') {
+                            this.unreadChar(ch);
+                            this.scanPCData(buf);
+                            break;
+                        }
+                    }
+                } else {
+                    buf.setLength(0);
+                    break;
+                }
+            }
+        }
+        if (buf.length() == 0) {
+            while (ch != '/') {
+                if (ch == '!') {
+                    ch = this.readChar();
+                    if (ch != '-') {
+                        throw this.expectedInput("Comment or Element");
+                    }
+                    ch = this.readChar();
+                    if (ch != '-') {
+                        throw this.expectedInput("Comment or Element");
+                    }
+                    this.skipComment();
+                } else {
+                    this.unreadChar(ch);
+                    XMLElement child = this.createAnotherElement();
+                    this.scanElement(child);
+                    elt.addChild(child);
+                }
+                ch = this.scanWhitespace();
+                if (ch != '<') {
+                    throw this.expectedInput("<");
+                }
+                ch = this.readChar();
+            }
+            this.unreadChar(ch);
+        } else {
+            if (this.ignoreWhitespace) {
+                elt.setContent(buf.toString().trim());
+            } else {
+                elt.setContent(buf.toString());
+            }
+        }
+        ch = this.readChar();
+        if (ch != '/') {
+            throw this.expectedInput("/");
+        }
+        this.unreadChar(this.scanWhitespace());
+        if (!this.checkLiteral(name)) {
+            throw this.expectedInput(name);
+        }
+        if (this.scanWhitespace() != '>') {
+            throw this.expectedInput(">");
+        }
+    }
+
+    /**
+     * Resolves an entity. The name of the entity is read from the reader.
+     * The value of the entity is appended to <code>buf</code>.
+     *
+     * @param buf Where to put the entity value.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li>The first &amp; has already been read.
+     *     <li><code>buf != null</code>
+     * </ul></dd></dl>
+     */
+    protected void resolveEntity(StringBuffer buf)
+            throws IOException {
+        char ch = '\0';
+        StringBuffer keyBuf = new StringBuffer();
+        for (;;) {
+            ch = this.readChar();
+            if (ch == ';') {
+                break;
+            }
+            keyBuf.append(ch);
+        }
+        String key = keyBuf.toString();
+        if (key.charAt(0) == '#') {
+            try {
+                if (key.charAt(1) == 'x') {
+                    ch = (char) Integer.parseInt(key.substring(2), 16);
+                } else {
+                    ch = (char) Integer.parseInt(key.substring(1), 10);
+                }
+            } catch (NumberFormatException e) {
+                throw this.unknownEntity(key);
+            }
+            buf.append(ch);
+        } else {
+            char[] value = entities.get(key);
+            if (value == null) {
+                throw this.unknownEntity(key);
+            }
+            buf.append(value);
+        }
+    }
+
+    /**
+     * Pushes a character back to the read-back buffer.
+     *
+     * @param ch The character to push back.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li>The read-back buffer is empty.
+     *     <li><code>ch != '\0'</code>
+     * </ul></dd></dl>
+     */
+    protected void unreadChar(char ch) {
+        this.charReadTooMuch = ch;
+    }
+
+    /**
+     * Creates a parse exception for when an invalid valueset is given to
+     * a method.
+     *
+     * @param name The name of the entity.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException invalidValueSet(String name) {
+        String msg = "Invalid value set (entity name = \"" + name + "\")";
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when an invalid value is given to a
+     * method.
+     *
+     * @param name  The name of the entity.
+     * @param value The value of the entity.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     *     <li><code>value != null</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException invalidValue(String name,
+                                             String value) {
+        String msg = "Attribute \"" + name + "\" does not contain a valid "
+                   + "value (\"" + value + "\")";
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when the end of the data input has been
+     * reached.
+     */
+    protected XMLParseException unexpectedEndOfData() {
+        String msg = "Unexpected end of data reached";
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when a syntax error occured.
+     *
+     * @param context The context in which the error occured.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>context != null</code>
+     *     <li><code>context.length() &gt; 0</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException syntaxError(String context) {
+        String msg = "Syntax error while parsing " + context;
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when the next character read is not
+     * the character that was expected.
+     *
+     * @param charSet The set of characters (in human readable form) that was
+     *                expected.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>charSet != null</code>
+     *     <li><code>charSet.length() &gt; 0</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException expectedInput(String charSet) {
+        String msg = "Expected: " + charSet;
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when the next character read is not
+     * the character that was expected.
+     *
+     * @param charSet The set of characters (in human readable form) that was
+     *                expected.
+     * @param ch The character that was received instead.
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>charSet != null</code>
+     *     <li><code>charSet.length() &gt; 0</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException expectedInput(String charSet, char ch) {
+        String msg = "Expected: '" + charSet + "'" + " but got: '" + ch + "'";
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Creates a parse exception for when an entity could not be resolved.
+     *
+     * @param name The name of the entity.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>name != null</code>
+     *     <li><code>name.length() &gt; 0</code>
+     * </ul></dd></dl>
+     */
+    protected XMLParseException unknownEntity(String name) {
+        String msg = "Unknown or invalid entity: &" + name + ";";
+        return new XMLParseException(this.getName(), this.parserLineNr, msg);
+    }
+
+    /**
+     * Reads an xml file and removes the comments, leaving only relevant
+     * xml code.
+     *
+     * @param isr The reader of the InputStream containing the xml.
+     * @param pout The PipedOutputStream that will be receiving the filtered
+     *             xml file.
+     */
+    public void sanitizeInput(InputStreamReader isr, PipedOutputStream pout) {
+        try {
+            PrintStream out = new PrintStream(pout);
+
+            this.sanitizeCharReadTooMuch = '\0';
+            this.reader = isr;
+            this.parserLineNr = 0;
+            int newline = 2;
+            char prev = ' ';
+
+            while (true) {
+                char ch;
+                if (this.sanitizeCharReadTooMuch != '\0') {
+                    ch = this.sanitizeCharReadTooMuch;
+                    this.sanitizeCharReadTooMuch = '\0';
+                } else {
+
+                    int i = this.reader.read();
+                    if (i == -1) {
+                        // no character in buffer, and nothing read
+                        out.flush();
+                        break;
+                    } else if (i == 10) {
+                        ch = '\n';
+                    } else {
+                        ch = (char) i;
+                    }
+                }
+
+                char next;
+                int i = this.reader.read();
+                if (i == -1) {
+                    // character in buffer and nothing read. write out
+                    // what's in the buffer
+                    out.print(ch);
+                    out.flush();
+                    if (JNLPRuntime.isDebug()) {
+                        if (ch == 10) {
+                            System.out.println();
+                            System.out.print("line: " + newline + " ");
+                            newline++;
+                        } else {
+                            System.out.print(ch);
+                        }
+                    }
+                    break;
+                } else if (i == 10) {
+                    next = '\n';
+                } else {
+                    next = (char) i;
+                }
+
+                this.sanitizeCharReadTooMuch = next;
+
+                // If the next char is a ? or !, then we've hit a special tag,
+                // and should skip it.
+                if (prev == '<' && (next == '!' || next == '?')) {
+                    this.skipSpecialTag(0);
+                    this.sanitizeCharReadTooMuch = '\0';
+                }
+                // Otherwise we haven't hit a comment, and we should write ch.
+                else {
+                    out.print(ch);
+                    if (JNLPRuntime.isDebug()) {
+                        if (ch == 10) {
+                            System.out.println();
+                            System.out.print("line: " + newline + " ");
+                            newline++;
+                        } else {
+                            System.out.print(ch);
+                        }
+                    }
+                }
+                prev = next;
+            }
+
+            out.close();
+            isr.close();
+        } catch (Exception e) {
+            // Print the stack trace here -- xml.parseFromReader() will
+            // throw the ParseException if something goes wrong.
+            e.printStackTrace();
+        }
+    }
+}
Index: /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLParseException.java
===================================================================
--- /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLParseException.java	(revision 403)
+++ /tags/icedtea-web/beta/netx/net/sourceforge/nanoxml/XMLParseException.java	(revision 403)
@@ -0,0 +1,120 @@
+/* XMLParseException.java
+ *
+ * $Revision: 1.1 $
+ * $Date: 2002/08/03 04:05:32 $
+ * $Name:  $
+ *
+ * This file is part of NanoXML 2 Lite.
+ * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from the
+ * use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ *  1. The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software in
+ *     a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *
+ *  2. Altered source versions must be plainly marked as such, and must not be
+ *     misrepresented as being the original software.
+ *
+ *  3. This notice may not be removed or altered from any source distribution.
+ *****************************************************************************/
+
+package net.sourceforge.nanoxml;
+
+/**
+ * An XMLParseException is thrown when an error occures while parsing an XML
+ * string.
+ * <P>
+ * $Revision: 1.1 $<BR>
+ * $Date: 2002/08/03 04:05:32 $<P>
+ *
+ * @see net.sourceforge.nanoxml.XMLElement
+ *
+ * @author Marc De Scheemaecker
+ * @version $Name:  $, $Revision: 1.1 $
+ */
+public class XMLParseException
+        extends RuntimeException {
+
+    /**
+     * Indicates that no line number has been associated with this exception.
+     */
+    public static final int NO_LINE = -1;
+
+    /**
+     * The line number in the source code where the error occurred, or
+     * <code>NO_LINE</code> if the line number is unknown.
+     *
+     * <dl><dt><b>Invariants:</b></dt><dd>
+     * <ul><li><code>lineNr &gt 0 || lineNr == NO_LINE</code>
+     * </ul></dd></dl>
+     */
+    private int lineNr;
+
+    /**
+     * Creates an exception.
+     *
+     * @param name    The name of the element where the error is located.
+     * @param message A message describing what went wrong.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>message != null</code>
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>getLineNr() => NO_LINE
+     * </ul></dd></dl><dl>
+     */
+    public XMLParseException(String name,
+                             String message) {
+        super("XML Parse Exception during parsing of "
+                + ((name == null) ? "the XML definition"
+                                : ("a " + name + " element"))
+                + ": " + message);
+        this.lineNr = XMLParseException.NO_LINE;
+    }
+
+    /**
+     * Creates an exception.
+     *
+     * @param name    The name of the element where the error is located.
+     * @param lineNr  The number of the line in the input.
+     * @param message A message describing what went wrong.
+     *
+     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+     * <ul><li><code>message != null</code>
+     *     <li><code>lineNr &gt; 0</code>
+     * </ul></dd></dl>
+     *
+     * <dl><dt><b>Postconditions:</b></dt><dd>
+     * <ul><li>getLineNr() => lineNr
+     * </ul></dd></dl><dl>
+     */
+    public XMLParseException(String name,
+                             int lineNr,
+                             String message) {
+        super("XML Parse Exception during parsing of "
+                + ((name == null) ? "the XML definition"
+                                : ("a " + name + " element"))
+                + " at line " + lineNr + ": " + message);
+        this.lineNr = lineNr;
+    }
+
+    /**
+     * Where the error occurred, or <code>NO_LINE</code> if the line number is
+     * unknown.
+     *
+     * @see net.sourceforge.nanoxml.XMLParseException#NO_LINE
+     */
+    public int getLineNr() {
+        return this.lineNr;
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/Makefile.kmk
===================================================================
--- /tags/icedtea-web/beta/plugin/Makefile.kmk	(revision 403)
+++ /tags/icedtea-web/beta/plugin/Makefile.kmk	(revision 403)
@@ -0,0 +1,12 @@
+## @file
+#
+
+SUB_DEPTH = ..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Include sub-makefiles.
+#
+include $(PATH_SUB_CURRENT)/icedteanp/Makefile.kmk
+
+include $(FILE_KBUILD_SUB_FOOTER)
Index: /tags/icedtea-web/beta/plugin/docs/npplugin_liveconnect_design.html
===================================================================
--- /tags/icedtea-web/beta/plugin/docs/npplugin_liveconnect_design.html	(revision 403)
+++ /tags/icedtea-web/beta/plugin/docs/npplugin_liveconnect_design.html	(revision 403)
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <head>
+        <title>IcedTeaNPPlugin LiveConnect Design</title>
+    </head>
+    <body>
+      <h1>IcedTeaNPPlugin LiveConnect Design</h1>
+      <h2>Plugin Architecture</h2>
+      <ul>
+	<li>Divided into C++ and Java components</li>
+	<li><ul>
+	  <li>C++ side talks to the browser</li>
+	  <li>Java side talks to the JVM</li>
+	  <li>Linked via a FIFO link</li>
+	  <li>Common string exchange format (UTF-8)</li>
+	</ul></li>
+	<li>Over 95% of changes in NPPlugin have been on the C++ side</li>
+	<li>Java side has been reused as much as possible to re-use the proven stable code</li>
+      </ul>
+      <h2>C++ Architecture</h2>
+      <ul>
+	<li>Encompassing classes from the LiveConnect engine (which previously resided in Mozilla
+	  and was exposed via OJI)</li>
+	<li>Each JavaScript var corresponding to a Java object has a corresponding
+	  <code>IcedTeaScriptableJavaObject</code></li>
+	<li>Engine controls the object life and services all requests (get field, set field,
+	  invoke method, etc.)</li>
+      </ul>
+      <h2>C++ Architecture (Browser Interface)</h2>
+      <ul>
+	<li>Browser interface consists primarily of <code>IcedTeaScriptableJavaPackageObject</code>,
+	  <code>IcedTeaScriptableJavaObject</code> and <code>IcedTeaPluginRequestProcessor</code>.</li>
+	<li>Above classes are unaware of Java interactions and delegate to the Java interfaces
+	  for Java interaction.</li>
+	<li>They process all requests coming from the browser and going to the browser (<code>getMember</code>,
+	  <code>call</code>, <code>eval</code>, etc.)</li>
+      </ul>
+      <h2>C++ Architecture (Java Interface)</h2>
+      <ul>
+	<li>Java interface consists primarily of <code>IcedTeaJavaRequestProcessor</code>.</li>
+	<li>This class has full knowledge of how the Java side works, and constructs appropriate
+	  requests to get all information from Java.</li>
+	<li>The class processes all requests to the JVM.</li>
+      </ul>
+      <h2>Java Architecture</h2>
+      <ul>
+	<li>Java side has two core classes aside from helpers: <code>PluginAppletViewer</code>
+	  and <code>PluginAppletSecurityContext</code>.</li>
+	<li><code>PluginAppletViewer</code> is an interface to NetX and processes JS-related
+	  requests to and from NetX (the applet).</li>
+	<li><code>PluginAppletSecurityContext</code> is a direct reflection-based interface
+	  to the VM.  It processes all LiveConnect requests to and from the JVM.</li>
+	<li>Request processing is asynchronous, with scalable generic request processing workers.</li>
+      </ul>
+      <h2>Java Architecture (<code>PluginAppletViewer</code>)</h2>
+      <ul>
+	<li>Control of applet (initialize, resize, destroy, etc.) from browser.</li>
+	<li>Access to JavaScript from the applet (<code>getMember</code>, <code>setMember</code>,
+	  <code>call</code>, <code>eval</code>, etc.)</li>
+      </ul>
+      <h2>Java Architecture (<code>PluginAppletSecurityContext</code>)</h2>
+      <ul>
+	<li>Direct access to the JVM from the browser (LiveConnect) via reflection.</li>
+	<li>All reflection is built-in, so C++ side never needs to be aware of the complexities,
+	  unlike how OJI was.</li>
+	<li>All VM calls are inside a sandbox, so JavaScript can not do things that the default
+	  sandboxed VM can't.</li>
+      </ul>
+      <h2>MessageBus Architecture (C++)</h2>
+      <ul>
+	<li>The link to Java is exposed to the rest of the code via a uniform "MessageBus" interface.</li>
+	<li>Since the code is unaware of the link specifics and has no synchronicity guarantee, the communication
+	  medium can be switched relatively easily.</li>
+	<li>Classes interested in the messages implement a <code>BusSubscriber</code> class and subscribe to
+	  the bus of interest.</li>
+	<li>When messages come in, the bus notifies all subscribers.</li>
+      </ul>
+      <h2>Example JS->Java Workflow</h2>
+      <ul>
+	<li>Example shows how <code>NPP_HasProperty()</code> works</li>
+	<li>Browser has a link to an <code>IcedTeaScriptableJavaObject</code> representing a Java
+	  object instance.</li>
+	<li>It call <code>IcedTeaScriptableJavaObject::HasProperty()</code></li>
+	<li><code>HasProperty()</code> creates an <code>IcedTeaJavaRequestProcessor</code>
+	  ("Java processor")</li>
+	<li>The Java processor exposes all necessary APIs to the VM, including <code>hasProperty</code>
+	  (called <code>hasField</code> for Java naming consistency).</li>
+	<li>Before making a <code>hasField</code> request, the processor subscribes itself
+	  to the "from Java" bus, so that it can read the response.</li>
+	<li>The <code>hasField</code> request is made by the processor and posted to the
+	  "to Java" bus.</li>
+	<li>The processor waits for either a response or a timeout.</li>
+	<li>Once a response is received, the processor unsubscribes itself from the
+	  "from Java" bus, performs post-processing and returns.</li>
+	<li>The <code>IcedTeaScriptableJavaObject</code> object reads the response and
+	  sends it to the browser.</li>
+      </ul>
+      <h2>Example Java->JS Workflow</h2>
+      <ul>
+	<li>All access to JS is via <code>JSObject</code> instances as defined in the
+	  LiveConnect specification.</li>
+	<li>If an applet wants to access a member of <code>JSObject</code>, "window"
+	  for example, it will call <code>getMember</code> on the window's <code>JSObject</code>.</li>
+	<li><code>getMember</code> calls a similarly named function in
+	  <code>PluginAppletViewer</code>.</li>
+	<li><code>PluginAppletViewer</code> constructs a request for the C++ side and
+	  posts it on the FIFO link.</li>
+	<li>On the C++ side, <code>IcedTeaPluginRequestProcessor</code> (the plugin
+	  processor) is always subscribed to the "from Java" bus.</li>
+	<li>When the <code>getMember</code> request comes through, the plugin processor
+	  gets notified.</li>
+	<li>The embedded request</li>
+      </ul>
+    </body>
+</html>
+
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	(revision 403)
@@ -0,0 +1,1429 @@
+/* IcedTeaJavaRequestProcessor.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifdef __EMX__
+#include <unistd.h> // usleep
+#endif
+
+#include <typeinfo>
+
+#include "IcedTeaJavaRequestProcessor.h"
+#include "IcedTeaScriptablePluginObject.h"
+
+/*
+ * This class processes LiveConnect requests from JavaScript to Java.
+ *
+ * It sends the requests to Java, gets the return information, and sends it
+ * back to the browser/JavaScript
+ */
+
+/**
+ * Processes return information from JavaSide (return messages of requests)
+ *
+ * @param message The message request to process
+ * @return boolean indicating whether the message is serviceable by this object
+ */
+
+bool
+JavaRequestProcessor::newMessageOnBus(const char* message)
+{
+
+	// Anything we are waiting for _MUST_ have and instance id and reference #
+	std::vector<std::string*>* message_parts = IcedTeaPluginUtilities::strSplit(message, " ");
+
+	IcedTeaPluginUtilities::printStringPtrVector("JavaRequest::newMessageOnBus:", message_parts);
+
+	if (*(message_parts->at(0)) == "context" && *(message_parts->at(2)) == "reference")
+		if (atoi(message_parts->at(1)->c_str()) == this->instance && atoi(message_parts->at(3)->c_str()) == this->reference)
+		{
+			// Gather the results
+
+			// Let's get errors out of the way first
+			if (!message_parts->at(4)->find("Error"))
+			{
+				for (int i=5; i < message_parts->size(); i++)
+				{
+					result->error_msg->append(*(message_parts->at(i)));
+					result->error_msg->append(" ");
+				}
+
+				printf("Error on Java side: %s\n", result->error_msg->c_str());
+
+				result->error_occurred = true;
+				result_ready = true;
+			}
+			else if (!message_parts->at(4)->find("GetStringUTFChars") ||
+			         !message_parts->at(4)->find("GetToStringValue"))
+			{
+				// first item is length, and it is radix 10
+				int length = strtol(message_parts->at(5)->c_str(), NULL, 10);
+
+				IcedTeaPluginUtilities::getUTF8String(length, 6 /* start at */, message_parts, result->return_string);
+				result_ready = true;
+			}
+			else if (!message_parts->at(4)->find("GetStringChars")) // GetStringChars (UTF-16LE/UCS-2)
+			{
+				// first item is length, and it is radix 10
+				int length = strtol(message_parts->at(5)->c_str(), NULL, 10);
+
+				IcedTeaPluginUtilities::getUTF16LEString(length, 6 /* start at */, message_parts, result->return_wstring);
+				result_ready = true;
+			} else if (!message_parts->at(4)->find("FindClass") ||
+			           !message_parts->at(4)->find("GetClassName") ||
+			           !message_parts->at(4)->find("GetClassID") ||
+			           !message_parts->at(4)->find("GetMethodID") ||
+			           !message_parts->at(4)->find("GetStaticMethodID") ||
+			           !message_parts->at(4)->find("GetObjectClass") ||
+			           !message_parts->at(4)->find("NewObject") ||
+			           !message_parts->at(4)->find("NewStringUTF") ||
+			           !message_parts->at(4)->find("HasPackage") ||
+			           !message_parts->at(4)->find("HasMethod") ||
+			           !message_parts->at(4)->find("HasField") ||
+			           !message_parts->at(4)->find("GetStaticFieldID") ||
+			           !message_parts->at(4)->find("GetFieldID") ||
+			           !message_parts->at(4)->find("GetJavaObject") ||
+			           !message_parts->at(4)->find("IsInstanceOf") ||
+			           !message_parts->at(4)->find("NewArray"))
+			{
+				result->return_identifier = atoi(message_parts->at(5)->c_str());
+				result->return_string->append(*(message_parts->at(5))); // store it as a string as well, for easy access
+				result_ready = true;
+			}  else if (!message_parts->at(4)->find("DeleteLocalRef") ||
+			            !message_parts->at(4)->find("NewGlobalRef"))
+			{
+			    result_ready = true; // nothing else to do
+			} else if (!message_parts->at(4)->find("CallMethod") ||
+			           !message_parts->at(4)->find("CallStaticMethod") ||
+			           !message_parts->at(4)->find("GetField") ||
+			           !message_parts->at(4)->find("GetStaticField") ||
+			           !message_parts->at(4)->find("GetValue") ||
+			           !message_parts->at(4)->find("GetObjectArrayElement"))
+			{
+
+			    if (!message_parts->at(5)->find("literalreturn"))
+                {
+			        // literal returns don't have a corresponding jni id
+			        result->return_identifier = 0;
+			        result->return_string->append(*(message_parts->at(5)));
+			        result->return_string->append(" ");
+			        result->return_string->append(*(message_parts->at(6)));
+
+                } else
+			    {
+                    // Else it is a complex object
+
+			        result->return_identifier = atoi(message_parts->at(5)->c_str());
+			        result->return_string->append(*(message_parts->at(5))); // store it as a string as well, for easy access
+			    }
+
+				result_ready = true;
+			} else if (!message_parts->at(4)->find("GetArrayLength"))
+            {
+			    result->return_identifier = 0; // length is not an "identifier"
+			    result->return_string->append(*(message_parts->at(5)));
+			    result_ready = true;
+            } else if (!message_parts->at(4)->find("SetField") ||
+                       !message_parts->at(4)->find("SetObjectArrayElement"))
+            {
+
+                // nothing to do
+
+                result->return_identifier = 0;
+                result_ready = true;
+            }
+
+            IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
+			return true;
+		}
+
+    IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
+	return false;
+}
+
+/**
+ * Constructor.
+ *
+ * Initializes the result data structure (heap)
+ */
+
+JavaRequestProcessor::JavaRequestProcessor()
+{
+    PLUGIN_DEBUG("JavaRequestProcessor constructor\n");
+
+	// caller frees this
+	result = new JavaResultData();
+	result->error_msg = new std::string();
+	result->return_identifier = 0;
+	result->return_string = new std::string();
+	result->return_wstring = new std::wstring();
+	result->error_occurred = false;
+
+	result_ready = false;
+}
+
+/**
+ * Destructor
+ *
+ * Frees memory used by the result struct
+ */
+
+JavaRequestProcessor::~JavaRequestProcessor()
+{
+    PLUGIN_DEBUG("JavaRequestProcessor::~JavaRequestProcessor\n");
+
+	if (result)
+	{
+		if (result->error_msg)
+			delete result->error_msg;
+
+		if (result->return_string)
+			delete result->return_string;
+
+		if (result->return_wstring)
+			delete result->return_wstring;
+
+		delete result;
+	}
+}
+
+/**
+ * Resets the results
+ */
+void
+JavaRequestProcessor::resetResult()
+{
+	// caller frees this
+	result->error_msg->clear();
+	result->return_identifier = 0;
+	result->return_string->clear();
+	result->return_wstring->clear();
+	result->error_occurred = false;
+
+	result_ready = false;
+}
+
+void
+JavaRequestProcessor::postAndWaitForResponse(std::string message)
+{
+    struct timespec t;
+#ifdef __OS2__
+    t.tv_sec = time(NULL);
+    t.tv_nsec = 0;
+#else
+    clock_gettime(CLOCK_REALTIME, &t);
+#endif
+    t.tv_sec += REQUESTTIMEOUT; // 1 minute timeout
+
+    // Clear the result
+    resetResult();
+
+    java_to_plugin_bus->subscribe(this);
+    plugin_to_java_bus->post(message.c_str());
+
+    // Wait for result to be filled in.
+    struct timespec curr_t;
+#ifdef __OS2__
+    curr_t.tv_sec = curr_t.tv_nsec = 0;
+#endif
+
+    bool isPluginThread = false;
+
+    if (pthread_self() == itnp_plugin_thread_id)
+    {
+        isPluginThread = true;
+        PLUGIN_DEBUG("JRP is in plug-in thread...\n");
+    }
+
+    do
+    {
+#ifdef __OS2__
+        curr_t.tv_sec = time(NULL);
+#else
+        clock_gettime(CLOCK_REALTIME, &curr_t);
+#endif
+
+        if (!result_ready && (curr_t.tv_sec < t.tv_sec))
+        {
+            if (isPluginThread)
+            {
+                processAsyncCallQueue(NULL);
+
+                // Let the browser run its pending events too
+                if (g_main_context_pending(NULL))
+                {
+                    g_main_context_iteration(NULL, false);
+                } else
+                {
+                    usleep(1000); // 1ms
+                }
+            } else
+            {
+                usleep(1000); // 1ms
+            }
+        }
+        else
+        {
+            break;
+        }
+    } while (1);
+
+    if (curr_t.tv_sec >= t.tv_sec)
+    {
+    	result->error_occurred = true;
+    	result->error_msg->append("Error: Timed out when waiting for response");
+
+    	// Report error
+    	PLUGIN_DEBUG("Error: Timed out when waiting for response to %s\n", message.c_str());
+    }
+
+    java_to_plugin_bus->unSubscribe(this);
+}
+
+/**
+ * Given an object id, fetches the toString() value from Java
+ *
+ * @param object_id The ID of the object
+ * @return A JavaResultData struct containing the result of the request
+ */
+
+JavaResultData*
+JavaRequestProcessor::getToStringValue(std::string object_id)
+{
+	std::string message = std::string();
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetToStringValue "); // get it in UTF8
+    message.append(object_id);
+
+    postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	return result;
+}
+
+/**
+ * Given an object id, fetches the value of that ID from Java
+ *
+ * @param object_id The ID of the object
+ * @return A JavaResultData struct containing the result of the request
+ */
+
+JavaResultData*
+JavaRequestProcessor::getValue(std::string object_id)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetValue "); // get it in UTF8
+    message.append(object_id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+/**
+ * Given a string id, fetches the actual string from Java side
+ *
+ * @param string_id The ID of the string
+ * @return A JavaResultData struct containing the result of the request
+ */
+
+JavaResultData*
+JavaRequestProcessor::getString(std::string string_id)
+{
+    std::string message = std::string();
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetStringUTFChars "); // get it in UTF8
+    message.append(string_id);
+
+    postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	return result;
+}
+
+/**
+ * Decrements reference count by 1
+ *
+ * @param object_id The ID of the object
+ */
+
+void
+JavaRequestProcessor::deleteReference(std::string object_id)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" DeleteLocalRef ");
+    message.append(object_id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+}
+
+/**
+ * Increments reference count by 1
+ *
+ * @param object_id The ID of the object
+ */
+
+void
+JavaRequestProcessor::addReference(std::string object_id)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" NewGlobalRef ");
+    message.append(object_id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+}
+
+JavaResultData*
+JavaRequestProcessor::findClass(int plugin_instance_id,
+                                std::string name)
+{
+    std::string message = std::string();
+    std::string plugin_instance_id_str = std::string();
+
+    IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" FindClass ");
+    message.append(plugin_instance_id_str);
+    message.append(" ");
+    message.append(name);
+
+    postAndWaitForResponse(message);
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getClassName(std::string objectID)
+{
+    std::string message = std::string();
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetClassName ");
+    message.append(objectID);
+
+    postAndWaitForResponse(message);
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getClassID(std::string objectID)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetClassID ");
+    message.append(objectID);
+
+    postAndWaitForResponse(message);
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getArrayLength(std::string objectID)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetArrayLength ");
+    message.append(objectID);
+
+    postAndWaitForResponse(message);
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getSlot(std::string objectID, std::string index)
+{
+    std::string message = std::string();
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetObjectArrayElement ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(index);
+
+    postAndWaitForResponse(message);
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::setSlot(std::string objectID,
+                              std::string index,
+                              std::string value_id)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" SetObjectArrayElement ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(index);
+    message.append(" ");
+    message.append(value_id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::newArray(std::string array_class,
+                               std::string length)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" NewArray ");
+    message.append(array_class);
+    message.append(" ");
+    message.append(length);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getFieldID(std::string classID, std::string fieldName)
+{
+	JavaResultData* java_result;
+	JavaRequestProcessor* java_request = new JavaRequestProcessor();
+	std::string message = std::string();
+
+	java_result = java_request->newString(fieldName);
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" GetFieldID ");
+	message.append(classID);
+	message.append(" ");
+	message.append(java_result->return_string->c_str());
+
+	postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	delete java_request;
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getStaticFieldID(std::string classID, std::string fieldName)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request->newString(fieldName);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" GetStaticFieldID ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    delete java_request;
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getField(std::string source,
+                               std::string classID,
+                               std::string objectID,
+                               std::string fieldName)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request->getFieldID(classID, fieldName);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+    message.append(" GetField ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    delete java_request;
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getStaticField(std::string source, std::string classID,
+                                     std::string fieldName)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request->getStaticFieldID(classID, fieldName);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+    message.append(" GetStaticField ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    delete java_request;
+
+    return result;
+}
+
+
+JavaResultData*
+JavaRequestProcessor::set(std::string source,
+                          bool isStatic,
+                          std::string classID,
+                          std::string objectID,
+                          std::string fieldName,
+                          std::string value_id)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request.getFieldID(classID, fieldName);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+
+    if (isStatic)
+    {
+        message.append(" SetStaticField ");
+        message.append(classID);
+    } else
+    {
+        message.append(" SetField ");
+        message.append(objectID);
+    }
+
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+    message.append(" ");
+    message.append(value_id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::setStaticField(std::string source,
+                                     std::string classID,
+                                     std::string fieldName,
+                                     std::string value_id)
+{
+    return set(source, true, classID, "", fieldName, value_id);
+}
+
+JavaResultData*
+JavaRequestProcessor::setField(std::string source,
+                               std::string classID,
+                               std::string objectID,
+                               std::string fieldName,
+                               std::string value_id)
+{
+    return set(source, false, classID, objectID, fieldName, value_id);
+}
+
+JavaResultData*
+JavaRequestProcessor::getMethodID(std::string classID, NPIdentifier methodName,
+                                  std::vector<std::string> args)
+{
+	JavaRequestProcessor* java_request;
+	std::string message = std::string();
+    std::string* signature;
+
+    signature = new std::string();
+    *signature += "(";
+
+    // FIXME: Need to determine how to extract array types and complex java objects
+    for (int i=0; i < args.size(); i++)
+    {
+    	*signature += args[i];
+    }
+
+    *signature += ")";
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message += " GetMethodID ";
+	message += classID;
+	message += " ";
+	message += browser_functions.utf8fromidentifier(methodName);
+	message += " ";
+	message += *signature;
+
+	postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+	delete signature;
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getStaticMethodID(std::string classID, NPIdentifier methodName,
+                                  std::vector<std::string> args)
+{
+    JavaRequestProcessor* java_request;
+    std::string message = std::string();
+    std::string* signature;
+
+    signature = new std::string();
+    *signature += "(";
+
+    // FIXME: Need to determine how to extract array types and complex java objects
+    for (int i=0; i < args.size(); i++)
+    {
+        *signature += args[i];
+    }
+
+    *signature += ")";
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message += " GetStaticMethodID ";
+    message += classID;
+    message += " ";
+    message += browser_functions.utf8fromidentifier(methodName);
+    message += " ";
+    message += *signature;
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+    delete signature;
+
+    return result;
+}
+
+void
+getArrayTypeForJava(NPP instance, NPVariant element, std::string* type)
+{
+
+    if (NPVARIANT_IS_BOOLEAN(element)) {
+        type->append("string");
+    } else if (NPVARIANT_IS_INT32(element)) {
+        type->append("string");
+    } else if (NPVARIANT_IS_DOUBLE(element)) {
+        type->append("string");
+    } else if (NPVARIANT_IS_STRING(element)) {
+        type->append("string");
+    } else if (NPVARIANT_IS_OBJECT(element)) {
+
+        NPObject* first_element_obj = NPVARIANT_TO_OBJECT(element);
+        if (IcedTeaScriptableJavaPackageObject::is_valid_java_object(first_element_obj))
+        {
+            std::string class_id = std::string(((IcedTeaScriptableJavaObject*) first_element_obj)->getClassID());
+            type->append(class_id);
+        } else
+        {
+            type->append("jsobject");
+        }
+    } else {
+        type->append("jsobject"); // Else it is a string
+    }
+}
+
+void
+createJavaObjectFromVariant(NPP instance, NPVariant variant, std::string* id)
+{
+	JavaResultData* java_result;
+
+	std::string className;
+	std::string jsObjectClassID = std::string();
+	std::string jsObjectConstructorID = std::string();
+
+	std::string stringArg = std::string();
+	std::vector<std::string> args = std::vector<std::string>();
+
+	JavaRequestProcessor java_request = JavaRequestProcessor();
+	bool alreadyCreated = false;
+
+    if (NPVARIANT_IS_VOID(variant))
+    {
+    	PLUGIN_DEBUG("VOID %d\n", variant);
+    	id->append("0");
+    	return; // no need to go further
+    } else if (NPVARIANT_IS_NULL(variant))
+    {
+    	PLUGIN_DEBUG("NULL\n", variant);
+    	id->append("0");
+    	return; // no need to go further
+    } else if (NPVARIANT_IS_BOOLEAN(variant))
+    {
+    	className = "java.lang.Boolean";
+
+    	if (NPVARIANT_TO_BOOLEAN(variant))
+    		stringArg = "true";
+    	else
+    		stringArg = "false";
+
+    } else if (NPVARIANT_IS_INT32(variant))
+    {
+    	className = "java.lang.Integer";
+
+    	char* valueStr = (char*) malloc(sizeof(char)*32);
+    	sprintf(valueStr, "%d", NPVARIANT_TO_INT32(variant));
+    	stringArg += valueStr;
+    	free(valueStr);
+    } else if (NPVARIANT_IS_DOUBLE(variant))
+    {
+    	className = "java.lang.Double";
+
+    	char* valueStr = (char*) malloc(sizeof(char)*1024);
+    	sprintf(valueStr, "%f", NPVARIANT_TO_DOUBLE(variant));
+    	stringArg += valueStr;
+    	free(valueStr);
+    } else if (NPVARIANT_IS_STRING(variant))
+    {
+    	className = "java.lang.String";
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+    	stringArg += NPVARIANT_TO_STRING(variant).utf8characters;
+#else
+    	stringArg += NPVARIANT_TO_STRING(variant).UTF8Characters;
+#endif
+    } else if (NPVARIANT_IS_OBJECT(variant))
+    {
+
+        NPObject* obj = NPVARIANT_TO_OBJECT(variant);
+        if (IcedTeaScriptableJavaPackageObject::is_valid_java_object(obj))
+        {
+            PLUGIN_DEBUG("NPObject is a Java object\n");
+            alreadyCreated = true;
+        } else
+        {
+            PLUGIN_DEBUG("NPObject is not a Java object\n");
+            NPIdentifier length_id = browser_functions.getstringidentifier("length");
+
+            // FIXME: We currently only handle <= 2 dim arrays. Do we really need more though?
+
+            // Is it an array?
+            if (IcedTeaPluginUtilities::isObjectJSArray(instance, obj)) {
+                PLUGIN_DEBUG("NPObject is an array\n");
+
+                std::string array_id = std::string();
+                std::string java_array_type = std::string();
+                NPVariant length = NPVariant();
+                browser_functions.getproperty(instance, obj, length_id, &length);
+
+                std::string length_str = std::string();
+                IcedTeaPluginUtilities::itoa(NPVARIANT_TO_INT32(length), &length_str);
+
+                if (NPVARIANT_TO_INT32(length) > 0)
+                {
+                    NPIdentifier id_0 = browser_functions.getintidentifier(0);
+                    NPVariant first_element = NPVariant();
+                    browser_functions.getproperty(instance, obj, id_0, &first_element);
+
+                    // Check for multi-dim array
+                    if (NPVARIANT_IS_OBJECT(first_element) &&
+                        IcedTeaPluginUtilities::isObjectJSArray(instance, NPVARIANT_TO_OBJECT(first_element))) {
+
+                        NPVariant first_nested_element = NPVariant();
+                        browser_functions.getproperty(instance, NPVARIANT_TO_OBJECT(first_element), id_0, &first_nested_element);
+
+                        getArrayTypeForJava(instance, first_nested_element, &java_array_type);
+
+                        length_str.append(" 0"); // secondary array is created on the fly
+                    } else
+                    {
+                        getArrayTypeForJava(instance, first_element, &java_array_type);
+                    }
+                } else
+                    java_array_type.append("jsobject");
+
+                java_result = java_request.newArray(java_array_type, length_str);
+
+                if (java_result->error_occurred) {
+                    printf("Unable to create array\n");
+                    id->append("-1");
+                    return;
+                }
+
+                id->append(*(java_result->return_string));
+
+                NPIdentifier index_id = NPIdentifier();
+                for (int i=0; i < NPVARIANT_TO_INT32(length); i++)
+                {
+                    NPVariant value = NPVariant();
+
+                    index_id = browser_functions.getintidentifier(i);
+                    browser_functions.getproperty(instance, obj, index_id, &value);
+
+                    std::string value_id = std::string();
+                    createJavaObjectFromVariant(instance, value, &value_id);
+
+                    if (value_id == "-1") {
+                        printf("Unable to populate array\n");
+                        id->clear();
+                        id->append("-1");
+                        return;
+                    }
+
+                    std::string value_str = std::string();
+                    IcedTeaPluginUtilities::itoa(i, &value_str);
+                    java_result = java_request.setSlot(*id, value_str, value_id);
+
+                }
+
+                // Got here => no errors above. We're good to return!
+                return;
+            } else // Else it is not an array
+            {
+
+                NPVariant* variant_copy = new NPVariant();
+                OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(variant), *variant_copy);
+
+                className = "netscape.javascript.JSObject";
+                IcedTeaPluginUtilities::JSIDToString(variant_copy, &stringArg);
+                browser_functions.retainobject(NPVARIANT_TO_OBJECT(variant));
+
+                std::string jsObjectClassID = std::string();
+                std::string jsObjectConstructorID = std::string();
+                std::vector<std::string> args = std::vector<std::string>();
+
+                java_result = java_request.findClass(0, "netscape.javascript.JSObject");
+
+                // the result we want is in result_string (assuming there was no error)
+                if (java_result->error_occurred)
+                {
+                    printf("Unable to get JSObject class id\n");
+                    id->clear();
+                    id->append("-1");
+                    return;
+                }
+
+                jsObjectClassID.append(*(java_result->return_string));
+                args.push_back("J");
+
+                java_result = java_request.getMethodID(jsObjectClassID,
+                                                       browser_functions.getstringidentifier("<init>"),
+                                                       args);
+
+                // the result we want is in result_string (assuming there was no error)
+                if (java_result->error_occurred)
+                {
+                    printf("Unable to get JSObject constructor id\n");
+                    id->clear();
+                    id->append("-1");
+                    return;
+                }
+
+                jsObjectConstructorID.append(*(java_result->return_string));
+
+                // We have the method id. Now create a new object.
+
+                args.clear();
+                args.push_back(stringArg);
+                java_result = java_request.newObjectWithConstructor("",
+                                                     jsObjectClassID,
+                                                     jsObjectConstructorID,
+                                                     args);
+
+                // Store the instance ID for future reference
+                IcedTeaPluginUtilities::storeInstanceID(variant_copy, instance);
+
+                // the result we want is in result_string (assuming there was no error)
+                // the result we want is in result_string (assuming there was no error)
+                if (java_result->error_occurred)
+                {
+                    printf("Unable to create JSObject\n");
+                    id->clear();
+                    id->append("-1");
+                    return;
+                }
+
+                id->append(*(java_result->return_string));
+                return;
+            }
+        }
+    }
+
+    if (!alreadyCreated) {
+		java_result = java_request.findClass(0, className);
+
+		// the result we want is in result_string (assuming there was no error)
+		if (java_result->error_occurred) {
+			printf("Unable to find classid for %s\n", className.c_str());
+			id->append("-1");
+			return;
+		}
+
+		jsObjectClassID.append(*(java_result->return_string));
+
+		std::string stringClassName = "Ljava/lang/String;";
+		args.push_back(stringClassName);
+
+		java_result = java_request.getMethodID(jsObjectClassID,
+				      browser_functions.getstringidentifier("<init>"), args);
+
+		// the result we want is in result_string (assuming there was no error)
+		if (java_result->error_occurred) {
+			printf("Unable to find string constructor for %s\n", className.c_str());
+			id->append("-1");
+            return;
+		}
+
+		jsObjectConstructorID.append(*(java_result->return_string));
+
+		// We have class id and constructor ID. So we know we can create the
+		// object.. now create the string that will be provided as the arg
+		java_result = java_request.newString(stringArg);
+
+		if (java_result->error_occurred) {
+			printf("Unable to create requested object\n");
+			id->append("-1");
+            return;
+		}
+
+		// Create the object
+		args.clear();
+		std::string arg = std::string();
+		arg.append(*(java_result->return_string));
+		args.push_back(arg);
+		java_result = java_request.newObjectWithConstructor("[System]", jsObjectClassID, jsObjectConstructorID, args);
+
+        if (java_result->error_occurred) {
+            printf("Unable to create requested object\n");
+            id->append("-1");
+            return;
+        }
+
+
+		id->append(*(java_result->return_string));
+
+	} else {
+	    // Else already created
+
+	    std::string classId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getClassID());
+	    std::string instanceId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getInstanceID());
+
+	    if (instanceId.length() == 0)
+	        id->append(classId.c_str());
+	    else
+	        id->append(instanceId.c_str());
+	}
+
+}
+
+JavaResultData*
+JavaRequestProcessor::callStaticMethod(std::string source, std::string classID,
+                                       std::string methodName,
+                                       std::vector<std::string> args)
+{
+    return call(source, true, classID, methodName, args);
+}
+
+JavaResultData*
+JavaRequestProcessor::callMethod(std::string source,
+                                 std::string objectID, std::string methodName,
+                                 std::vector<std::string> args)
+{
+    return call(source, false, objectID, methodName, args);
+}
+
+JavaResultData*
+JavaRequestProcessor::call(std::string source,
+                           bool isStatic, std::string objectID,
+                           std::string methodName,
+                           std::vector<std::string> args)
+{
+    std::string message = std::string();
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+
+    if (isStatic)
+        message += " CallStaticMethod ";
+    else
+        message += " CallMethod ";
+
+    message += objectID;
+    message += " ";
+    message += methodName;
+    message += " ";
+
+    for (int i=0; i < args.size(); i++)
+    {
+        message += args[i];
+        message += " ";
+    }
+
+	postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getObjectClass(std::string objectID)
+{
+    JavaRequestProcessor* java_request;
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message += " GetObjectClass ";
+    message += objectID;
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::newObject(std::string source, std::string classID,
+                                std::vector<std::string> args)
+{
+    JavaRequestProcessor* java_request;
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+    message += " NewObject ";
+    message += classID;
+    message += " ";
+
+    for (int i=0; i < args.size(); i++)
+    {
+        message += args[i];
+        message += " ";
+    }
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::newObjectWithConstructor(std::string source, std::string classID,
+                                std::string methodID,
+                                std::vector<std::string> args)
+{
+	JavaRequestProcessor* java_request;
+	std::string message = std::string();
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+	message += " NewObjectWithConstructor ";
+	message += classID;
+	message += " ";
+	message += methodID;
+	message += " ";
+
+	for (int i=0; i < args.size(); i++)
+	{
+		message += args[i];
+		message += " ";
+	}
+
+	postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::newString(std::string str)
+{
+	std::string utf_string = std::string();
+	std::string message = std::string();
+
+	IcedTeaPluginUtilities::convertStringToUTF8(&str, &utf_string);
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" NewStringUTF ");
+	message.append(utf_string);
+
+	postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::hasPackage(int plugin_instance_id,
+                                 std::string package_name)
+{
+	JavaResultData* java_result;
+	JavaRequestProcessor* java_request = new JavaRequestProcessor();
+	std::string message = std::string();
+	std::string plugin_instance_id_str = std::string();
+	IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
+
+	java_result = java_request->newString(package_name);
+
+	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+	this->reference = IcedTeaPluginUtilities::getReference();
+
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" HasPackage ");
+    message.append(plugin_instance_id_str);
+    message.append(" ");
+	message.append(java_result->return_string->c_str());
+
+	postAndWaitForResponse(message);
+
+	IcedTeaPluginUtilities::releaseReference();
+
+	delete java_request;
+
+	return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::hasMethod(std::string classID, std::string method_name)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request->newString(method_name);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" HasMethod ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    delete java_request;
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::hasField(std::string classID, std::string method_name)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    std::string message = std::string();
+
+    java_result = java_request.newString(method_name);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" HasField ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::isInstanceOf(std::string objectID, std::string classID)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" IsInstanceOf ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(classID);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getAppletObjectInstance(std::string instanceID)
+{
+    std::string message = std::string();
+    std::string ref_str = std::string();
+
+    this->instance = 0;
+    this->reference = IcedTeaPluginUtilities::getReference();
+    IcedTeaPluginUtilities::itoa(reference, &ref_str);
+
+    message = "instance ";
+    message += instanceID;
+    message += " reference ";
+    message += ref_str;
+    message += " GetJavaObject";
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	(revision 403)
@@ -0,0 +1,233 @@
+/* IcedTeaJavaRequestProcessor.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef ICEDTEAJAVAREQUEST_H_
+#define ICEDTEAJAVAREQUEST_H_
+
+#include <errno.h>
+#include <stdlib.h>
+#include <vector>
+
+#include "IcedTeaNPPlugin.h"
+#include "IcedTeaPluginUtils.h"
+
+#define REQUESTTIMEOUT 180
+
+/*
+ * This struct holds data specific to a Java operation requested by the plugin
+ */
+typedef struct java_request
+{
+    // Instance id  (if applicable)
+    int instance;
+
+    // Context id (if applicable)
+    int context;
+
+    // request specific data
+    std::vector<std::string>* data;
+
+    // source of the request
+    std::string* source;
+
+} JavaRequest;
+
+/* Creates a argument on java-side with appropriate type */
+void createJavaObjectFromVariant(NPP instance, NPVariant variant, std::string* id);
+
+/* Returns the type of array based on the given element */
+void getArrayTypeForJava(NPP instance, NPVariant element, std::string* type);
+
+class JavaRequestProcessor : BusSubscriber
+{
+    private:
+    	// instance and references are constant throughout this objects
+    	// lifecycle
+    	int instance;
+    	int reference;
+    	bool result_ready;
+    	JavaResultData* result;
+
+    	/* Post message on bus and wait */
+    	void postAndWaitForResponse(std::string message);
+
+    	// Call a method, static or otherwise, depending on supplied arg
+        JavaResultData* call(std::string source, bool isStatic,
+                             std::string objectID, std::string methodName,
+                             std::vector<std::string> args);
+
+        // Set a static/non-static field to given value
+        JavaResultData* set(std::string source,
+                            bool isStatic,
+                            std::string classID,
+                            std::string objectID,
+                            std::string fieldName,
+                            std::string value_id);
+
+        /* Resets the results */
+        void resetResult();
+
+    public:
+    	JavaRequestProcessor();
+    	~JavaRequestProcessor();
+    	virtual bool newMessageOnBus(const char* message);
+
+    	/* Increments reference count by 1 */
+    	void addReference(std::string object_id);
+
+    	/* Decrements reference count by 1 */
+    	void deleteReference(std::string object_id);
+
+    	/* Returns the toString() value, given an object identifier */
+    	JavaResultData* getToStringValue(std::string object_id);
+
+        /* Returns the value, given an object identifier */
+        JavaResultData* getValue(std::string object_id);
+
+    	/* Returns the string, given the identifier */
+    	JavaResultData* getString(std::string string_id);
+
+    	/* Returns the field object */
+        JavaResultData* getField(std::string source,
+                                 std::string classID,
+                                 std::string objectID,
+                                 std::string fieldName);
+
+        /* Returns the static field object */
+        JavaResultData* getStaticField(std::string source,
+                                       std::string classID,
+                                       std::string fieldName);
+
+        /* Sets the field object */
+        JavaResultData* setField(std::string source,
+                                 std::string classID,
+                                 std::string objectID,
+                                 std::string fieldName,
+                                 std::string value_id);
+
+        /* Sets the static field object */
+        JavaResultData* setStaticField(std::string source,
+                                       std::string classID,
+                                       std::string fieldName,
+                                       std::string value_id);
+
+        /* Returns the field id */
+        JavaResultData* getFieldID(std::string classID, std::string fieldName);
+
+        /* Returns the static field id */
+    	JavaResultData* getStaticFieldID(std::string classID, std::string fieldName);
+
+    	/* Returns the method id */
+    	JavaResultData* getMethodID(std::string classID, NPIdentifier methodName,
+                                    std::vector<std::string> args);
+
+        /* Returns the static method id */
+        JavaResultData* getStaticMethodID(std::string classID, NPIdentifier methodName,
+                                     std::vector<std::string> args);
+
+        /* Calls a static method */
+        JavaResultData* callStaticMethod(std::string source,
+                                         std::string classID,
+                                         std::string methodName,
+                                         std::vector<std::string> args);
+
+        /* Calls a method on an instance */
+        JavaResultData* callMethod(std::string source,
+                                   std::string objectID,
+                                   std::string methodName,
+                                   std::vector<std::string> args);
+
+        /* Returns the class of the given object */
+        JavaResultData* getObjectClass(std::string objectID);
+
+    	/* Creates a new object with choosable constructor */
+    	JavaResultData* newObject(std::string source,
+                                  std::string classID,
+                                  std::vector<std::string> args);
+
+    	/* Creates a new object when constructor is undetermined */
+    	JavaResultData* newObjectWithConstructor(std::string source, std::string classID,
+                                  std::string methodID,
+                                  std::vector<std::string> args);
+
+    	/* Returns the class ID */
+    	JavaResultData* findClass(int plugin_instance_id,
+                                  std::string name);
+
+    	/* Returns the type class name */
+    	JavaResultData* getClassName(std::string objectID);
+
+    	/* Returns the type class id */
+    	JavaResultData* getClassID(std::string objectID);
+
+    	/* Returns the length of the array object. -1 if not found */
+    	JavaResultData* getArrayLength(std::string objectID);
+
+    	/* Returns the item at the given index for the array */
+    	JavaResultData* getSlot(std::string objectID, std::string index);
+
+        /* Sets the item at the given index to the given value */
+        JavaResultData* setSlot(std::string objectID,
+                                std::string index,
+                                std::string value_id);
+
+        /* Creates a new array of given length */
+        JavaResultData* newArray(std::string component_class,
+                                 std::string length);
+
+    	/* Creates a new string in the Java store */
+    	JavaResultData* newString(std::string str);
+
+    	/* Check if package exists */
+    	JavaResultData* hasPackage(int plugin_instance_id,
+                                   std::string package_name);
+
+        /* Check if method exists */
+        JavaResultData* hasMethod(std::string classID, std::string method_name);
+
+        /* Check if field exists */
+        JavaResultData* hasField(std::string classID, std::string method_name);
+
+        /* Check if given object is instance of given class */
+        JavaResultData* isInstanceOf(std::string objectID, std::string classID);
+
+        /* Returns the instance ID of the java applet */
+        JavaResultData* getAppletObjectInstance(std::string instanceID);
+};
+
+#endif /* ICEDTEAJAVAREQUESTPROCESSOR_H_ */
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.cc	(revision 403)
@@ -0,0 +1,2725 @@
+/* IcedTeaNPPlugin.cc -- web browser plugin to execute Java applets
+   Copyright (C) 2003, 2004, 2006, 2007  Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 Red Hat
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifdef __OS2__
+// OS/2 includes.
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#define INCL_WINDIALOG
+#include <os2.h>
+#include <emx/startup.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include "OS_OS2.h"
+#endif
+
+// System includes.
+#include <dlfcn.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// Liveconnect extension
+#include "IcedTeaScriptablePluginObject.h"
+#include "IcedTeaNPPlugin.h"
+
+#ifdef __OS2__
+#define DT_SOCKET_DLL "jdtsock"
+#else
+#define DT_SOCKET_DLL "dt_socket"
+#endif
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+// Documentbase retrieval includes.
+#include <nsIPluginInstance.h>
+#include <nsIPluginInstancePeer.h>
+#include <nsIPluginTagInfo2.h>
+
+// API's into Mozilla
+#include <nsCOMPtr.h>
+#include <nsICookieService.h>
+#include <nsIDNSRecord.h>
+#include <nsIDNSService.h>
+#include <nsINetUtil.h>
+#include <nsIProxyInfo.h>
+#include <nsIProtocolProxyService.h>
+#include <nsIScriptSecurityManager.h>
+#include <nsIIOService.h>
+#include <nsIURI.h>
+#include <nsNetCID.h>
+#include <nsStringAPI.h>
+#include <nsServiceManagerUtils.h>
+#endif
+
+// Error reporting macros.
+#define PLUGIN_ERROR(message)                                       \
+  g_printerr ("%s:%d: thread %p: Error: %s\n", __FILE__, __LINE__,  \
+              g_thread_self (), message)
+
+#define PLUGIN_ERROR_TWO(first, second)                                 \
+  g_printerr ("%s:%d: thread %p: Error: %s: %s\n", __FILE__, __LINE__,  \
+              g_thread_self (), first, second)
+
+#define PLUGIN_ERROR_THREE(first, second, third)                        \
+  g_printerr ("%s:%d: thread %p: Error: %s: %s: %s\n", __FILE__,        \
+              __LINE__, g_thread_self (), first, second, third)
+
+// Plugin information passed to about:plugins.
+#define PLUGIN_FULL_NAME PLUGIN_NAME " (using " PLUGIN_VERSION ")"
+#define PLUGIN_DESC "The <a href=\"" PACKAGE_URL "\">" PLUGIN_NAME "</a> executes Java applets."
+
+#define PLUGIN_MIME_DESC                                               \
+  "application/x-java-vm:class,jar:IcedTea;"                           \
+  "application/x-java-applet:class,jar:IcedTea;"                       \
+  "application/x-java-applet;version=1.1:class,jar:IcedTea;"           \
+  "application/x-java-applet;version=1.1.1:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.1.2:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.1.3:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.2:class,jar:IcedTea;"           \
+  "application/x-java-applet;version=1.2.1:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.2.2:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.3:class,jar:IcedTea;"           \
+  "application/x-java-applet;version=1.3.1:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.4:class,jar:IcedTea;"           \
+  "application/x-java-applet;version=1.4.1:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.4.2:class,jar:IcedTea;"         \
+  "application/x-java-applet;version=1.5:class,jar:IcedTea;"           \
+  "application/x-java-applet;version=1.6:class,jar:IcedTea;"           \
+  "application/x-java-applet;jpi-version=1.6.0_" JDK_UPDATE_VERSION ":class,jar:IcedTea;"  \
+  "application/x-java-bean:class,jar:IcedTea;"                         \
+  "application/x-java-bean;version=1.1:class,jar:IcedTea;"             \
+  "application/x-java-bean;version=1.1.1:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.1.2:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.1.3:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.2:class,jar:IcedTea;"             \
+  "application/x-java-bean;version=1.2.1:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.2.2:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.3:class,jar:IcedTea;"             \
+  "application/x-java-bean;version=1.3.1:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.4:class,jar:IcedTea;"             \
+  "application/x-java-bean;version=1.4.1:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.4.2:class,jar:IcedTea;"           \
+  "application/x-java-bean;version=1.5:class,jar:IcedTea;"             \
+  "application/x-java-bean;version=1.6:class,jar:IcedTea;"             \
+  "application/x-java-bean;jpi-version=1.6.0_" JDK_UPDATE_VERSION ":class,jar:IcedTea;"    \
+  "application/x-java-vm-npruntime::IcedTea;"
+
+#define PLUGIN_URL NS_INLINE_PLUGIN_CONTRACTID_PREFIX NS_JVM_MIME_TYPE
+#define PLUGIN_MIME_TYPE "application/x-java-vm"
+#define PLUGIN_FILE_EXTS "class,jar,zip"
+#define PLUGIN_MIME_COUNT 1
+
+#define FAILURE_MESSAGE "icedteanp plugin error: Failed to run %s." \
+  "  For more detail rerun \"firefox -g\" in a terminal window."
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+// Documentbase retrieval required definition.
+static NS_DEFINE_IID (kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID);
+#endif
+
+// Data directory for plugin.
+static gchar* data_directory = NULL;
+
+// Fully-qualified appletviewer executable.
+static gchar* appletviewer_executable = NULL;
+
+// Applet viewer input channel (needs to be static because it is used in plugin_in_pipe_callback)
+static GIOChannel* in_from_appletviewer = NULL;
+
+#ifdef __OS2__
+#define CLOSE_FD(fd) do { if (fd != -1) { close (fd); fd = -1; } } while (0)
+#endif
+
+#ifdef __OS2__
+int in_pipe[2] = { -1 };
+#else
+// Applet viewer input pipe name.
+gchar* in_pipe_name;
+#endif
+
+// Applet viewer input watch source.
+gint in_watch_source;
+
+#ifdef __OS2__
+int out_pipe[2] = { -1 };
+#else
+// Applet viewer output pipe name.
+gchar* out_pipe_name;
+#endif
+
+// Applet viewer output watch source.
+gint out_watch_source;
+
+// Thread ID of plug-in thread
+pthread_t itnp_plugin_thread_id;
+
+// Mutex to lock async call queue
+pthread_mutex_t pluginAsyncCallMutex;
+
+// Applet viewer output channel.
+GIOChannel* out_to_appletviewer;
+
+// Tracks jvm status
+gboolean jvm_up = FALSE;
+
+// Keeps track of initialization. NP_Initialize should only be
+// called once.
+gboolean initialized = false;
+
+// browser functions into mozilla
+NPNetscapeFuncs browser_functions;
+
+// Various message buses carrying information to/from Java, and internally
+MessageBus* plugin_to_java_bus;
+MessageBus* java_to_plugin_bus;
+//MessageBus* internal_bus = new MessageBus();
+
+// Processor for plugin requests
+PluginRequestProcessor* plugin_req_proc;
+
+// Sends messages to Java over the bus
+JavaMessageSender* java_req_proc;
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+// Documentbase retrieval type-punning union.
+typedef union
+{
+  void** void_field;
+  nsIPluginTagInfo2** info_field;
+} info_union;
+#endif
+
+// Static instance helper functions.
+// Have the browser allocate a new ITNPPluginData structure.
+static void plugin_data_new (ITNPPluginData** data);
+// Retrieve the current document's documentbase.
+static gchar* plugin_get_documentbase (NPP instance);
+// Notify the user that the appletviewer is not installed correctly.
+static void plugin_display_failure_dialog ();
+// Callback used to monitor input pipe status.
+static gboolean plugin_in_pipe_callback (GIOChannel* source,
+                                         GIOCondition condition,
+                                         gpointer plugin_data);
+// Callback used to monitor output pipe status.
+static gboolean plugin_out_pipe_callback (GIOChannel* source,
+                                          GIOCondition condition,
+                                          gpointer plugin_data);
+static NPError plugin_start_appletviewer (ITNPPluginData* data);
+static gchar* plugin_create_applet_tag (int16_t argc, char* argn[],
+                                        char* argv[]);
+static void plugin_stop_appletviewer ();
+// Uninitialize ITNPPluginData structure
+static void plugin_data_destroy (NPP instance);
+
+NPError get_cookie_info(const char* siteAddr, char** cookieString, uint32_t* len);
+NPError get_proxy_info(const char* siteAddr, char** proxy, uint32_t* len);
+void consume_message(gchar* message);
+void start_jvm_if_needed();
+static void appletviewer_monitor(GPid pid, gint status, gpointer data);
+void plugin_send_initialization_message(char* instance, gulong handle,
+                                               int width, int height,
+                                               char* url);
+
+// Global instance counter.
+// Mutex to protect plugin_instance_counter.
+static GMutex* plugin_instance_mutex = NULL;
+// A global variable for reporting GLib errors.  This must be free'd
+// and set to NULL after each use.
+static GError* channel_error = NULL;
+
+static GHashTable* instance_to_id_map = g_hash_table_new(NULL, NULL);
+static GHashTable* id_to_instance_map = g_hash_table_new(NULL, NULL);
+static gint instance_counter = 1;
+static GPid appletviewer_pid = -1;
+static guint appletviewer_watch_id = -1;
+
+int plugin_debug = getenv ("ICEDTEAPLUGIN_DEBUG") != NULL;
+int plugin_debug_suspend = (getenv("ICEDTEAPLUGIN_DEBUG") != NULL) &&
+        (strcmp(getenv("ICEDTEAPLUGIN_DEBUG"), "suspend") == 0);
+
+pthread_cond_t cond_message_available = PTHREAD_COND_INITIALIZER;
+
+// Functions prefixed by ITNP_ are instance functions.  They are called
+// by the browser and operate on instances of ITNPPluginData.
+// Functions prefixed by plugin_ are static helper functions.
+// Functions prefixed by NP_ are factory functions.  They are called
+// by the browser and provide functionality needed to create plugin
+// instances.
+
+// INSTANCE FUNCTIONS
+
+// Creates a new icedtea np plugin instance.  This function creates a
+// ITNPPluginData* and stores it in instance->pdata.  The following
+// ITNPPluginData fiels are initialized: instance_id, in_pipe_name,
+// in_from_appletviewer, in_watch_source, out_pipe_name,
+// out_to_appletviewer, out_watch_source, appletviewer_mutex, owner,
+// appletviewer_alive.  In addition two pipe files are created.  All
+// of those fields must be properly destroyed, and the pipes deleted,
+// by ITNP_Destroy.  If an error occurs during initialization then this
+// function will free anything that's been allocated so far, set
+// instance->pdata to NULL and return an error code.
+NPError
+ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode,
+         int16_t argc, char* argn[], char* argv[],
+         NPSavedData* saved)
+{
+  PLUGIN_DEBUG("ITNP_New\n");
+
+  static NPObject *window_ptr;
+  NPIdentifier identifier;
+  NPVariant member_ptr;
+  browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr);
+  identifier = browser_functions.getstringidentifier("document");
+  if (!browser_functions.hasproperty(instance, window_ptr, identifier))
+  {
+	printf("%s not found!\n", "document");
+  }
+  browser_functions.getproperty(instance, window_ptr, identifier, &member_ptr);
+
+  PLUGIN_DEBUG("Got variant %p\n", &member_ptr);
+
+
+  NPError np_error = NPERR_NO_ERROR;
+  ITNPPluginData* data = NULL;
+
+  gchar* documentbase = NULL;
+  gchar* read_message = NULL;
+  gchar* applet_tag = NULL;
+  gchar* cookie_info = NULL;
+
+  NPObject* npPluginObj = NULL;
+
+  if (!instance)
+    {
+      PLUGIN_ERROR ("Browser-provided instance pointer is NULL.");
+      np_error = NPERR_INVALID_INSTANCE_ERROR;
+      goto cleanup_done;
+    }
+
+  // data
+  plugin_data_new (&data);
+  if (data == NULL)
+    {
+      PLUGIN_ERROR ("Failed to allocate plugin data.");
+      np_error = NPERR_OUT_OF_MEMORY_ERROR;
+      goto cleanup_done;
+    }
+
+  // start the jvm if needed
+  start_jvm_if_needed();
+
+  // Initialize data->instance_id.
+  //
+  // instance_id should be unique for this process so we use a
+  // combination of getpid and plugin_instance_counter.
+  //
+  // Critical region.  Reference and increment plugin_instance_counter
+  // global.
+  g_mutex_lock (plugin_instance_mutex);
+
+  // data->instance_id
+  data->instance_id = g_strdup_printf ("%d",
+                                           instance_counter);
+
+  g_mutex_unlock (plugin_instance_mutex);
+
+  // data->appletviewer_mutex
+  data->appletviewer_mutex = g_mutex_new ();
+
+  g_mutex_lock (data->appletviewer_mutex);
+
+  // Documentbase retrieval.
+  documentbase = plugin_get_documentbase (instance);
+  if (documentbase && argc != 0)
+    {
+      // Send applet tag message to appletviewer.
+      applet_tag = plugin_create_applet_tag (argc, argn, argv);
+
+      data->applet_tag = (gchar*) malloc(strlen(applet_tag)*sizeof(gchar) + strlen(documentbase)*sizeof(gchar) + 32);
+      g_sprintf(data->applet_tag, "tag %s %s", documentbase, applet_tag);
+
+      data->is_applet_instance = true;
+    }
+
+  if (argc == 0)
+    {
+      data->is_applet_instance = false;
+    }
+
+  g_mutex_unlock (data->appletviewer_mutex);
+
+  // If initialization succeeded entirely then we store the plugin
+  // data in the instance structure and return.  Otherwise we free the
+  // data we've allocated so far and set instance->pdata to NULL.
+
+  // Set back-pointer to owner instance.
+  data->owner = instance;
+
+  // source of this instance
+  // don't use documentbase, it is cleared later
+  data->source = plugin_get_documentbase(instance);
+
+  instance->pdata = data;
+
+  goto cleanup_done;
+
+ cleanup_appletviewer_mutex:
+  g_free (data->appletviewer_mutex);
+  data->appletviewer_mutex = NULL;
+
+  // cleanup_instance_string:
+  g_free (data->instance_id);
+  data->instance_id = NULL;
+
+  // cleanup applet tag:
+  g_free (data->applet_tag);
+  data->applet_tag = NULL;
+
+  // cleanup_data:
+  // Eliminate back-pointer to plugin instance.
+  data->owner = NULL;
+  (*browser_functions.memfree) (data);
+  data = NULL;
+
+  // Initialization failed so return a NULL pointer for the browser
+  // data.
+  instance->pdata = NULL;
+
+ cleanup_done:
+  g_free (applet_tag);
+  applet_tag = NULL;
+  g_free (read_message);
+  read_message = NULL;
+  g_free (documentbase);
+  documentbase = NULL;
+
+  // store an identifier for this plugin
+  PLUGIN_DEBUG("Mapping id %d and instance %p\n", instance_counter, instance);
+  g_hash_table_insert(instance_to_id_map, instance, GINT_TO_POINTER(instance_counter));
+  g_hash_table_insert(id_to_instance_map, GINT_TO_POINTER(instance_counter), instance);
+  instance_counter++;
+
+  PLUGIN_DEBUG ("ITNP_New return\n");
+
+  return np_error;
+}
+
+// Starts the JVM if it is not already running
+void start_jvm_if_needed()
+{
+
+  // This is asynchronized function. It must
+  // have exclusivity when running.
+
+  GMutex *vm_start_mutex = g_mutex_new();
+  g_mutex_lock(vm_start_mutex);
+
+  PLUGIN_DEBUG("Checking JVM status...\n");
+
+  // If the jvm is already up, do nothing
+  if (jvm_up)
+  {
+      PLUGIN_DEBUG("JVM is up. Returning.\n");
+      return;
+  }
+
+  PLUGIN_DEBUG("No JVM is running. Attempting to start one...\n");
+
+  NPError np_error = NPERR_NO_ERROR;
+  ITNPPluginData* data = NULL;
+
+  // Create appletviewer-to-plugin pipe which we refer to as the input
+  // pipe.
+
+#ifdef __OS2__
+  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, in_pipe) == -1)
+    {
+      PLUGIN_ERROR_TWO ("Failed to create input pipe", strerror (errno));
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_in_pipe;
+    }
+  PLUGIN_DEBUG ("ITNP_New: created input fifo: %d/%d\n", in_pipe [0], in_pipe [1]);
+#else
+  // in_pipe_name
+  in_pipe_name = g_strdup_printf ("%s/%d-icedteanp-appletviewer-to-plugin",
+                                         data_directory, getpid());
+  if (!in_pipe_name)
+    {
+      PLUGIN_ERROR ("Failed to create input pipe name.");
+      np_error = NPERR_OUT_OF_MEMORY_ERROR;
+      // If in_pipe_name is NULL then the g_free at
+      // cleanup_in_pipe_name will simply return.
+      goto cleanup_in_pipe_name;
+    }
+
+  // clean up any older pip
+  unlink (in_pipe_name);
+
+  PLUGIN_DEBUG ("ITNP_New: creating input fifo: %s\n", in_pipe_name);
+  if (mkfifo (in_pipe_name, 0600) == -1 && errno != EEXIST)
+    {
+      PLUGIN_ERROR_TWO ("Failed to create input pipe", strerror (errno));
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_in_pipe_name;
+    }
+  PLUGIN_DEBUG ("ITNP_New: created input fifo: %s\n", in_pipe_name);
+#endif
+
+  // Create plugin-to-appletviewer pipe which we refer to as the
+  // output pipe.
+
+#ifdef __OS2__
+  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, out_pipe) == -1)
+    {
+      PLUGIN_ERROR_TWO ("Failed to create output pipe", strerror (errno));
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_out_pipe;
+    }
+  PLUGIN_DEBUG ("ITNP_New: created output fifo: %d/%d\n", out_pipe [0], out_pipe [1]);
+#else
+  // out_pipe_name
+  out_pipe_name = g_strdup_printf ("%s/%d-icedteanp-plugin-to-appletviewer",
+                                         data_directory, getpid());
+
+  if (!out_pipe_name)
+    {
+      PLUGIN_ERROR ("Failed to create output pipe name.");
+      np_error = NPERR_OUT_OF_MEMORY_ERROR;
+      goto cleanup_out_pipe_name;
+    }
+
+  // clean up any older pip
+  unlink (out_pipe_name);
+
+  PLUGIN_DEBUG ("ITNP_New: creating output fifo: %s\n", out_pipe_name);
+  if (mkfifo (out_pipe_name, 0600) == -1 && errno != EEXIST)
+    {
+      PLUGIN_ERROR_TWO ("Failed to create output pipe", strerror (errno));
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_out_pipe_name;
+    }
+  PLUGIN_DEBUG ("ITNP_New: created output fifo: %s\n", out_pipe_name);
+#endif
+
+  // Start a separate appletviewer process for each applet, even if
+  // there are multiple applets in the same page.  We may need to
+  // change this behaviour if we find pages with multiple applets that
+  // rely on being run in the same VM.
+
+#ifdef __OS2__
+  // make sure parent ends are not inherited by the child (otherwise read() on
+  // the child's side will not be aborted when the parent closes its end)
+  fcntl (in_pipe [0], F_SETFD, FD_CLOEXEC);
+  fcntl (out_pipe [0], F_SETFD, FD_CLOEXEC);
+#endif
+
+  np_error = plugin_start_appletviewer (data);
+
+#ifdef __OS2__
+  // close child ends of the pipes (not needed)
+  CLOSE_FD (in_pipe [1]);
+  CLOSE_FD (out_pipe [1]);
+#endif
+
+  // Create plugin-to-appletviewer channel.  The default encoding for
+  // the file is UTF-8.
+  // out_to_appletviewer
+#ifdef __OS2__
+  out_to_appletviewer = g_io_channel_unix_new (out_pipe [0]);
+#else
+  out_to_appletviewer = g_io_channel_new_file (out_pipe_name,
+                                               "w", &channel_error);
+#endif
+  if (!out_to_appletviewer)
+    {
+      if (channel_error)
+        {
+          PLUGIN_ERROR_TWO ("Failed to create output channel",
+                            channel_error->message);
+          g_error_free (channel_error);
+          channel_error = NULL;
+        }
+      else
+        PLUGIN_ERROR ("Failed to create output channel");
+
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_out_to_appletviewer;
+    }
+
+  // Watch for hangup and error signals on the output pipe.
+  out_watch_source =
+    g_io_add_watch (out_to_appletviewer,
+                    (GIOCondition) (G_IO_ERR | G_IO_HUP),
+                    plugin_out_pipe_callback, (gpointer) out_to_appletviewer);
+
+  // Create appletviewer-to-plugin channel.  The default encoding for
+  // the file is UTF-8.
+  // in_from_appletviewer
+#ifdef __OS2__
+  in_from_appletviewer = g_io_channel_unix_new (in_pipe [0]);
+#else
+  in_from_appletviewer = g_io_channel_new_file (in_pipe_name,
+                                                      "r", &channel_error);
+#endif
+  if (!in_from_appletviewer)
+    {
+      if (channel_error)
+        {
+          PLUGIN_ERROR_TWO ("Failed to create input channel",
+                            channel_error->message);
+          g_error_free (channel_error);
+          channel_error = NULL;
+        }
+      else
+        PLUGIN_ERROR ("Failed to create input channel");
+
+      np_error = NPERR_GENERIC_ERROR;
+      goto cleanup_in_from_appletviewer;
+    }
+
+  // Watch for hangup and error signals on the input pipe.
+  in_watch_source =
+    g_io_add_watch (in_from_appletviewer,
+                    (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_HUP),
+                    plugin_in_pipe_callback, (gpointer) in_from_appletviewer);
+
+  jvm_up = TRUE;
+
+  goto done;
+
+  // Free allocated data
+
+ cleanup_in_watch_source:
+  // Removing a source is harmless if it fails since it just means the
+  // source has already been removed.
+  g_source_remove (in_watch_source);
+  in_watch_source = 0;
+
+ cleanup_in_from_appletviewer:
+  if (in_from_appletviewer)
+    g_io_channel_unref (in_from_appletviewer);
+  in_from_appletviewer = NULL;
+
+  // cleanup_out_watch_source:
+  g_source_remove (out_watch_source);
+  out_watch_source = 0;
+
+ cleanup_out_to_appletviewer:
+  if (out_to_appletviewer)
+    g_io_channel_unref (out_to_appletviewer);
+  out_to_appletviewer = NULL;
+
+  // cleanup_out_pipe:
+#ifdef __OS2__
+ cleanup_out_pipe:
+  CLOSE_FD (out_pipe [0]);
+  CLOSE_FD (out_pipe [1]);
+#else
+  // Delete output pipe.
+  PLUGIN_DEBUG ("ITNP_New: deleting output fifo: %s\n", out_pipe_name);
+  unlink (out_pipe_name);
+  PLUGIN_DEBUG ("ITNP_New: deleted output fifo: %s\n", out_pipe_name);
+
+ cleanup_out_pipe_name:
+  g_free (out_pipe_name);
+  out_pipe_name = NULL;
+#endif
+
+  // cleanup_in_pipe:
+#ifdef __OS2__
+ cleanup_in_pipe:
+  CLOSE_FD (in_pipe [0]);
+  CLOSE_FD (in_pipe [1]);
+#else
+  // Delete input pipe.
+  PLUGIN_DEBUG ("ITNP_New: deleting input fifo: %s\n", in_pipe_name);
+  unlink (in_pipe_name);
+  PLUGIN_DEBUG ("ITNP_New: deleted input fifo: %s\n", in_pipe_name);
+
+ cleanup_in_pipe_name:
+  g_free (in_pipe_name);
+  in_pipe_name = NULL;
+#endif
+
+ done:
+
+  // Now other threads may re-enter.. unlock the mutex
+  g_mutex_unlock(vm_start_mutex);
+
+}
+
+NPError
+ITNP_GetValue (NPP instance, NPPVariable variable, void* value)
+{
+  PLUGIN_DEBUG ("ITNP_GetValue\n");
+
+  NPError np_error = NPERR_NO_ERROR;
+
+  switch (variable)
+    {
+    // This plugin needs XEmbed support.
+    case NPPVpluginNeedsXEmbed:
+      {
+        PLUGIN_DEBUG ("ITNP_GetValue: returning TRUE for NeedsXEmbed.\n");
+        bool* bool_value = (bool*) value;
+        *bool_value = true;
+      }
+      break;
+    case NPPVpluginScriptableNPObject:
+      {
+         *(NPObject **)value = get_scriptable_object(instance);
+      }
+      break;
+    default:
+      PLUGIN_ERROR ("Unknown plugin value requested.");
+      np_error = NPERR_GENERIC_ERROR;
+      break;
+    }
+
+  PLUGIN_DEBUG ("ITNP_GetValue return\n");
+
+  return np_error;
+}
+
+NPError
+ITNP_Destroy (NPP instance, NPSavedData** save)
+{
+  PLUGIN_DEBUG ("ITNP_Destroy %p\n", instance);
+
+  ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
+
+  int id = get_id_from_instance(instance);
+
+  // Let Java know that this applet needs to be destroyed
+  gchar* msg = (gchar*) g_malloc(512*sizeof(gchar)); // 512 is more than enough. We need < 100
+  g_sprintf(msg, "instance %d destroy", id);
+  plugin_send_message_to_appletviewer(msg);
+  g_free(msg);
+  msg = NULL;
+
+  if (data)
+    {
+      // Free plugin data.
+      plugin_data_destroy (instance);
+    }
+
+  g_hash_table_remove(instance_to_id_map, instance);
+  g_hash_table_remove(id_to_instance_map, GINT_TO_POINTER(id));
+
+  IcedTeaPluginUtilities::invalidateInstance(instance);
+
+  PLUGIN_DEBUG ("ITNP_Destroy return\n");
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+ITNP_SetWindow (NPP instance, NPWindow* window)
+{
+  PLUGIN_DEBUG ("ITNP_SetWindow\n");
+
+  if (instance == NULL)
+    {
+      PLUGIN_ERROR ("Invalid instance.");
+
+      return NPERR_INVALID_INSTANCE_ERROR;
+    }
+
+  gpointer id_ptr = g_hash_table_lookup(instance_to_id_map, instance);
+
+  gint id = 0;
+  if (id_ptr)
+    {
+      id = GPOINTER_TO_INT(id_ptr);
+    }
+
+  ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
+
+  // Simply return if we receive a NULL window.
+  if ((window == NULL) || (window->window == NULL))
+    {
+      PLUGIN_DEBUG ("ITNP_SetWindow: got NULL window.\n");
+
+      return NPERR_NO_ERROR;
+    }
+
+#ifdef __OS2__
+  void *wnd = wrap_window_handle (window->window);
+  if (!wnd)
+      return NPERR_GENERIC_ERROR;
+
+  PLUGIN_DEBUG ("ITNP_SetWindow: wrapped window handle %d (%x) in %d (%x)\n",
+                window->window, window->window, wnd, wnd);
+#endif
+
+  if (data->window_handle)
+    {
+      // The window already exists.
+      if (data->window_handle == wnd)
+    {
+          // The parent window is the same as in previous calls.
+          PLUGIN_DEBUG ("ITNP_SetWindow: window already exists.\n");
+
+          // Critical region.  Read data->appletviewer_mutex and send
+          // a message to the appletviewer.
+          g_mutex_lock (data->appletviewer_mutex);
+
+      if (jvm_up)
+        {
+          gboolean dim_changed = FALSE;
+
+          // The window is the same as it was for the last
+          // SetWindow call.
+          if (window->width != data->window_width)
+        {
+                  PLUGIN_DEBUG ("ITNP_SetWindow: window width changed.\n");
+          // The width of the plugin window has changed.
+
+                  // Store the new width.
+                  data->window_width = window->width;
+                  dim_changed = TRUE;
+        }
+
+          if (window->height != data->window_height)
+        {
+                  PLUGIN_DEBUG ("ITNP_SetWindow: window height changed.\n");
+          // The height of the plugin window has changed.
+
+                  // Store the new height.
+                  data->window_height = window->height;
+
+                  dim_changed = TRUE;
+        }
+
+        if (dim_changed) {
+            gchar* message = g_strdup_printf ("instance %d width %d height %d",
+                                                id, window->width, window->height);
+            plugin_send_message_to_appletviewer (message);
+            g_free (message);
+            message = NULL;
+        }
+
+
+        }
+      else
+        {
+              // The appletviewer is not running.
+          PLUGIN_DEBUG ("ITNP_SetWindow: appletviewer is not running.\n");
+        }
+
+          g_mutex_unlock (data->appletviewer_mutex);
+    }
+      else
+    {
+      // The parent window has changed.  This branch does run but
+      // doing nothing in response seems to be sufficient.
+      PLUGIN_DEBUG ("ITNP_SetWindow: parent window changed.\n");
+    }
+    }
+  else
+    {
+
+	  // Else this is initialization
+      PLUGIN_DEBUG ("ITNP_SetWindow: setting window.\n");
+
+      // Critical region.  Send messages to appletviewer.
+      g_mutex_lock (data->appletviewer_mutex);
+
+      // Store the window handle and dimensions
+      data->window_handle = wnd;
+      data->window_width = window->width;
+      data->window_height = window->height;
+
+      // Now we have everything. Send this data to the Java side
+      plugin_send_initialization_message(
+    		  data->instance_id, (gulong) data->window_handle,
+    		  data->window_width, data->window_height, data->applet_tag);
+
+      g_mutex_unlock (data->appletviewer_mutex);
+
+    }
+
+  PLUGIN_DEBUG ("ITNP_SetWindow return\n");
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+ITNP_NewStream (NPP instance, NPMIMEType type, NPStream* stream,
+               NPBool seekable, uint16_t* stype)
+{
+  PLUGIN_DEBUG ("ITNP_NewStream\n");
+
+  PLUGIN_DEBUG ("ITNP_NewStream return\n");
+
+  return NPERR_GENERIC_ERROR;
+}
+
+void
+ITNP_StreamAsFile (NPP instance, NPStream* stream, const char* filename)
+{
+  PLUGIN_DEBUG ("ITNP_StreamAsFile\n");
+
+  PLUGIN_DEBUG ("ITNP_StreamAsFile return\n");
+}
+
+NPError
+ITNP_DestroyStream (NPP instance, NPStream* stream, NPReason reason)
+{
+  PLUGIN_DEBUG ("ITNP_DestroyStream\n");
+
+  PLUGIN_DEBUG ("ITNP_DestroyStream return\n");
+
+  return NPERR_NO_ERROR;
+}
+
+int32_t
+ITNP_WriteReady (NPP instance, NPStream* stream)
+{
+  PLUGIN_DEBUG ("ITNP_WriteReady\n");
+
+  PLUGIN_DEBUG ("ITNP_WriteReady return\n");
+
+  return 0;
+}
+
+int32_t
+ITNP_Write (NPP instance, NPStream* stream, int32_t offset, int32_t len,
+           void* buffer)
+{
+  PLUGIN_DEBUG ("ITNP_Write\n");
+
+  PLUGIN_DEBUG ("ITNP_Write return\n");
+
+  return 0;
+}
+
+void
+ITNP_Print (NPP instance, NPPrint* platformPrint)
+{
+  PLUGIN_DEBUG ("ITNP_Print\n");
+
+  PLUGIN_DEBUG ("ITNP_Print return\n");
+}
+
+int16_t
+ITNP_HandleEvent (NPP instance, void* event)
+{
+  PLUGIN_DEBUG ("ITNP_HandleEvent\n");
+
+  PLUGIN_DEBUG ("ITNP_HandleEvent return\n");
+
+  return 0;
+}
+
+void
+ITNP_URLNotify (NPP instance, const char* url, NPReason reason,
+               void* notifyData)
+{
+  PLUGIN_DEBUG ("ITNP_URLNotify\n");
+
+  PLUGIN_DEBUG ("ITNP_URLNotify return\n");
+}
+
+NPError
+get_cookie_info(const char* siteAddr, char** cookieString, uint32_t* len)
+{
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+  nsresult rv;
+  nsCOMPtr<nsIScriptSecurityManager> sec_man =
+    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+
+  if (!sec_man) {
+    return NPERR_GENERIC_ERROR;
+  }
+
+  nsCOMPtr<nsIIOService> io_svc = do_GetService("@mozilla.org/network/io-service;1", &rv);
+
+  if (NS_FAILED(rv) || !io_svc) {
+    return NPERR_GENERIC_ERROR;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  io_svc->NewURI(nsCString(siteAddr), NULL, NULL, getter_AddRefs(uri));
+
+  nsCOMPtr<nsICookieService> cookie_svc = do_GetService("@mozilla.org/cookieService;1", &rv);
+
+  if (NS_FAILED(rv) || !cookie_svc) {
+    return NPERR_GENERIC_ERROR;
+  }
+
+  rv = cookie_svc->GetCookieString(uri, NULL, cookieString);
+
+  if (NS_FAILED(rv) || !*cookieString) {
+    return NPERR_GENERIC_ERROR;
+  }
+
+#else
+
+  // getvalueforurl needs an NPP instance. Quite frankly, there is no easy way
+  // to know which instance needs the information, as applets on Java side can
+  // be multi-threaded and the thread making a proxy.cookie request cannot be
+  // easily tracked.
+
+  // Fortunately, XULRunner does not care about the instance as long as it is
+  // valid. So we just pick the first valid one and use it. Proxy/Cookie
+  // information is not instance specific anyway, it is URL specific.
+
+  if (browser_functions.getvalueforurl)
+  {
+      GHashTableIter iter;
+      gpointer id, instance;
+
+      g_hash_table_iter_init (&iter, instance_to_id_map);
+      g_hash_table_iter_next (&iter, &instance, &id);
+
+      return browser_functions.getvalueforurl((NPP) instance, NPNURLVCookie, siteAddr, cookieString, len);
+  } else
+  {
+      return NPERR_GENERIC_ERROR;
+  }
+
+#endif
+
+  return NPERR_NO_ERROR;
+}
+
+// HELPER FUNCTIONS
+
+static void
+plugin_data_new (ITNPPluginData** data)
+{
+  PLUGIN_DEBUG ("plugin_data_new\n");
+
+  *data = (ITNPPluginData*)
+    (*browser_functions.memalloc) (sizeof (struct ITNPPluginData));
+
+  // appletviewer_alive is false until the applet viewer is spawned.
+  if (*data)
+    memset (*data, 0, sizeof (struct ITNPPluginData));
+
+  PLUGIN_DEBUG ("plugin_data_new return\n");
+}
+
+
+
+// Documentbase retrieval.  This function gets the current document's
+// documentbase.  This function relies on browser-private data so it
+// will only work when the plugin is loaded in a Mozilla-based
+// browser.  We could not find a way to retrieve the documentbase
+// using the original Netscape plugin API so we use the XPCOM API
+// instead.
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+static gchar*
+plugin_get_documentbase (NPP instance)
+{
+  PLUGIN_DEBUG ("plugin_get_documentbase\n");
+
+  nsIPluginInstance* xpcom_instance = NULL;
+  nsIPluginInstancePeer* peer = NULL;
+  nsresult result = 0;
+  nsIPluginTagInfo2* pluginTagInfo2 = NULL;
+  info_union u = { NULL };
+  char const* documentbase = NULL;
+  gchar* documentbase_copy = NULL;
+
+  xpcom_instance = (nsIPluginInstance*) (instance->ndata);
+  if (!xpcom_instance)
+    {
+      PLUGIN_ERROR ("xpcom_instance is NULL.");
+      goto cleanup_done;
+    }
+
+  xpcom_instance->GetPeer (&peer);
+  if (!peer)
+    {
+      PLUGIN_ERROR ("peer is NULL.");
+      goto cleanup_done;
+    }
+
+  u.info_field = &pluginTagInfo2;
+
+  result = peer->QueryInterface (kIPluginTagInfo2IID,
+                                 u.void_field);
+  if (result || !pluginTagInfo2)
+    {
+      PLUGIN_ERROR ("pluginTagInfo2 retrieval failed.");
+      goto cleanup_peer;
+    }
+
+  pluginTagInfo2->GetDocumentBase (&documentbase);
+
+  if (!documentbase)
+    {
+      // NULL => dummy instantiation for LiveConnect
+      goto cleanup_plugintaginfo2;
+    }
+
+  documentbase_copy = g_strdup (documentbase);
+
+  // Release references.
+ cleanup_plugintaginfo2:
+  NS_RELEASE (pluginTagInfo2);
+
+ cleanup_peer:
+  NS_RELEASE (peer);
+
+ cleanup_done:
+  PLUGIN_DEBUG ("plugin_get_documentbase return\n");
+
+  PLUGIN_DEBUG("plugin_get_documentbase returning: %s\n", documentbase_copy);
+  return documentbase_copy;
+}
+#else
+static gchar*
+plugin_get_documentbase (NPP instance)
+{
+  PLUGIN_DEBUG ("plugin_get_documentbase\n");
+
+  char const* documentbase = NULL;
+  gchar* documentbase_copy = NULL;
+
+  // FIXME: This method is not ideal, but there are no known NPAPI call
+  // for this. See thread for more information:
+  // http://www.mail-archive.com/chromium-dev@googlegroups.com/msg04844.html
+
+  // Additionally, since it is insecure, we cannot use it for making
+  // security decisions.
+  NPObject* window;
+  browser_functions.getvalue(instance, NPNVWindowNPObject, &window);
+
+  NPVariant location;
+  NPIdentifier location_id = browser_functions.getstringidentifier("location");
+  browser_functions.getproperty(instance, window, location_id, &location);
+
+  NPVariant href;
+  NPIdentifier href_id = browser_functions.getstringidentifier("href");
+  browser_functions.getproperty(instance, NPVARIANT_TO_OBJECT(location), 
+                               href_id, &href);
+
+  // Strip everything after the last "/"
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+  gchar** parts = g_strsplit (NPVARIANT_TO_STRING(href).utf8characters, "/", -1);
+#else
+  gchar** parts = g_strsplit (NPVARIANT_TO_STRING(href).UTF8Characters, "/", -1);
+#endif
+  guint parts_sz = g_strv_length (parts);
+
+  std::string location_str;
+  for (int i=0; i < parts_sz - 1; i++)
+  {
+      location_str += parts[i];
+      location_str += "/";
+  }
+
+  documentbase_copy = g_strdup (location_str.c_str());
+
+  // Release references.
+  browser_functions.releasevariantvalue(&href);
+  browser_functions.releasevariantvalue(&location);
+ cleanup_done:
+  PLUGIN_DEBUG ("plugin_get_documentbase return\n");
+  PLUGIN_DEBUG("plugin_get_documentbase returning: %s\n", documentbase_copy);
+
+  return documentbase_copy;
+}
+#endif
+
+// This function displays an error message if the appletviewer has not
+// been installed correctly.
+static void
+plugin_display_failure_dialog ()
+{
+#ifdef __OS2__
+  gchar *msg = NULL;
+
+  PLUGIN_DEBUG ("plugin_display_failure_dialog\n");
+
+  msg = g_strdup_printf (FAILURE_MESSAGE, appletviewer_executable);
+  WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
+                 msg, "Error", 0, MB_ERROR | MB_OK | MB_MOVEABLE);
+  g_free(msg);
+#else
+  GtkWidget* dialog = NULL;
+
+  PLUGIN_DEBUG ("plugin_display_failure_dialog\n");
+
+  dialog = gtk_message_dialog_new (NULL,
+                                   GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_ERROR,
+                                   GTK_BUTTONS_CLOSE,
+                                   FAILURE_MESSAGE,
+                                   appletviewer_executable);
+  gtk_widget_show_all (dialog);
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+#endif
+
+  PLUGIN_DEBUG ("plugin_display_failure_dialog return\n");
+}
+
+
+
+// plugin_in_pipe_callback is called when data is available on the
+// input pipe, or when the appletviewer crashes or is killed.  It may
+// be called after data has been destroyed in which case it simply
+// returns FALSE to remove itself from the glib main loop.
+static gboolean
+plugin_in_pipe_callback (GIOChannel* source,
+                         GIOCondition condition,
+                         gpointer plugin_data)
+{
+  PLUGIN_DEBUG ("plugin_in_pipe_callback\n");
+
+  gboolean keep_installed = TRUE;
+
+  if (condition & G_IO_IN)
+    {
+      gchar* message = NULL;
+
+      if (g_io_channel_read_line (in_from_appletviewer,
+                                  &message, NULL, NULL,
+                                  &channel_error)
+          != G_IO_STATUS_NORMAL)
+        {
+          if (channel_error)
+            {
+              PLUGIN_ERROR_TWO ("Failed to read line from input channel",
+                                channel_error->message);
+              g_error_free (channel_error);
+              channel_error = NULL;
+            }
+          else
+            PLUGIN_ERROR ("Failed to read line from input channel");
+#ifdef __OS2__
+          // G_IO_ERR/HUP is not reported on file/pipe handles, simulate it
+          condition = (GIOCondition) (condition | G_IO_ERR);
+#endif
+        } else
+        {
+          consume_message(message);
+        }
+
+      g_free (message);
+      message = NULL;
+
+      keep_installed = TRUE;
+    }
+
+  if (condition & (G_IO_ERR | G_IO_HUP))
+    {
+      PLUGIN_DEBUG ("appletviewer has stopped.\n");
+      keep_installed = FALSE;
+    }
+
+  PLUGIN_DEBUG ("plugin_in_pipe_callback return\n");
+
+  return keep_installed;
+}
+
+void consume_message(gchar* message) {
+
+	PLUGIN_DEBUG ("  PIPE: plugin read: %s\n", message);
+
+  if (g_str_has_prefix (message, "instance"))
+    {
+
+	  ITNPPluginData* data;
+      gchar** parts = g_strsplit (message, " ", -1);
+      guint parts_sz = g_strv_length (parts);
+
+      int instance_id = atoi(parts[1]);
+      NPP instance = (NPP) g_hash_table_lookup(id_to_instance_map,
+                                         GINT_TO_POINTER(instance_id));
+
+      if (instance_id > 0 && !instance)
+        {
+          PLUGIN_DEBUG("Instance %d is not active. Refusing to consume message \"%s\"\n", instance_id, message);
+          return;
+        }
+      else if (instance)
+        {
+           data = (ITNPPluginData*) instance->pdata;
+        }
+
+      if (g_str_has_prefix (parts[2], "status"))
+        {
+
+          // clear the "instance X status" parts
+          sprintf(parts[0], "");
+          sprintf(parts[1], "");
+          sprintf(parts[2], "");
+
+          // join the rest
+          gchar* status_message = g_strjoinv(" ", parts);
+          PLUGIN_DEBUG ("plugin_in_pipe_callback: setting status %s\n", status_message);
+          (*browser_functions.status) (data->owner, status_message);
+
+          g_free(status_message);
+          status_message = NULL;
+        }
+      else if (g_str_has_prefix (parts[1], "internal"))
+    	{
+    	  //s->post(message);
+    	}
+      else
+        {
+          // All other messages are posted to the bus, and subscribers are
+          // expected to take care of them. They better!
+
+    	  java_to_plugin_bus->post(message);
+        }
+
+        g_strfreev (parts);
+        parts = NULL;
+    }
+  else if (g_str_has_prefix (message, "context"))
+    {
+	      java_to_plugin_bus->post(message);
+    }
+  else if (g_str_has_prefix (message, "plugin "))
+    {
+      // internal plugin related message
+      gchar** parts = g_strsplit (message, " ", 5);
+      if (g_str_has_prefix(parts[1], "PluginProxyInfo"))
+      {
+        gchar* proxy;
+        uint32_t len;
+
+        gchar* decoded_url = (gchar*) calloc(strlen(parts[4]) + 1, sizeof(gchar));
+        IcedTeaPluginUtilities::decodeURL(parts[4], &decoded_url);
+        PLUGIN_DEBUG("parts[0]=%s, parts[1]=%s, reference, parts[3]=%s, parts[4]=%s -- decoded_url=%s\n", parts[0], parts[1], parts[3], parts[4], decoded_url);
+
+        gchar* proxy_info;
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+	proxy = (char*) malloc(sizeof(char)*2048);
+#endif
+
+        proxy_info = g_strconcat ("plugin PluginProxyInfo reference ", parts[3], " ", NULL);
+        if (get_proxy_info(decoded_url, &proxy, &len) == NPERR_NO_ERROR)
+          {
+            proxy_info = g_strconcat (proxy_info, proxy, NULL);
+          }
+
+        PLUGIN_DEBUG("Proxy info: %s\n", proxy_info);
+        plugin_send_message_to_appletviewer(proxy_info);
+
+        g_free(decoded_url);
+        decoded_url = NULL;
+        g_free(proxy_info);
+        proxy_info = NULL;
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+	g_free(proxy);
+	proxy = NULL;
+#endif
+
+      } else if (g_str_has_prefix(parts[1], "PluginCookieInfo"))
+      {
+        gchar* decoded_url = (gchar*) calloc(strlen(parts[4])+1, sizeof(gchar));
+        IcedTeaPluginUtilities::decodeURL(parts[4], &decoded_url);
+
+        gchar* cookie_info = g_strconcat ("plugin PluginCookieInfo reference ", parts[3], " ", NULL);
+        gchar* cookie_string;
+        uint32_t len;
+        if (get_cookie_info(decoded_url, &cookie_string, &len) == NPERR_NO_ERROR)
+        {
+            cookie_info = g_strconcat (cookie_info, cookie_string, NULL);
+        }
+
+        PLUGIN_DEBUG("Cookie info: %s\n", cookie_info);
+        plugin_send_message_to_appletviewer(cookie_info);
+
+        g_free(decoded_url);
+        decoded_url = NULL;
+        g_free(cookie_info);
+        cookie_info = NULL;
+      }
+    }
+  else
+    {
+        g_print ("  Unable to handle message: %s\n", message);
+    }
+}
+
+void get_instance_from_id(int id, NPP& instance)
+{
+    instance = (NPP) g_hash_table_lookup(id_to_instance_map,
+                                       GINT_TO_POINTER(id));
+}
+
+int get_id_from_instance(NPP instance)
+{
+    int id = GPOINTER_TO_INT(g_hash_table_lookup(instance_to_id_map,
+                                                       instance));
+    PLUGIN_DEBUG("Returning id %d for instance %p\n", id, instance);
+    return id;
+}
+
+NPError
+get_proxy_info(const char* siteAddr, char** proxy, uint32_t* len)
+{
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+  nsresult rv;
+
+  // Initialize service variables
+  nsCOMPtr<nsIProtocolProxyService> proxy_svc = do_GetService("@mozilla.org/network/protocol-proxy-service;1", &rv);
+
+  if (!proxy_svc) {
+      printf("Cannot initialize proxy service\n");
+      return NPERR_GENERIC_ERROR;
+  }
+
+  nsCOMPtr<nsIIOService> io_svc = do_GetService("@mozilla.org/network/io-service;1", &rv);
+
+  if (NS_FAILED(rv) || !io_svc) {
+    printf("Cannot initialize io service\n");
+    return NPERR_GENERIC_ERROR;
+  }
+
+  // uri which needs to be accessed
+  nsCOMPtr<nsIURI> uri;
+  io_svc->NewURI(nsCString(siteAddr), NULL, NULL, getter_AddRefs(uri));
+
+  // find the proxy address if any
+  nsCOMPtr<nsIProxyInfo> info;
+  proxy_svc->Resolve(uri, 0, getter_AddRefs(info));
+
+  // if there is no proxy found, return immediately
+  if (!info) {
+     PLUGIN_DEBUG("%s does not need a proxy\n", siteAddr);
+     return NPERR_GENERIC_ERROR;
+  }
+
+  // if proxy info is available, extract it
+  nsCString phost;
+  PRInt32 pport;
+  nsCString ptype;
+
+  info->GetHost(phost);
+  info->GetPort(&pport);
+  info->GetType(ptype);
+
+  // resolve the proxy address to an IP
+  nsCOMPtr<nsIDNSService> dns_svc = do_GetService("@mozilla.org/network/dns-service;1", &rv);
+
+  if (!dns_svc) {
+      printf("Cannot initialize DNS service\n");
+      return NPERR_GENERIC_ERROR;
+  }
+
+  nsCOMPtr<nsIDNSRecord> record;
+  dns_svc->Resolve(phost, 0U, getter_AddRefs(record));
+
+  // TODO: Add support for multiple ips
+  nsDependentCString ipAddr;
+  record->GetNextAddrAsString(ipAddr);
+
+  if (!strcmp(ptype.get(), "http"))
+  {
+      snprintf(*proxy, sizeof(char)*1024, "%s %s:%d", "PROXY", ipAddr.get(), pport);
+  } else
+  {
+      snprintf(*proxy, sizeof(char)*1024, "%s %s:%d", "SOCKS", ipAddr.get(), pport);
+  }
+
+  *len = strlen(*proxy);
+
+  PLUGIN_DEBUG("Proxy info for %s: %s\n", siteAddr, *proxy);
+
+#else
+
+  if (browser_functions.getvalueforurl)
+  {
+
+      // As in get_cookie_info, we use the first active instance
+      GHashTableIter iter;
+      gpointer id, instance;
+
+      g_hash_table_iter_init (&iter, instance_to_id_map);
+      g_hash_table_iter_next (&iter, &instance, &id);
+
+      browser_functions.getvalueforurl((NPP) instance, NPNURLVProxy, siteAddr, proxy, len);
+  } else
+  {
+      return NPERR_GENERIC_ERROR;
+  }
+#endif
+
+  return NPERR_NO_ERROR;
+}
+
+// plugin_out_pipe_callback is called when the appletviewer crashes or
+// is killed.  It may be called after data has been destroyed in which
+// case it simply returns FALSE to remove itself from the glib main
+// loop.
+static gboolean
+plugin_out_pipe_callback (GIOChannel* source,
+                          GIOCondition condition,
+                          gpointer plugin_data)
+{
+  PLUGIN_DEBUG ("plugin_out_pipe_callback\n");
+
+  ITNPPluginData* data = (ITNPPluginData*) plugin_data;
+
+  PLUGIN_DEBUG ("plugin_out_pipe_callback: appletviewer has stopped.\n");
+
+  PLUGIN_DEBUG ("plugin_out_pipe_callback return\n");
+
+  return FALSE;
+}
+
+// remove all components from LD_LIBRARY_PATH, which start with
+// MOZILLA_FIVE_HOME; firefox has its own NSS based security provider,
+// which conflicts with the one configured in nss.cfg.
+static gchar*
+plugin_filter_ld_library_path(gchar *path_old)
+{
+  gchar *moz_home = g_strdup (g_getenv ("MOZILLA_FIVE_HOME"));
+  gchar *moz_prefix;
+  gchar *path_new;
+  gchar** components;
+  int i1, i2;
+
+  if (moz_home == NULL || path_old == NULL || strlen (path_old) == 0)
+    return path_old;
+  if (g_str_has_suffix (moz_home, "/"))
+    moz_home[strlen (moz_home - 1)] = '\0';
+  moz_prefix = g_strconcat (moz_home, "/", NULL);
+
+  components = g_strsplit (path_old, ":", -1);
+  for (i1 = 0, i2 = 0; components[i1] != NULL; i1++)
+    {
+      if (g_strcmp0 (components[i1], moz_home) == 0
+	  || g_str_has_prefix (components[i1], moz_home))
+	components[i2] = components[i1];
+      else
+	components[i2++] = components[i1];
+    }
+  components[i2] = NULL;
+
+  if (i1 > i2)
+    path_new = g_strjoinv (":", components);
+  g_strfreev (components);
+  g_free (moz_home);
+  g_free (moz_prefix);
+  g_free (path_old);
+
+  if (path_new == NULL || strlen (path_new) == 0)
+    {
+      PLUGIN_DEBUG("Unset LD_LIBRARY_PATH\n");
+      return NULL;
+    }
+  else
+    {
+      PLUGIN_DEBUG ("Set LD_LIBRARY_PATH: %s\n", path_new);
+      return path_new;
+    }
+}
+
+// build the environment to pass to the external plugin process
+static gchar**
+plugin_filter_environment(void)
+{
+  gchar **var_names = g_listenv();
+  gchar **new_env = (gchar**) malloc(sizeof(gchar*) * (g_strv_length (var_names) + 1));
+  int i_var, i_env;
+
+  for (i_var = 0, i_env = 0; var_names[i_var] != NULL; i_var++)
+    {
+      gchar *env_value = g_strdup (g_getenv (var_names[i_var]));
+
+      if (g_str_has_prefix (var_names[i_var], "LD_LIBRARY_PATH"))
+	env_value = plugin_filter_ld_library_path (env_value);
+      if (env_value != NULL)
+	{
+	  new_env[i_env++] = g_strdup_printf ("%s=%s", var_names[i_var], env_value);
+	  g_free (env_value);
+	}
+    }
+  new_env[i_env] = NULL;
+  return new_env;
+}
+
+static NPError
+plugin_test_appletviewer ()
+{
+  PLUGIN_DEBUG ("plugin_test_appletviewer: %s\n", appletviewer_executable);
+  NPError error = NPERR_NO_ERROR;
+
+  gchar* command_line[3] = { NULL, NULL, NULL };
+  gchar** environment;
+
+  command_line[0] = g_strdup (appletviewer_executable);
+  command_line[1] = g_strdup("-version");
+  command_line[2] = NULL;
+
+  environment = plugin_filter_environment();
+
+  if (!g_spawn_async (NULL, command_line, environment,
+		      (GSpawnFlags) 0,
+                      NULL, NULL, NULL, &channel_error))
+    {
+      if (channel_error)
+        {
+          PLUGIN_ERROR_TWO ("Failed to spawn applet viewer",
+                            channel_error->message);
+          g_error_free (channel_error);
+          channel_error = NULL;
+        }
+      else
+        PLUGIN_ERROR ("Failed to spawn applet viewer");
+      error = NPERR_GENERIC_ERROR;
+    }
+
+  g_strfreev (environment);
+
+  g_free (command_line[0]);
+  command_line[0] = NULL;
+  g_free (command_line[1]);
+  command_line[1] = NULL;
+  g_free (command_line[2]);
+  command_line[2] = NULL;
+
+  PLUGIN_DEBUG ("plugin_test_appletviewer return\n");
+  return error;
+}
+
+static NPError
+plugin_start_appletviewer (ITNPPluginData* data)
+{
+  PLUGIN_DEBUG ("plugin_start_appletviewer\n");
+  NPError error = NPERR_NO_ERROR;
+
+  gchar** command_line;
+  gchar** environment;
+
+  int cmd_num = 0;
+  if (plugin_debug)
+  {
+      command_line = (gchar**) malloc(sizeof(gchar*)*11);
+      command_line[cmd_num++] = g_strdup(appletviewer_executable);
+      command_line[cmd_num++] = g_strdup_printf(PLUGIN_BOOTCLASSPATH);
+      // set the classpath to avoid using the default (cwd).
+      command_line[cmd_num++] = g_strdup("-classpath");
+      command_line[cmd_num++] = g_strdup_printf("%s/lib/rt.jar", ICEDTEA_WEB_JRE);
+      command_line[cmd_num++] = g_strdup("-Xdebug");
+      command_line[cmd_num++] = g_strdup("-Xnoagent");
+      if (plugin_debug_suspend)
+      {
+          command_line[cmd_num++] = g_strdup("-Xrunjdwp:transport="DT_SOCKET_DLL",address=8787,server=y,suspend=y");
+      } else
+      {
+          command_line[cmd_num++] = g_strdup("-Xrunjdwp:transport="DT_SOCKET_DLL",address=8787,server=y,suspend=n");
+      }
+      command_line[cmd_num++] = g_strdup("sun.applet.PluginMain");
+#ifdef __OS2__
+      command_line[cmd_num++] = g_strdup_printf("%d", out_pipe [1]);
+      command_line[cmd_num++] = g_strdup_printf("%d", in_pipe [1]);
+#else
+      command_line[cmd_num++] = g_strdup(out_pipe_name);
+      command_line[cmd_num++] = g_strdup(in_pipe_name);
+#endif
+      command_line[cmd_num] = NULL;
+  } else
+  {
+      command_line = (gchar**) malloc(sizeof(gchar*)*8);
+      command_line[cmd_num++] = g_strdup(appletviewer_executable);
+      command_line[cmd_num++] = g_strdup_printf(PLUGIN_BOOTCLASSPATH);
+      command_line[cmd_num++] = g_strdup("-classpath");
+      command_line[cmd_num++] = g_strdup_printf("%s/lib/rt.jar", ICEDTEA_WEB_JRE);
+      command_line[cmd_num++] = g_strdup("sun.applet.PluginMain");
+#ifdef __OS2__
+      command_line[cmd_num++] = g_strdup_printf("%d", out_pipe [1]);
+      command_line[cmd_num++] = g_strdup_printf("%d", in_pipe [1]);
+#else
+      command_line[cmd_num++] = g_strdup(out_pipe_name);
+      command_line[cmd_num++] = g_strdup(in_pipe_name);
+#endif
+      command_line[cmd_num] = NULL;
+  }
+
+  environment = plugin_filter_environment();
+
+#ifdef __OS2__
+  int flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD;
+#else
+  int flags = G_SPAWN_DO_NOT_REAP_CHILD;
+#endif
+
+  if (!g_spawn_async (NULL, command_line, environment,
+		      (GSpawnFlags) flags,
+                      NULL, NULL, &appletviewer_pid, &channel_error))
+    {
+      if (channel_error)
+        {
+          PLUGIN_ERROR_TWO ("Failed to spawn applet viewer",
+                            channel_error->message);
+          g_error_free (channel_error);
+          channel_error = NULL;
+        }
+      else
+        PLUGIN_ERROR ("Failed to spawn applet viewer");
+      error = NPERR_GENERIC_ERROR;
+    }
+
+  // make sure we get an error rather than crash the browser when talking to the
+  // jvm process if it dies unexpectedly (we do it here since g_spawn() is known
+  // to reset SIGPIPE handler to SIG_DFL)
+  signal (SIGPIPE, SIG_IGN);
+
+  g_strfreev (environment);
+
+  for (int i = 0; i < cmd_num; i++) {
+    g_free (command_line[i]);
+    command_line[i] = NULL;
+  }
+
+  g_free(command_line);
+  command_line = NULL;
+
+  if (appletviewer_pid)
+    {
+      PLUGIN_DEBUG("Initialized VM with pid=%d\n", appletviewer_pid);
+      appletviewer_watch_id = g_child_watch_add(appletviewer_pid, (GChildWatchFunc) appletviewer_monitor, (gpointer) appletviewer_pid);
+    }
+
+
+  PLUGIN_DEBUG ("plugin_start_appletviewer return\n");
+  return error;
+}
+
+/*
+ * Replaces certain characters (\r, \n, etc) with HTML escape equivalents.
+ *
+ * Return string is allocated on the heap. Caller assumes responsibility 
+ * for freeing the memory via free()
+ */
+static char*
+encode_string(char* to_encode)
+{
+
+  // Do nothing for an empty string
+  if (to_encode == '\0')
+      return to_encode;
+
+  // worst case scenario -> all characters are newlines or
+  // returns, each of which translates to 5 substitutions
+  char* encoded = (char*) calloc(((strlen(to_encode)*5)+1), sizeof(char));
+
+  strcpy(encoded, "");
+
+  for (int i=0; i < strlen(to_encode); i++)
+  {
+      if (to_encode[i] == '\r')
+          encoded = strcat(encoded, "&#13;");
+      else if (to_encode[i] == '\n')
+          encoded = strcat(encoded, "&#10;");
+      else if (to_encode[i] == '>')
+          encoded = strcat(encoded, "&gt;");
+      else if (to_encode[i] == '<')
+          encoded = strcat(encoded, "&lt;");
+      else if (to_encode[i] == '&')
+          encoded = strcat(encoded, "&amp;");
+      else if (to_encode[i] == '"')
+          encoded = strcat(encoded, "&quot;");
+      else
+      {
+           char* orig_char = (char*) calloc(2, sizeof(char));
+           orig_char[0] = to_encode[i];
+           orig_char[1] = '\0';
+ 
+           strcat(encoded, orig_char);
+ 
+           free(orig_char);
+           orig_char = NULL;
+      }
+  }
+
+  return encoded;
+}
+
+// Build up the applet tag string that we'll send to the applet
+// viewer.
+static gchar*
+plugin_create_applet_tag (int16_t argc, char* argn[], char* argv[])
+{
+  PLUGIN_DEBUG ("plugin_create_applet_tag\n");
+
+  gchar* applet_tag = g_strdup ("<EMBED ");
+  gchar* parameters = g_strdup ("");
+
+  for (int16_t i = 0; i < argc; i++)
+    {
+      gchar* argn_escaped = encode_string(argn[i]);
+      gchar* argv_escaped = encode_string(argv[i]);
+
+      if (!g_ascii_strcasecmp (argn_escaped, "code"))
+        {
+          gchar* code = g_strdup_printf ("CODE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, code, NULL);
+          g_free (code);
+          code = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "java_code"))
+    {
+          gchar* java_code = g_strdup_printf ("JAVA_CODE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, java_code, NULL);
+          g_free (java_code);
+          java_code = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "codebase"))
+    {
+          gchar* codebase = g_strdup_printf ("CODEBASE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, codebase, NULL);
+          g_free (codebase);
+          codebase = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "java_codebase"))
+    {
+          gchar* java_codebase = g_strdup_printf ("JAVA_CODEBASE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, java_codebase, NULL);
+          g_free (java_codebase);
+          java_codebase = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "classid"))
+    {
+          gchar* classid = g_strdup_printf ("CLASSID=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, classid, NULL);
+          g_free (classid);
+          classid = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "archive"))
+    {
+          gchar* archive = g_strdup_printf ("ARCHIVE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, archive, NULL);
+          g_free (archive);
+          archive = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "java_archive"))
+    {
+          gchar* java_archive = g_strdup_printf ("JAVA_ARCHIVE=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, java_archive, NULL);
+          g_free (java_archive);
+          java_archive = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "width"))
+    {
+          gchar* width = g_strdup_printf ("width=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, width, NULL);
+          g_free (width);
+          width = NULL;
+    }
+      else if (!g_ascii_strcasecmp (argn_escaped, "height"))
+    {
+          gchar* height = g_strdup_printf ("height=\"%s\" ", argv_escaped);
+          applet_tag = g_strconcat (applet_tag, height, NULL);
+          g_free (height);
+          height = NULL;
+    }
+      else
+        {
+
+          if (argv_escaped != '\0')
+            {
+              parameters = g_strconcat (parameters, "<PARAM NAME=\"", argn_escaped,
+                                        "\" VALUE=\"", argv_escaped, "\">", NULL);
+            }
+        }
+
+      free(argn_escaped);
+      free(argv_escaped);
+
+      argn_escaped = NULL;
+      argv_escaped = NULL;
+    }
+
+  applet_tag = g_strconcat (applet_tag, ">", parameters, "</EMBED>", NULL);
+
+  g_free (parameters);
+  parameters = NULL;
+
+  PLUGIN_DEBUG ("plugin_create_applet_tag return\n");
+
+  return applet_tag;
+}
+
+// plugin_send_message_to_appletviewer must be called while holding
+// data->appletviewer_mutex.
+void
+plugin_send_message_to_appletviewer (gchar const* message)
+{
+  PLUGIN_DEBUG ("plugin_send_message_to_appletviewer\n");
+
+  if (jvm_up)
+    {
+      gchar* newline_message = NULL;
+      gsize bytes_written = 0;
+
+      // Send message to appletviewer.
+      newline_message = g_strdup_printf ("%s\n", message);
+
+      // g_io_channel_write_chars will return something other than
+      // G_IO_STATUS_NORMAL if not all the data is written.  In that
+      // case we fail rather than retrying.
+      if (g_io_channel_write_chars (out_to_appletviewer,
+                                    newline_message, -1, &bytes_written,
+                                    &channel_error)
+            != G_IO_STATUS_NORMAL)
+        {
+          if (channel_error)
+            {
+              PLUGIN_ERROR_TWO ("Failed to write bytes to output channel",
+                                channel_error->message);
+              g_error_free (channel_error);
+              channel_error = NULL;
+            }
+          else
+            PLUGIN_ERROR ("Failed to write bytes to output channel");
+        }
+
+      if (g_io_channel_flush (out_to_appletviewer, &channel_error)
+          != G_IO_STATUS_NORMAL)
+        {
+          if (channel_error)
+            {
+              PLUGIN_ERROR_TWO ("Failed to flush bytes to output channel",
+                                channel_error->message);
+              g_error_free (channel_error);
+              channel_error = NULL;
+            }
+          else
+            PLUGIN_ERROR ("Failed to flush bytes to output channel");
+        }
+      g_free (newline_message);
+      newline_message = NULL;
+
+      PLUGIN_DEBUG ("  PIPE: plugin wrote: %s\n", message);
+    }
+
+  PLUGIN_DEBUG ("plugin_send_message_to_appletviewer return\n");
+}
+
+/*
+ * Sends the initialization message (handle/size/url) to the plugin
+ */
+void
+plugin_send_initialization_message(char* instance, gulong handle,
+                                   int width, int height, char* url)
+{
+  PLUGIN_DEBUG ("plugin_send_initialization_message\n");
+
+  gchar *window_message = g_strdup_printf ("instance %s handle %ld width %d height %d %s",
+                                            instance, handle, width, height, url);
+  plugin_send_message_to_appletviewer (window_message);
+  g_free (window_message);
+  window_message = NULL;
+
+  PLUGIN_DEBUG ("plugin_send_initialization_message return\n");
+}
+
+
+// Stop the appletviewer process.  When this is called the
+// appletviewer can be in any of three states: running, crashed or
+// hung.  If the appletviewer is running then sending it "shutdown"
+// will cause it to exit.  This will cause
+// plugin_out_pipe_callback/plugin_in_pipe_callback to be called and
+// the input and output channels to be shut down.  If the appletviewer
+// has crashed then plugin_out_pipe_callback/plugin_in_pipe_callback
+// would already have been called and data->appletviewer_alive cleared
+// in which case this function simply returns.  If the appletviewer is
+// hung then this function will be successful and the input and output
+// watches will be removed by plugin_data_destroy.
+// plugin_stop_appletviewer must be called with
+// data->appletviewer_mutex held.
+static void
+plugin_stop_appletviewer ()
+{
+  PLUGIN_DEBUG ("plugin_stop_appletviewer\n");
+
+  if (jvm_up)
+    {
+      // Shut down the appletviewer.
+      gsize bytes_written = 0;
+
+      if (out_to_appletviewer)
+        {
+          if (g_io_channel_write_chars (out_to_appletviewer, "shutdown",
+                                        -1, &bytes_written, &channel_error)
+              != G_IO_STATUS_NORMAL)
+            {
+              if (channel_error)
+                {
+                  PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
+                                    " appletviewer", channel_error->message);
+                  g_error_free (channel_error);
+                  channel_error = NULL;
+                }
+              else
+                PLUGIN_ERROR ("Failed to write shutdown message to");
+            }
+
+          if (g_io_channel_flush (out_to_appletviewer, &channel_error)
+              != G_IO_STATUS_NORMAL)
+            {
+              if (channel_error)
+                {
+                  PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
+                                    " appletviewer", channel_error->message);
+                  g_error_free (channel_error);
+                  channel_error = NULL;
+                }
+              else
+                PLUGIN_ERROR ("Failed to write shutdown message to");
+            }
+
+          if (g_io_channel_shutdown (out_to_appletviewer,
+                                     TRUE, &channel_error)
+              != G_IO_STATUS_NORMAL)
+            {
+              if (channel_error)
+                {
+                  PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
+                                    " output channel", channel_error->message);
+                  g_error_free (channel_error);
+                  channel_error = NULL;
+                }
+              else
+                PLUGIN_ERROR ("Failed to shut down appletviewer");
+            }
+        }
+
+      if (in_from_appletviewer)
+        {
+          if (g_io_channel_shutdown (in_from_appletviewer,
+                                     TRUE, &channel_error)
+              != G_IO_STATUS_NORMAL)
+            {
+              if (channel_error)
+                {
+                  PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
+                                    " input channel", channel_error->message);
+                  g_error_free (channel_error);
+                  channel_error = NULL;
+                }
+              else
+                PLUGIN_ERROR ("Failed to shut down appletviewer");
+            }
+        }
+    }
+
+  jvm_up = FALSE;
+  sleep(2); /* Needed to prevent crashes during debug (when JDWP port is not freed by the kernel right away) */
+
+  PLUGIN_DEBUG ("plugin_stop_appletviewer return\n");
+}
+
+static void appletviewer_monitor(GPid pid, gint status, gpointer data)
+{
+    PLUGIN_DEBUG ("appletviewer_monitor\n");
+    jvm_up = FALSE;
+    pid = -1;
+    PLUGIN_DEBUG ("appletviewer_monitor return\n");
+}
+
+static void
+plugin_data_destroy (NPP instance)
+{
+  PLUGIN_DEBUG ("plugin_data_destroy\n");
+
+  ITNPPluginData* tofree = (ITNPPluginData*) instance->pdata;
+
+  // Remove instance from map
+  gpointer id_ptr = g_hash_table_lookup(instance_to_id_map, instance);
+
+  if (id_ptr)
+    {
+      gint id = GPOINTER_TO_INT(id_ptr);
+      g_hash_table_remove(instance_to_id_map, instance);
+      g_hash_table_remove(id_to_instance_map, id_ptr);
+    }
+
+  tofree->window_handle = NULL;
+  tofree->window_height = 0;
+  tofree->window_width = 0;
+
+  // cleanup_appletviewer_mutex:
+  g_free (tofree->appletviewer_mutex);
+  tofree->appletviewer_mutex = NULL;
+
+  // cleanup_instance_string:
+  g_free (tofree->instance_id);
+  tofree->instance_id = NULL;
+
+  // cleanup applet tag
+  g_free (tofree->applet_tag);
+  tofree->applet_tag = NULL;
+
+  g_free(tofree->source);
+  tofree->source = NULL;
+
+  // cleanup_data:
+  // Eliminate back-pointer to plugin instance.
+  tofree->owner = NULL;
+  (*browser_functions.memfree) (tofree);
+  tofree = NULL;
+
+  PLUGIN_DEBUG ("plugin_data_destroy return\n");
+}
+
+static NPError
+plugin_get_entry_points (NPPluginFuncs* pluginTable)
+{
+  // Ensure that the plugin function table we've received is large
+  // enough to store the number of functions that we may provide.
+  if (pluginTable->size < sizeof (NPPluginFuncs))
+    {
+      PLUGIN_ERROR ("Invalid plugin function table.");
+
+      return NPERR_INVALID_FUNCTABLE_ERROR;
+    }
+
+  // Return to the browser the plugin functions that we implement.
+  pluginTable->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
+  pluginTable->size = sizeof (NPPluginFuncs);
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+  pluginTable->newp = NewNPP_NewProc (ITNP_New);
+  pluginTable->destroy = NewNPP_DestroyProc (ITNP_Destroy);
+  pluginTable->setwindow = NewNPP_SetWindowProc (ITNP_SetWindow);
+  pluginTable->newstream = NewNPP_NewStreamProc (ITNP_NewStream);
+  pluginTable->destroystream = NewNPP_DestroyStreamProc (ITNP_DestroyStream);
+  pluginTable->asfile = NewNPP_StreamAsFileProc (ITNP_StreamAsFile);
+  pluginTable->writeready = NewNPP_WriteReadyProc (ITNP_WriteReady);
+  pluginTable->write = NewNPP_WriteProc (ITNP_Write);
+  pluginTable->print = NewNPP_PrintProc (ITNP_Print);
+  pluginTable->urlnotify = NewNPP_URLNotifyProc (ITNP_URLNotify);
+  pluginTable->getvalue = NewNPP_GetValueProc (ITNP_GetValue);
+#else
+  pluginTable->newp = NPP_NewProcPtr (ITNP_New);
+  pluginTable->destroy = NPP_DestroyProcPtr (ITNP_Destroy);
+  pluginTable->setwindow = NPP_SetWindowProcPtr (ITNP_SetWindow);
+  pluginTable->newstream = NPP_NewStreamProcPtr (ITNP_NewStream);
+  pluginTable->destroystream = NPP_DestroyStreamProcPtr (ITNP_DestroyStream);
+  pluginTable->asfile = NPP_StreamAsFileProcPtr (ITNP_StreamAsFile);
+  pluginTable->writeready = NPP_WriteReadyProcPtr (ITNP_WriteReady);
+  pluginTable->write = NPP_WriteProcPtr (ITNP_Write);
+  pluginTable->print = NPP_PrintProcPtr (ITNP_Print);
+  pluginTable->urlnotify = NPP_URLNotifyProcPtr (ITNP_URLNotify);
+  pluginTable->getvalue = NPP_GetValueProcPtr (ITNP_GetValue);
+#endif
+
+  return NPERR_NO_ERROR;
+}
+
+// FACTORY FUNCTIONS
+
+// Provides the browser with pointers to the plugin functions that we
+// implement and initializes a local table with browser functions that
+// we may wish to call.  Called once, after browser startup and before
+// the first plugin instance is created.
+// The field 'initialized' is set to true once this function has
+// finished. If 'initialized' is already true at the beginning of
+// this function, then it is evident that NP_Initialize has already
+// been called. There is no need to call this function more than once and
+// this workaround avoids any duplicate calls.
+NPError
+#if defined(_WIN32) || defined (__OS2__)
+OSCALL NP_Initialize (NPNetscapeFuncs* browserTable)
+#else
+OSCALL NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable)
+#endif
+{
+  PLUGIN_DEBUG ("NP_Initialize\n");
+
+#if defined(_WIN32) || defined (__OS2__)
+  if (browserTable == NULL)
+  {
+    PLUGIN_ERROR ("Browser function table is NULL.");
+
+    return NPERR_INVALID_FUNCTABLE_ERROR;
+  }
+#else
+  if ((browserTable == NULL) || (pluginTable == NULL))
+  {
+    PLUGIN_ERROR ("Browser or plugin function table is NULL.");
+
+    return NPERR_INVALID_FUNCTABLE_ERROR;
+  }
+#endif
+
+  // Ensure that the major version of the plugin API that the browser
+  // expects is not more recent than the major version of the API that
+  // we've implemented.
+  if ((browserTable->version >> 8) > NP_VERSION_MAJOR)
+    {
+      PLUGIN_ERROR ("Incompatible version.");
+
+      return NPERR_INCOMPATIBLE_VERSION_ERROR;
+    }
+
+  // Ensure that the browser function table is large enough to store
+  // the number of browser functions that we may use.
+  if (browserTable->size < sizeof (NPNetscapeFuncs))
+    {
+      fprintf (stderr, "ERROR: Invalid browser function table. Some functionality may be restricted.\n");
+    }
+
+  // Store in a local table the browser functions that we may use.
+  browser_functions.size                    = browserTable->size;
+  browser_functions.version                 = browserTable->version;
+  browser_functions.geturlnotify            = browserTable->geturlnotify;
+  browser_functions.geturl                  = browserTable->geturl;
+  browser_functions.posturlnotify           = browserTable->posturlnotify;
+  browser_functions.posturl                 = browserTable->posturl;
+  browser_functions.requestread             = browserTable->requestread;
+  browser_functions.newstream               = browserTable->newstream;
+  browser_functions.write                   = browserTable->write;
+  browser_functions.destroystream           = browserTable->destroystream;
+  browser_functions.status                  = browserTable->status;
+  browser_functions.uagent                  = browserTable->uagent;
+  browser_functions.memalloc                = browserTable->memalloc;
+  browser_functions.memfree                 = browserTable->memfree;
+  browser_functions.memflush                = browserTable->memflush;
+  browser_functions.reloadplugins           = browserTable->reloadplugins;
+  browser_functions.getJavaEnv              = browserTable->getJavaEnv;
+  browser_functions.getJavaPeer             = browserTable->getJavaPeer;
+  browser_functions.getvalue                = browserTable->getvalue;
+  browser_functions.setvalue                = browserTable->setvalue;
+  browser_functions.invalidaterect          = browserTable->invalidaterect;
+  browser_functions.invalidateregion        = browserTable->invalidateregion;
+  browser_functions.forceredraw             = browserTable->forceredraw;
+  browser_functions.getstringidentifier     = browserTable->getstringidentifier;
+  browser_functions.getstringidentifiers    = browserTable->getstringidentifiers;
+  browser_functions.getintidentifier        = browserTable->getintidentifier;
+  browser_functions.identifierisstring      = browserTable->identifierisstring;
+  browser_functions.utf8fromidentifier      = browserTable->utf8fromidentifier;
+  browser_functions.intfromidentifier       = browserTable->intfromidentifier;
+  browser_functions.createobject            = browserTable->createobject;
+  browser_functions.retainobject            = browserTable->retainobject;
+  browser_functions.releaseobject           = browserTable->releaseobject;
+  browser_functions.invoke                  = browserTable->invoke;
+  browser_functions.invokeDefault           = browserTable->invokeDefault;
+  browser_functions.evaluate                = browserTable->evaluate;
+  browser_functions.getproperty             = browserTable->getproperty;
+  browser_functions.setproperty             = browserTable->setproperty;
+  browser_functions.removeproperty          = browserTable->removeproperty;
+  browser_functions.hasproperty             = browserTable->hasproperty;
+  browser_functions.hasmethod               = browserTable->hasmethod;
+  browser_functions.releasevariantvalue     = browserTable->releasevariantvalue;
+  browser_functions.setexception            = browserTable->setexception;
+  browser_functions.pluginthreadasynccall   = browserTable->pluginthreadasynccall;
+#if MOZILLA_VERSION_COLLAPSED >= 1090100
+  browser_functions.getvalueforurl          = browserTable->getvalueforurl;
+  browser_functions.setvalueforurl          = browserTable->setvalueforurl;
+#endif
+
+  NPError np_error = NPERR_NO_ERROR;
+#if !defined(_WIN32) && !defined (__OS2__)
+  np_error = plugin_get_entry_points (pluginTable);
+  if (np_error != NPERR_NO_ERROR)
+    return np_error;
+#endif
+
+  // Re-setting the above tables multiple times is OK (as the 
+  // browser may change its function locations). However 
+  // anything beyond this point should only run once.
+  if (initialized)
+    return NPERR_NO_ERROR;
+
+#ifdef __OS2__
+  // perform OS-specific initialization
+  if (!init_os())
+    {
+      PLUGIN_ERROR ("Failed to perform OS-specific initialization.");
+      return NPERR_GENERIC_ERROR;
+    }
+#endif
+
+#ifndef __OS2__
+  // Make sure the plugin data directory exists, creating it if
+  // necessary.
+  data_directory = g_strconcat (P_tmpdir, NULL);
+  if (!data_directory)
+    {
+      PLUGIN_ERROR ("Failed to create data directory name.");
+      return NPERR_OUT_OF_MEMORY_ERROR;
+    }
+
+  // If P_tmpdir does not exist, try /tmp directly
+
+  if (!g_file_test (data_directory,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+    {
+      data_directory = g_strconcat ("/tmp", NULL);
+        if (!data_directory)
+          {
+            PLUGIN_ERROR ("Failed to create data directory name.");
+            return NPERR_OUT_OF_MEMORY_ERROR;
+          }
+
+    }
+
+  data_directory = g_strconcat (data_directory, "/icedteaplugin-", getenv("USER"), NULL);
+
+  if (!data_directory)
+  {
+      PLUGIN_ERROR ("Failed to create data directory name.");
+      return NPERR_OUT_OF_MEMORY_ERROR;
+  }
+
+  // Now create a icedteaplugin subdir
+  if (!g_file_test (data_directory,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+    {
+      int file_error = 0;
+
+      file_error = g_mkdir (data_directory, 0700);
+      if (file_error != 0)
+        {
+          PLUGIN_ERROR_THREE ("Failed to create data directory",
+                          data_directory,
+                          strerror (errno));
+          np_error = NPERR_GENERIC_ERROR;
+          goto cleanup_data_directory;
+        }
+    }
+
+
+  // If data directory doesn't exit by this point, bail
+  if (!g_file_test (data_directory,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+    {
+      PLUGIN_ERROR_THREE ("Temp directory does not exist: ",
+                          data_directory,
+                          strerror (errno));
+
+      np_error = NPERR_GENERIC_ERROR;
+            goto cleanup_data_directory;
+
+    }
+#endif
+
+  // Set appletviewer_executable.
+  gchar* filename = g_strdup(ICEDTEA_WEB_JRE);
+  appletviewer_executable = g_strdup_printf ("%s/bin/java",
+                                             filename);
+  PLUGIN_DEBUG("Executing java at %s\n", appletviewer_executable);
+  if (!appletviewer_executable)
+    {
+      PLUGIN_ERROR ("Failed to create appletviewer executable name.");
+      np_error = NPERR_OUT_OF_MEMORY_ERROR;
+      goto cleanup_filename;
+    }
+
+  np_error = plugin_test_appletviewer ();
+  if (np_error != NPERR_NO_ERROR)
+    {
+      plugin_display_failure_dialog ();
+      goto cleanup_appletviewer_executable;
+    }
+  g_free (filename);
+
+  // Initialize threads (needed for mutexes).
+  if (!g_thread_supported ())
+    g_thread_init (NULL);
+
+#ifdef __OS2__
+  if (!g_main_context_os2_start_pm_integration (NULL))
+  {
+    PLUGIN_DEBUG ("Failed to integrate with PM");
+    np_error = NPERR_GENERIC_ERROR;
+    goto cleanup_appletviewer_executable;
+  }
+#endif
+
+  plugin_instance_mutex = g_mutex_new ();
+
+  PLUGIN_DEBUG ("NP_Initialize: using %s\n", appletviewer_executable);
+
+  plugin_req_proc = new PluginRequestProcessor();
+  java_req_proc = new JavaMessageSender();
+
+  java_to_plugin_bus = new MessageBus();
+  plugin_to_java_bus = new MessageBus();
+
+  java_to_plugin_bus->subscribe(plugin_req_proc);
+  plugin_to_java_bus->subscribe(java_req_proc);
+
+#ifdef __OS2__
+  queue_processor_data1.processor = plugin_req_proc;
+  queue_processor_data2.processor = plugin_req_proc;
+  queue_processor_data3.processor = plugin_req_proc;
+  pthread_create (&plugin_request_processor_thread1, NULL, &queue_processor, (void*) &queue_processor_data1);
+  pthread_create (&plugin_request_processor_thread2, NULL, &queue_processor, (void*) &queue_processor_data2);
+  pthread_create (&plugin_request_processor_thread3, NULL, &queue_processor, (void*) &queue_processor_data3);
+#else
+  pthread_create (&plugin_request_processor_thread1, NULL, &queue_processor, (void*) plugin_req_proc);
+  pthread_create (&plugin_request_processor_thread2, NULL, &queue_processor, (void*) plugin_req_proc);
+  pthread_create (&plugin_request_processor_thread3, NULL, &queue_processor, (void*) plugin_req_proc);
+#endif
+
+  itnp_plugin_thread_id = pthread_self();
+
+  pthread_mutexattr_t attribute;
+  pthread_mutexattr_init(&attribute);
+  pthread_mutexattr_settype(&attribute, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&pluginAsyncCallMutex, &attribute);
+  pthread_mutexattr_destroy(&attribute);
+
+  initialized = true;
+
+  PLUGIN_DEBUG ("NP_Initialize return\n");
+
+  return NPERR_NO_ERROR;
+
+ cleanup_appletviewer_executable:
+  if (appletviewer_executable)
+    {
+      g_free (appletviewer_executable);
+      appletviewer_executable = NULL;
+    }
+
+ cleanup_filename:
+  if (filename)
+    {
+      g_free (filename);
+      filename = NULL;
+    }
+
+ cleanup_data_directory:
+  if (data_directory)
+    {
+      g_free (data_directory);
+      data_directory = NULL;
+    }
+
+
+  return np_error;
+}
+
+#if defined(_WIN32) || defined (__OS2__)
+NPError
+OSCALL NP_GetEntryPoints (NPPluginFuncs* pluginTable)
+{
+  PLUGIN_DEBUG ("NP_GetEntryPoints\n");
+
+  if (pluginTable == NULL)
+  {
+    PLUGIN_ERROR ("Plugin function table is NULL.");
+
+    return NPERR_INVALID_FUNCTABLE_ERROR;
+  }
+
+  return plugin_get_entry_points (pluginTable);
+}
+#endif
+
+// Returns a string describing the MIME type that this plugin
+// handles.
+const char*
+OSCALL NP_GetMIMEDescription ()
+{
+  PLUGIN_DEBUG ("NP_GetMIMEDescription\n");
+
+  PLUGIN_DEBUG ("NP_GetMIMEDescription return\n");
+
+  return PLUGIN_MIME_DESC;
+}
+
+// Returns a value relevant to the plugin as a whole.  The browser
+// calls this function to obtain information about the plugin.
+NPError
+OSCALL NP_GetValue (void* future, NPPVariable variable, void* value)
+{
+  PLUGIN_DEBUG ("NP_GetValue\n");
+
+  NPError result = NPERR_NO_ERROR;
+  gchar** char_value = (gchar**) value;
+
+  switch (variable)
+    {
+    case NPPVpluginNameString:
+      PLUGIN_DEBUG ("NP_GetValue: returning plugin name.\n");
+      *char_value = g_strdup (PLUGIN_FULL_NAME);
+      break;
+
+    case NPPVpluginDescriptionString:
+      PLUGIN_DEBUG ("NP_GetValue: returning plugin description.\n");
+      *char_value = g_strdup (PLUGIN_DESC);
+      break;
+
+    default:
+      PLUGIN_ERROR ("Unknown plugin value requested.");
+      result = NPERR_GENERIC_ERROR;
+      break;
+    }
+
+  PLUGIN_DEBUG ("NP_GetValue return\n");
+
+  return result;
+}
+
+// Shuts down the plugin.  Called after the last plugin instance is
+// destroyed.
+NPError
+OSCALL NP_Shutdown (void)
+{
+  PLUGIN_DEBUG ("NP_Shutdown\n");
+
+#ifdef __OS2__
+  g_main_context_os2_stop_pm_integration (NULL);
+#endif
+
+  // Free mutex.
+  if (plugin_instance_mutex)
+    {
+      g_mutex_free (plugin_instance_mutex);
+      plugin_instance_mutex = NULL;
+    }
+
+  if (data_directory)
+    {
+      g_free (data_directory);
+      data_directory = NULL;
+    }
+
+  if (appletviewer_executable)
+    {
+      g_free (appletviewer_executable);
+      appletviewer_executable = NULL;
+    }
+
+  // stop the appletviewer
+  plugin_stop_appletviewer();
+
+  // remove monitor
+  if (appletviewer_watch_id != -1)
+    g_source_remove(appletviewer_watch_id);
+
+  // Removing a source is harmless if it fails since it just means the
+  // source has already been removed.
+  g_source_remove (in_watch_source);
+  in_watch_source = 0;
+
+  // cleanup_in_from_appletviewer:
+  if (in_from_appletviewer)
+    g_io_channel_unref (in_from_appletviewer);
+  in_from_appletviewer = NULL;
+
+  // cleanup_out_watch_source:
+  g_source_remove (out_watch_source);
+  out_watch_source = 0;
+
+  // cleanup_out_to_appletviewer:
+  if (out_to_appletviewer)
+    g_io_channel_unref (out_to_appletviewer);
+  out_to_appletviewer = NULL;
+
+  // cleanup_out_pipe:
+#ifdef __OS2__
+  CLOSE_FD (out_pipe [0]);
+  CLOSE_FD (out_pipe [1]);
+#else
+  // Delete output pipe.
+  PLUGIN_DEBUG ("NP_Shutdown: deleting output fifo: %s\n", out_pipe_name);
+  unlink (out_pipe_name);
+  PLUGIN_DEBUG ("NP_Shutdown: deleted output fifo: %s\n", out_pipe_name);
+
+  // cleanup_out_pipe_name:
+  g_free (out_pipe_name);
+  out_pipe_name = NULL;
+#endif
+
+  // cleanup_in_pipe:
+#ifdef __OS2__
+  CLOSE_FD (in_pipe [0]);
+  CLOSE_FD (in_pipe [1]);
+#else
+  // Delete input pipe.
+  PLUGIN_DEBUG ("NP_Shutdown: deleting input fifo: %s\n", in_pipe_name);
+  unlink (in_pipe_name);
+  PLUGIN_DEBUG ("NP_Shutdown: deleted input fifo: %s\n", in_pipe_name);
+
+  // cleanup_in_pipe_name:
+  g_free (in_pipe_name);
+  in_pipe_name = NULL;
+#endif
+
+  // Destroy the call queue mutex
+  pthread_mutex_destroy(&pluginAsyncCallMutex);
+
+#ifdef __OS2__
+  // perform OS-specific uninitialization
+  done_os();
+#endif
+
+  initialized = false;
+
+#ifdef __OS2__
+  // pthread_cancel() isn't implemented on OS?2, so use an old good flag
+  queue_processor_data1.stopRequested = true;
+  queue_processor_data2.stopRequested = true;
+  queue_processor_data3.stopRequested = true;
+  pthread_cond_broadcast(&cond_message_available);
+#else
+  pthread_cancel(plugin_request_processor_thread1);
+  pthread_cancel(plugin_request_processor_thread2);
+  pthread_cancel(plugin_request_processor_thread3);
+#endif
+
+  pthread_join(plugin_request_processor_thread1, NULL);
+  pthread_join(plugin_request_processor_thread2, NULL);
+  pthread_join(plugin_request_processor_thread3, NULL);
+
+  java_to_plugin_bus->unSubscribe(plugin_req_proc);
+  plugin_to_java_bus->unSubscribe(java_req_proc);
+  //internal_bus->unSubscribe(java_req_proc);
+  //internal_bus->unSubscribe(plugin_req_proc);
+
+  delete plugin_req_proc;
+  delete java_req_proc;
+  delete java_to_plugin_bus;
+  delete plugin_to_java_bus;
+  //delete internal_bus;
+
+  PLUGIN_DEBUG ("NP_Shutdown return\n");
+
+  return NPERR_NO_ERROR;
+}
+
+NPObject*
+get_scriptable_object(NPP instance)
+{
+    NPObject* obj;
+    ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
+
+    if (data->is_applet_instance) // dummy instance/package?
+    {
+        JavaRequestProcessor java_request = JavaRequestProcessor();
+        JavaResultData* java_result;
+        std::string instance_id = std::string();
+        std::string applet_class_id = std::string();
+
+        int id = get_id_from_instance(instance);
+        gchar* id_str = g_strdup_printf ("%d", id);
+
+        // Some browsers.. (e.g. chromium) don't call NPP_SetWindow
+        // for 0x0 plugins and therefore require initialization with
+        // a 0 handle
+        if (!data->window_handle)
+        {
+            plugin_send_initialization_message(data->instance_id, 0, 0, 0, data->applet_tag);
+        }
+
+        java_result = java_request.getAppletObjectInstance(id_str);
+
+        g_free(id_str);
+
+        if (java_result->error_occurred)
+        {
+            printf("Error: Unable to fetch applet instance id from Java side.\n");
+            return NULL;
+        }
+
+        instance_id.append(*(java_result->return_string));
+
+        java_result = java_request.getClassID(instance_id);
+
+        if (java_result->error_occurred)
+        {
+            printf("Error: Unable to fetch applet instance id from Java side.\n");
+            return NULL;
+        }
+
+        applet_class_id.append(*(java_result->return_string));
+
+        obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, applet_class_id, instance_id, false);
+
+    } else
+    {
+        obj = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(instance, "");
+    }
+
+	return obj;
+}
+
+NPObject*
+allocate_scriptable_object(NPP npp, NPClass *aClass)
+{
+	PLUGIN_DEBUG("Allocating new scriptable object\n");
+	return new IcedTeaScriptablePluginObject(npp);
+}
+
+#ifdef __OS2__
+
+// Make sure static initializers in the plugin DLL are called
+
+static APIENTRY void cleanup(ULONG ulReason)
+{
+    __ctordtorTerm();
+    _CRT_term();
+    DosExitList(EXLST_EXIT, cleanup);
+}
+
+unsigned long _System _DLL_InitTerm(unsigned long hModule,
+                                    unsigned long ulFlag)
+{
+    APIRET arc;
+
+    if (ulFlag == 0)
+    {
+        arc = DosExitList (EXLST_ADD, cleanup);
+        if (arc != NO_ERROR)
+            return 0;
+
+        if (_CRT_init() != 0) // failure?
+            return 0;
+        __ctordtorInit();
+    }
+
+    return 1;
+}
+
+#endif /* __OS2__ */
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaNPPlugin.h	(revision 403)
@@ -0,0 +1,153 @@
+/* IcedTeaNPPlugin.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __ICEDTEANPPLUGIN_H__
+#define	__ICEDTEANPPLUGIN_H__
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+#include <nsThreadUtils.h>
+#else
+#include <npapi.h>
+#include <npruntime.h>
+#include <npfunctions.h>
+#endif
+
+// GLib includes.
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#ifndef __OS2__
+// GTK includes.
+#include <gtk/gtk.h>
+#endif
+
+#include "IcedTeaPluginUtils.h"
+#include "IcedTeaPluginRequestProcessor.h"
+
+// ITNPPluginData stores all the data associated with a single plugin
+// instance.  A separate plugin instance is created for each <APPLET>
+// tag.  For now, each plugin instance spawns its own applet viewer
+// process but this may need to change if we find pages containing
+// multiple applets that expect to be running in the same VM.
+struct ITNPPluginData
+{
+  // A unique identifier for this plugin window.
+  gchar* instance_id;
+  // The applet tag sent to Java side
+  gchar* applet_tag;
+  // Mutex to protect appletviewer_alive.
+  GMutex* appletviewer_mutex;
+  // Back-pointer to the plugin instance to which this data belongs.
+  // This should not be freed but instead simply set to NULL.
+  NPP owner;
+  // The address of the plugin window.  This should not be freed but
+  // instead simply set to NULL.
+  gpointer window_handle;
+  // The last plugin window width sent to us by the browser.
+  guint32 window_width;
+  // The last plugin window height sent to us by the browser.
+  guint32 window_height;
+  // The source location for this instance
+  gchar* source;
+  // If this is an actual applet instance, or a dummy instance for static calls
+  bool is_applet_instance;
+};
+
+// Queue processing threads
+static pthread_t plugin_request_processor_thread1;
+static pthread_t plugin_request_processor_thread2;
+static pthread_t plugin_request_processor_thread3;
+
+#ifdef __OS2__
+struct QueueProcessorData
+{
+    PluginRequestProcessor *processor;
+    bool stopRequested;
+};
+
+static QueueProcessorData queue_processor_data1 = { NULL, false };
+static QueueProcessorData queue_processor_data2 = { NULL, false };
+static QueueProcessorData queue_processor_data3 = { NULL, false };
+#endif
+
+// Condition on which the queue processor waits
+extern pthread_cond_t cond_message_available;
+
+// ID of plug-in thread
+extern pthread_t itnp_plugin_thread_id;
+
+/* Mutex around plugin async call queue ops */
+extern pthread_mutex_t pluginAsyncCallMutex;
+
+// debug switch
+extern int plugin_debug;
+
+// Browser function table.
+extern NPNetscapeFuncs browser_functions;
+
+// messages to the java side
+extern MessageBus* plugin_to_java_bus;
+
+// messages from the java side
+extern MessageBus* java_to_plugin_bus;
+
+// internal messages (e.g ones that need processing in main thread)
+//extern MessageBus* internal_bus;
+
+// subscribes to plugin_to_java_bus and sends messages over the link
+extern JavaMessageSender java_request_processor;
+
+// processes requests made to the plugin
+extern PluginRequestProcessor plugin_request_processor;
+
+/* Given an instance pointer, return its id */
+void get_instance_from_id(int id, NPP& instance);
+
+/* Given an instance id, return its pointer */
+int get_id_from_instance(NPP instance);
+
+/* Sends a message to the appletviewer */
+void plugin_send_message_to_appletviewer(gchar const* message);
+
+/* Returns an appropriate (package/object) scriptable npobject */
+NPObject* get_scriptable_object(NPP instance);
+
+/* Creates a new scriptable plugin object and returns it */
+NPObject* allocate_scriptable_object(NPP npp, NPClass *aClass);
+
+#endif	/* __ICEDTEANPPLUGIN_H__ */
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	(revision 403)
@@ -0,0 +1,1037 @@
+/* IcedTeaPluginRequestProcessor.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include <typeinfo>
+
+#include "IcedTeaScriptablePluginObject.h"
+#include "IcedTeaNPPlugin.h"
+#include "IcedTeaPluginRequestProcessor.h"
+
+/*
+ * This class processes requests made by Java. The requests include pointer
+ * information, script execution and variable get/set
+ */
+
+// Initialize static members used by the queue processing framework
+pthread_mutex_t message_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t syn_write_mutex = PTHREAD_MUTEX_INITIALIZER;
+std::vector< std::vector<std::string*>* >* message_queue = new std::vector< std::vector<std::string*>* >();
+
+/**
+ * PluginRequestProcessor constructor.
+ *
+ * Initializes various complex data structures used by the class.
+ */
+
+PluginRequestProcessor::PluginRequestProcessor()
+{
+    this->pendingRequests = new std::map<pthread_t, uintmax_t>();
+
+    internal_req_ref_counter = 0;
+
+    pthread_mutex_init(&message_queue_mutex, NULL);
+    pthread_mutex_init(&syn_write_mutex, NULL);
+
+    pthread_cond_init(&cond_message_available, NULL);
+}
+
+/**
+ * PluginRequestProcessor destructor.
+ *
+ * Frees memory used by complex objects.
+ */
+
+PluginRequestProcessor::~PluginRequestProcessor()
+{
+    PLUGIN_DEBUG("PluginRequestProcessor::~PluginRequestProcessor\n");
+
+    if (pendingRequests)
+        delete pendingRequests;
+
+    pthread_mutex_destroy(&message_queue_mutex);
+    pthread_mutex_destroy(&syn_write_mutex);
+
+    pthread_cond_destroy(&cond_message_available);
+}
+
+/**
+ * Processes plugin (C++ side) requests from the Java side, and internally.
+ *
+ * @param message The message request to process
+ * @return boolean indicating whether the message is serviceable by this object
+ */
+
+bool
+PluginRequestProcessor::newMessageOnBus(const char* message)
+{
+    PLUGIN_DEBUG("PluginRequestProcessor processing %s\n", message);
+
+    std::string* type;
+    std::string* command;
+    int counter = 0;
+
+    std::vector<std::string*>* message_parts = IcedTeaPluginUtilities::strSplit(message, " ");
+
+    std::vector<std::string*>::iterator the_iterator;
+    the_iterator = message_parts->begin();
+
+    IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::newMessageOnBus:", message_parts);
+
+    type = message_parts->at(0);
+    command = message_parts->at(4);
+
+    if (!type->find("instance"))
+    {
+        if (!command->find("GetWindow"))
+        {
+            // Window can be queried from the main thread only. And this call
+            // returns immediately, so we do it in the same thread.
+            this->sendWindow(message_parts);
+            return true;
+        } else if (!command->find("GetMember") ||
+                   !command->find("SetMember") ||
+                   !command->find("ToString") ||
+                   !command->find("Call") ||
+                   !command->find("GetSlot") ||
+                   !command->find("SetSlot") ||
+                   !command->find("Eval") ||
+                   !command->find("Finalize") ||
+                   !command->find("LoadURL"))
+        {
+
+            // Update queue synchronously
+            pthread_mutex_lock(&message_queue_mutex);
+            message_queue->push_back(message_parts);
+            pthread_mutex_unlock(&message_queue_mutex);
+
+            // Broadcast that a message is now available
+            pthread_cond_broadcast(&cond_message_available);
+
+            return true;
+        }
+
+    }
+
+    IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
+
+    // If we got here, it means we couldn't process the message. Let the caller know.
+    return false;
+}
+
+/**
+ * Sends the window pointer to the Java side.
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::sendWindow(std::vector<std::string*>* message_parts)
+{
+    std::string* type;
+    std::string* command;
+    int reference;
+    std::string response = std::string();
+    std::string window_ptr_str = std::string();
+    NPVariant* variant = new NPVariant();
+    static NPObject* window_ptr;
+    int id;
+
+    type = message_parts->at(0);
+    id = atoi(message_parts->at(1)->c_str());
+    reference = atoi(message_parts->at(3)->c_str());
+    command = message_parts->at(4);
+
+    NPP instance;
+    get_instance_from_id(id, instance);
+
+    browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr);
+    PLUGIN_DEBUG("ID=%d, Instance=%p, WindowPTR = %p\n", id, instance, window_ptr);
+
+    OBJECT_TO_NPVARIANT(window_ptr, *variant);
+    browser_functions.retainobject(window_ptr);
+    IcedTeaPluginUtilities::JSIDToString(variant, &window_ptr_str);
+
+    // We need the context 0 for backwards compatibility with the Java side
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response += " JavaScriptGetWindow ";
+    response += window_ptr_str;
+
+    plugin_to_java_bus->post(response.c_str());
+
+    // store the instance pointer for future reference
+    IcedTeaPluginUtilities::storeInstanceID(variant, instance);
+}
+
+/**
+ * Evaluates the given script
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::eval(std::vector<std::string*>* message_parts)
+{
+    JavaRequestProcessor request_processor = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    NPVariant* window_ptr;
+    NPP instance;
+    std::string script;
+    NPVariant result;
+    int reference;
+    std::string response = std::string();
+    std::string return_type = std::string();
+    int id;
+
+    reference = atoi(message_parts->at(3)->c_str());
+    window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(message_parts->at(5));
+    instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	return;
+
+    java_result = request_processor.getString(*(message_parts->at(6)));
+    CHECK_JAVA_RESULT(java_result);
+    script.append(*(java_result->return_string));
+
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr));
+    thread_data.parameters.push_back(&script);
+
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_eval, &thread_data);
+
+    NPVariant* result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(thread_data.result);
+    std::string result_variant_jniid = std::string();
+    createJavaObjectFromVariant(instance, *result_variant, &result_variant_jniid);
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response += " JavaScriptEval ";
+    response += result_variant_jniid;
+
+    plugin_to_java_bus->post(response.c_str());
+}
+
+/**
+ * Calls the given javascript script
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::call(std::vector<std::string*>* message_parts)
+{
+    NPP instance;
+    std::string* window_ptr_str;
+    NPVariant* window_ptr;
+    int reference;
+    std::string window_function_name;
+    std::vector<NPVariant> args = std::vector<NPVariant>();
+    std::vector<std::string> arg_ids = std::vector<std::string>();
+    int arg_count;
+    std::string response = std::string();
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+    NPVariant* result_variant;
+    std::string result_variant_jniid = std::string();
+    NPVariant* args_array;
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+
+    reference = atoi(message_parts->at(3)->c_str());
+
+    // window
+    window_ptr_str = message_parts->at(5);
+    window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(window_ptr_str);
+
+    // instance
+    instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	goto cleanup;
+
+    // function name
+    java_result = java_request.getString(*(message_parts->at(6)));
+    CHECK_JAVA_RESULT(java_result);
+    window_function_name.append(*(java_result->return_string));
+
+    // arguments
+    for (int i=7; i < message_parts->size(); i++)
+    {
+        arg_ids.push_back(*(message_parts->at(i)));
+    }
+
+    // determine arguments
+    for (int i=0; i < arg_ids.size(); i++)
+    {
+        NPVariant* variant = new NPVariant();
+        java_result = java_request.getValue(arg_ids[i]);
+        CHECK_JAVA_RESULT(java_result);
+
+        IcedTeaPluginUtilities::javaResultToNPVariant(instance, java_result->return_string, variant);
+
+        args.push_back(*variant);
+    }
+
+    arg_count = args.size();
+    args_array = (NPVariant*) malloc(sizeof(NPVariant)*args.size());
+    for (int i=0; i < args.size(); i++)
+        args_array[i] = args[i];
+
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr));
+    thread_data.parameters.push_back(&window_function_name);
+    thread_data.parameters.push_back(&arg_count);
+    thread_data.parameters.push_back(args_array);
+
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_call, &thread_data);
+
+    result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(thread_data.result);
+
+    if (result_variant)
+    {
+        createJavaObjectFromVariant(instance, *result_variant, &result_variant_jniid);
+    } else
+    {
+        result_variant_jniid = "0";
+    }
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response += " JavaScriptCall ";
+    response += result_variant_jniid;
+
+    plugin_to_java_bus->post(response.c_str());
+
+    cleanup:
+    free(args_array);
+}
+
+/**
+ * Sends the string value of the requested variable
+ *
+ * @param message_parts The request message.
+ */
+void
+PluginRequestProcessor::sendString(std::vector<std::string*>* message_parts)
+{
+    std::string variant_ptr;
+    NPVariant* variant;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+    int reference;
+    std::string response = std::string();
+
+    reference = atoi(message_parts->at(3)->c_str());
+    variant_ptr = *(message_parts->at(5));
+
+    variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr);
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(variant);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	return;
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(variant);
+
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_getString, &thread_data);
+
+    // We need the context 0 for backwards compatibility with the Java side
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response += " JavaScriptToString ";
+    response += thread_data.result;
+
+    plugin_to_java_bus->post(response.c_str());
+}
+
+/**
+ * Sets variable to given value
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::setMember(std::vector<std::string*>* message_parts)
+{
+    std::string propertyNameID;
+    std::string value = std::string();
+    std::string response = std::string();
+    int reference;
+
+    NPP instance;
+    NPVariant* member;
+    NPIdentifier property_identifier;
+
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::_setMember - ", message_parts);
+
+    reference = atoi(message_parts->at(3)->c_str());
+
+    member = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(*(message_parts->at(5))));
+    propertyNameID = *(message_parts->at(6));
+
+    if (*(message_parts->at(7)) == "literalreturn")
+    {
+        value.append(*(message_parts->at(7)));
+        value.append(" ");
+        value.append(*(message_parts->at(8)));
+    } else
+    {
+        value.append(*(message_parts->at(7)));
+    }
+
+    instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(member);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	return;
+
+    if (*(message_parts->at(4)) == "SetSlot")
+    {
+        property_identifier = browser_functions.getintidentifier(atoi(message_parts->at(6)->c_str()));
+    } else
+    {
+        java_result = java_request.getString(propertyNameID);
+
+        // the result we want is in result_string (assuming there was no error)
+        if (java_result->error_occurred)
+        {
+	    printf("Unable to get member name for setMember. Error occurred: %s\n", java_result->error_msg->c_str());
+            //goto cleanup;
+        }
+
+        property_identifier = browser_functions.getstringidentifier(java_result->return_string->c_str());
+    }
+
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*member));
+    thread_data.parameters.push_back(&property_identifier);
+    thread_data.parameters.push_back(&value);
+
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_setMember, &thread_data);
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response.append(" JavaScriptSetMember ");
+    plugin_to_java_bus->post(response.c_str());
+}
+
+/**
+ * Sends request member pointer to the Java side.
+ *
+ * This is a static function, called in another thread. Since certain data
+ * can only be requested from the main thread in Mozilla, this function
+ * does whatever it can seperately, and then makes an internal request that
+ * causes _sendMember to do the rest of the work.
+ *
+ * @param message_parts The request message
+ */
+
+void
+PluginRequestProcessor::sendMember(std::vector<std::string*>* message_parts)
+{
+    // member initialization
+    std::vector<std::string> args;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+    NPVariant* parent_ptr;
+
+    //int reference;
+    std::string member_id = std::string();
+    std::string jsObjectClassID = std::string();
+    std::string jsObjectConstructorID = std::string();
+    std::string response = std::string();
+
+    NPIdentifier member_identifier;
+
+    int method_id;
+    int instance_id;
+    int reference;
+
+    // debug printout of parent thread data
+    IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::getMember:", message_parts);
+
+    reference = atoi(message_parts->at(3)->c_str());
+
+    // store info in local variables for easy access
+    instance_id = atoi(message_parts->at(1)->c_str());
+    parent_ptr = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(message_parts->at(5)));
+    member_id.append(*(message_parts->at(6)));
+
+    /** Request data from Java if necessary **/
+    if (*(message_parts->at(4)) == "GetSlot")
+    {
+        member_identifier = browser_functions.getintidentifier(atoi(member_id.c_str()));
+    } else
+    {
+        // make a new request for getString, to get the name of the identifier
+        java_result = java_request.getString(member_id);
+
+        // the result we want is in result_string (assuming there was no error)
+        if (java_result->error_occurred)
+        {
+	    printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg->c_str());
+            //goto cleanup;
+        }
+
+        member_identifier = browser_functions.getstringidentifier(java_result->return_string->c_str());
+    }
+
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(parent_ptr);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	return;
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*parent_ptr));
+    thread_data.parameters.push_back(&member_identifier);
+
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_getMember, &thread_data);
+
+    PLUGIN_DEBUG("Member PTR after internal request: %s\n", thread_data.result.c_str());
+
+    java_result = java_request.findClass(0, "netscape.javascript.JSObject");
+
+    // the result we want is in result_string (assuming there was no error)
+    if (java_result->error_occurred)
+    {
+        printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg->c_str());
+        //goto cleanup;
+    }
+
+    jsObjectClassID.append(*(java_result->return_string));
+
+    args = std::vector<std::string>();
+    std::string longArg = "J";
+    args.push_back(longArg);
+
+    java_result = java_request.getMethodID(jsObjectClassID,
+                                           browser_functions.getstringidentifier("<init>"),
+                                           args);
+
+    // the result we want is in result_string (assuming there was no error)
+    if (java_result->error_occurred)
+    {
+        printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg->c_str());
+        //goto cleanup;
+    }
+
+    jsObjectConstructorID.append(*(java_result->return_string));
+
+    // We have the method id. Now create a new object.
+
+    args.clear();
+    args.push_back(thread_data.result);
+    java_result = java_request.newObjectWithConstructor("",
+                                         jsObjectClassID,
+                                         jsObjectConstructorID,
+                                         args);
+
+    // the result we want is in result_string (assuming there was no error)
+    if (java_result->error_occurred)
+    {
+        printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg->c_str());
+        //goto cleanup;
+    }
+
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    if (*(message_parts->at(2)) == "GetSlot")
+    {
+        response.append(" JavaScriptGetMember ");
+    } else {
+        response.append(" JavaScriptGetSlot ");
+    }
+    response.append(java_result->return_string->c_str());
+    plugin_to_java_bus->post(response.c_str());
+}
+
+/**
+ * Decrements reference count to given object
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::finalize(std::vector<std::string*>* message_parts)
+{
+    std::string* type;
+    std::string* command;
+    int reference;
+    std::string response = std::string();
+    std::string* variant_ptr_str;
+    NPVariant* variant_ptr;
+    NPObject* window_ptr;
+    int id;
+
+    type = message_parts->at(0);
+    id = atoi(message_parts->at(1)->c_str());
+    reference = atoi(message_parts->at(3)->c_str());
+    variant_ptr_str = message_parts->at(5);
+
+    NPP instance;
+    get_instance_from_id(id, instance);
+
+    variant_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr_str);
+    window_ptr = NPVARIANT_TO_OBJECT(*variant_ptr);
+    browser_functions.releaseobject(window_ptr);
+
+    // remove reference
+    IcedTeaPluginUtilities::removeInstanceID(variant_ptr);
+
+    // clear memory
+    free(variant_ptr);
+
+    // We need the context 0 for backwards compatibility with the Java side
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response);
+    response += " JavaScriptFinalize";
+
+    plugin_to_java_bus->post(response.c_str());
+}
+
+/**
+ * Fetches the URL and loads it into the given target
+ *
+ * @param message_parts The request message.
+ */
+void
+PluginRequestProcessor::loadURL(std::vector<std::string*>* message_parts)
+{
+
+    int id = atoi(message_parts->at(1)->c_str());
+
+    AsyncCallThreadData thread_data = AsyncCallThreadData();
+    thread_data.result_ready = false;
+    thread_data.parameters = std::vector<void*>();
+    thread_data.result = std::string();
+
+    NPP instance;
+    get_instance_from_id(id, instance);
+
+    // If instance is invalid, do not proceed further
+    if (!instance)
+    	return;
+
+    thread_data.parameters.push_back(instance);
+    thread_data.parameters.push_back(message_parts->at(5)); // push url
+    thread_data.parameters.push_back(message_parts->at(6)); // push target
+
+    thread_data.result_ready = false;
+    IcedTeaPluginUtilities::callAndWaitForResult(instance, &_loadURL, &thread_data);
+}
+
+static void
+queue_cleanup(void* data)
+{
+
+    pthread_mutex_destroy((pthread_mutex_t*) data);
+
+    PLUGIN_DEBUG("Queue processing stopped.\n");
+}
+
+void*
+queue_processor(void* data)
+{
+#ifdef __OS2__
+    QueueProcessorData *queue_processor_data = (QueueProcessorData *) data;
+    PluginRequestProcessor* processor = queue_processor_data->processor;
+#else
+    PluginRequestProcessor* processor = (PluginRequestProcessor*) data;
+#endif
+    std::vector<std::string*>* message_parts = NULL;
+    std::string command;
+    pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+    PLUGIN_DEBUG("Queue processor initialized. Queue = %p\n", message_queue);
+
+    pthread_mutex_init(&wait_mutex, NULL);
+
+#ifdef __OS2__
+    queue_processor_data->stopRequested = false;
+#else
+    pthread_cleanup_push(queue_cleanup, (void*) &wait_mutex);
+#endif
+
+    while (true)
+    {
+        pthread_mutex_lock(&message_queue_mutex);
+        if (message_queue->size() > 0)
+        {
+            message_parts = message_queue->front();
+            message_queue->erase(message_queue->begin());
+        }
+        pthread_mutex_unlock(&message_queue_mutex);
+
+        if (message_parts)
+        {
+            command = *(message_parts->at(4));
+
+            if (command == "GetMember")
+            {
+                processor->sendMember(message_parts);
+            } else if (command == "ToString")
+            {
+                processor->sendString(message_parts);
+            } else if (command == "SetMember")
+            {
+            	// write methods are synchronized
+            	pthread_mutex_lock(&syn_write_mutex);
+                processor->setMember(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "Call")
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->call(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "Eval")
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->eval(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "GetSlot")
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->sendMember(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "SetSlot")
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->setMember(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "Finalize")
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->finalize(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else if (command == "LoadURL") // For instance X url <url> <target>
+            {
+                // write methods are synchronized
+                pthread_mutex_lock(&syn_write_mutex);
+                processor->loadURL(message_parts);
+                pthread_mutex_unlock(&syn_write_mutex);
+            } else
+            {
+                // Nothing matched
+                IcedTeaPluginUtilities::printStringPtrVector("Error: Unable to process message: ", message_parts);
+            }
+
+            // Free memory for message_parts
+            IcedTeaPluginUtilities::freeStringPtrVector(message_parts);
+
+        } else
+        {
+	    pthread_mutex_lock(&wait_mutex);
+	    pthread_cond_wait(&cond_message_available, &wait_mutex);
+	    pthread_mutex_unlock(&wait_mutex);
+        }
+
+        message_parts = NULL;
+
+#ifdef __OS2__
+        if (queue_processor_data->stopRequested)
+            break;
+#else
+	pthread_testcancel();
+#endif
+    }
+
+#ifdef __OS2__
+    queue_cleanup((void*) &wait_mutex);
+#else
+    pthread_cleanup_pop(1);
+#endif
+}
+
+/******************************************
+ * Functions delegated to the main thread *
+ ******************************************/
+
+void
+_setMember(void* data)
+{
+    std::string* value;
+
+    NPP instance;
+    NPVariant value_variant = NPVariant();
+    NPObject* member;
+    NPIdentifier* property;
+
+    std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
+    instance = (NPP) parameters.at(0);
+    member = (NPObject*) parameters.at(1);
+    property = (NPIdentifier*) parameters.at(2);
+    value = (std::string*) parameters.at(3);
+
+    PLUGIN_DEBUG("Setting %s on instance %p, object %p to value %s\n", browser_functions.utf8fromidentifier(*property), instance, member, value->c_str());
+
+    IcedTeaPluginUtilities::javaResultToNPVariant(instance, value, &value_variant);
+
+    ((AsyncCallThreadData*) data)->call_successful = browser_functions.setproperty(instance, member, *property, &value_variant);
+
+    ((AsyncCallThreadData*) data)->result_ready = true;
+}
+
+void
+_getMember(void* data)
+{
+    NPObject* parent_ptr;
+    NPVariant* member_ptr = new NPVariant();
+    std::string member_ptr_str = std::string();
+    NPP instance;
+
+    std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
+
+    instance = (NPP) parameters.at(0);
+    parent_ptr = (NPObject*) parameters.at(1);
+    NPIdentifier* member_identifier = (NPIdentifier*) parameters.at(2);
+
+    // Get the NPVariant corresponding to this member
+    PLUGIN_DEBUG("Looking for %p %p %p (%s)\n", instance, parent_ptr, member_identifier, browser_functions.utf8fromidentifier(*member_identifier));
+
+    if (!browser_functions.hasproperty(instance, parent_ptr, *member_identifier))
+    {
+        printf("%s not found!\n", browser_functions.utf8fromidentifier(*member_identifier));
+    }
+    ((AsyncCallThreadData*) data)->call_successful = browser_functions.getproperty(instance, parent_ptr, *member_identifier, member_ptr);
+
+    IcedTeaPluginUtilities::printNPVariant(*member_ptr);
+
+    if (((AsyncCallThreadData*) data)->call_successful)
+    {
+        IcedTeaPluginUtilities::JSIDToString(member_ptr, &member_ptr_str);
+        ((AsyncCallThreadData*) data)->result.append(member_ptr_str);
+    }
+    ((AsyncCallThreadData*) data)->result_ready = true;
+
+    // store member -> instance link
+    IcedTeaPluginUtilities::storeInstanceID(member_ptr, instance);
+
+    PLUGIN_DEBUG("_getMember returning.\n");
+}
+
+void
+_eval(void* data)
+{
+    NPP instance;
+    NPObject* window_ptr;
+    std::string* script_str;
+    NPIdentifier script_identifier;
+    NPString script = NPString();
+    NPVariant* eval_result = new NPVariant();
+    std::string eval_result_ptr_str = std::string();
+
+    PLUGIN_DEBUG("_eval called\n");
+
+    std::vector<void*>* call_data = (std::vector<void*>*) data;
+
+    instance = (NPP) call_data->at(0);
+    window_ptr = (NPObject*) call_data->at(1);
+    script_str = (std::string*) call_data->at(2);
+
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+    script.utf8characters = script_str->c_str();
+    script.utf8length = script_str->size();
+
+    PLUGIN_DEBUG("Evaluating: %s\n", script.utf8characters);
+#else
+    script.UTF8Characters = script_str->c_str();
+    script.UTF8Length = script_str->size();
+
+    PLUGIN_DEBUG("Evaluating: %s\n", script.UTF8Characters);
+#endif
+
+    ((AsyncCallThreadData*) data)->call_successful = browser_functions.evaluate(instance, window_ptr, &script, eval_result);
+    IcedTeaPluginUtilities::printNPVariant(*eval_result);
+
+    if (((AsyncCallThreadData*) data)->call_successful)
+    {
+        IcedTeaPluginUtilities::JSIDToString(eval_result, &eval_result_ptr_str);
+        ((AsyncCallThreadData*) data)->result.append(eval_result_ptr_str);
+    }
+    ((AsyncCallThreadData*) data)->result_ready = true;
+
+    PLUGIN_DEBUG("_eval returning\n");
+}
+
+
+void
+_call(void* data)
+{
+    NPP instance;
+    NPObject* window_ptr;
+    std::string* function_name;
+    NPIdentifier function;
+    int* arg_count;
+    NPVariant* args;
+    NPVariant* call_result = new NPVariant();
+    std::string call_result_ptr_str = std::string();
+
+    PLUGIN_DEBUG("_call called\n");
+
+    std::vector<void*>* call_data = (std::vector<void*>*) data;
+
+    instance = (NPP) call_data->at(0);
+    window_ptr = (NPObject*) call_data->at(1);
+    function_name = (std::string*) call_data->at(2);
+
+    function = browser_functions.getstringidentifier(function_name->c_str());
+    arg_count = (int*) call_data->at(3);
+    args = (NPVariant*) call_data->at(4);
+
+    for (int i=0; i < *arg_count; i++) {
+        IcedTeaPluginUtilities::printNPVariant(args[i]);
+    }
+
+    PLUGIN_DEBUG("_calling\n");
+    ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, window_ptr, function, args, *arg_count, call_result);
+    PLUGIN_DEBUG("_called\n");
+
+    IcedTeaPluginUtilities::printNPVariant(*call_result);
+
+    if (((AsyncCallThreadData*) data)->call_successful)
+    {
+        IcedTeaPluginUtilities::JSIDToString(call_result, &call_result_ptr_str);
+        ((AsyncCallThreadData*) data)->result.append(call_result_ptr_str);
+    }
+
+    ((AsyncCallThreadData*) data)->result_ready = true;
+
+    PLUGIN_DEBUG("_call returning\n");
+}
+
+void
+_getString(void* data)
+{
+    NPP instance;
+    NPObject* object;
+    NPIdentifier toString = browser_functions.getstringidentifier("toString");
+    NPVariant tostring_result;
+    std::string result = std::string();
+
+    std::vector<void*>* call_data = (std::vector<void*>*) data;
+    instance = (NPP) call_data->at(0);
+    NPVariant* variant = (NPVariant*) call_data->at(1);
+
+    PLUGIN_DEBUG("_getString called with %p and %p\n", instance, variant);
+
+    if (NPVARIANT_IS_OBJECT(*variant))
+    {
+        ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, NPVARIANT_TO_OBJECT(*variant), toString, NULL, 0, &tostring_result);
+    }
+    else
+    {
+        IcedTeaPluginUtilities::NPVariantToString(*variant, &result);
+        tostring_result = NPVariant();
+        STRINGZ_TO_NPVARIANT(result.c_str(), tostring_result);
+        ((AsyncCallThreadData*) data)->call_successful = true;
+    }
+
+    PLUGIN_DEBUG("ToString result: ");
+    IcedTeaPluginUtilities::printNPVariant(tostring_result);
+
+    if (((AsyncCallThreadData*) data)->call_successful)
+    {
+        createJavaObjectFromVariant(instance, tostring_result, &(((AsyncCallThreadData*) data)->result));
+    }
+    ((AsyncCallThreadData*) data)->result_ready = true;
+
+    PLUGIN_DEBUG("_getString returning\n");
+}
+
+void
+_loadURL(void* data) {
+
+    PLUGIN_DEBUG("_loadURL called\n");
+
+    NPP instance;
+    std::string* url;
+    std::string* target;
+
+    std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
+
+    instance = (NPP) parameters.at(0);
+    url = (std::string*) parameters.at(1);
+    target = (std::string*) parameters.at(2);
+
+    PLUGIN_DEBUG("Launching %s in %s\n", url->c_str(), target->c_str());
+
+    // Each decode can expand to 4 chars at the most
+    gchar* decoded_url = (gchar*) calloc(strlen(url->c_str())*4 + 1, sizeof(gchar));
+    IcedTeaPluginUtilities::decodeURL(url->c_str(), &decoded_url);
+
+    ((AsyncCallThreadData*) data)->call_successful =
+        (*browser_functions.geturl) (instance, decoded_url, target->c_str());
+
+    ((AsyncCallThreadData*) data)->result_ready = true;
+
+    g_free(decoded_url);
+    decoded_url = NULL;
+
+    PLUGIN_DEBUG("_loadURL returning %d\n", ((AsyncCallThreadData*) data)->call_successful);
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginRequestProcessor.h	(revision 403)
@@ -0,0 +1,135 @@
+/* IcedTeaPluginRequestProcessor.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __ICEDTEAPLUGINREQUESTPROCESSOR_H__
+#define __ICEDTEAPLUGINREQUESTPROCESSOR_H__
+
+#include <map>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <npapi.h>
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+#include <npupp.h>
+#else
+#include <npapi.h>
+#include <npruntime.h>
+#endif
+
+#include "IcedTeaPluginUtils.h"
+#include "IcedTeaJavaRequestProcessor.h"
+
+/* Internal request reference counter */
+static long internal_req_ref_counter;
+
+/* Given a value and type, performs the appropriate Java->JS type
+ * mapping and puts it in the given variant */
+
+static void convertToNPVariant(std::string value, std::string type, NPVariant* result_variant);
+
+// Internal methods that need to run in main thread
+void _getMember(void* data);
+void _setMember(void* data);
+void _call(void* data);
+void _eval(void* data);
+void _getString(void* data);
+void _loadURL(void* data);
+
+void* queue_processor(void* data);
+
+/* Mutex to ensure that the request queue is accessed synchronously */
+extern pthread_mutex_t message_queue_mutex;
+
+/* Mutex to ensure synchronized writes */
+extern pthread_mutex_t syn_write_mutex;
+
+/* Queue for holding messages that get processed in a separate thread */
+extern std::vector< std::vector<std::string*>* >* message_queue;
+
+/**
+ * Processes requests made TO the plugin (by java or anyone else)
+ */
+class PluginRequestProcessor : public BusSubscriber
+{
+    private:
+
+    	/* Requests that are still pending */
+    	std::map<pthread_t, uintmax_t>* pendingRequests;
+
+    	/* Dispatch request processing to a new thread for asynch. processing */
+    	void dispatch(void* func_ptr (void*), std::vector<std::string>* message, std::string* src);
+
+        /* Send main window pointer to Java */
+        void sendWindow(std::vector<std::string*>* message_parts);
+
+        /* Stores the variant on java side */
+    	void storeVariantInJava(NPVariant variant, std::string* result);
+
+    public:
+    	PluginRequestProcessor(); /* Constructor */
+    	~PluginRequestProcessor(); /* Destructor */
+
+    	/* Process new requests (if applicable) */
+        virtual bool newMessageOnBus(const char* message);
+
+        /* Send member ID to Java */
+        void sendMember(std::vector<std::string*>* message_parts);
+
+        /* Set member to given value */
+        void setMember(std::vector<std::string*>* message_parts);
+
+        /* Send string value of requested object */
+        void sendString(std::vector<std::string*>* message_parts);
+
+        /* Evaluate the given script */
+        void eval(std::vector<std::string*>* message_parts);
+
+        /* Evaluate the given script */
+        void call(std::vector<std::string*>* message_parts);
+
+        /* Decrements reference count for given object */
+        void finalize(std::vector<std::string*>* message_parts);
+
+        /* Loads a URL into the specified target */
+        void loadURL(std::vector<std::string*>* message_parts);
+};
+
+#endif // __ICEDTEAPLUGINREQUESTPROCESSOR_H__
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.cc	(revision 403)
@@ -0,0 +1,1170 @@
+/* IcedTeaPluginUtils.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifdef __EMX__
+#include <unistd.h> // usleep
+#endif
+
+#include "IcedTeaNPPlugin.h"
+#include "IcedTeaScriptablePluginObject.h"
+#include "IcedTeaPluginUtils.h"
+
+/**
+ * Misc. utility functions used by the plugin
+ */
+
+/***********************************************
+ * Begin IcedTeaPluginUtilities implementation *
+************************************************/
+
+// Initialize static variables
+int IcedTeaPluginUtilities::reference = -1;
+pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER;
+std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>();
+std::map<std::string, NPObject*>* IcedTeaPluginUtilities::object_map = new std::map<std::string, NPObject*>();
+
+/* Plugin async call queue */
+static std::vector< PluginThreadCall* >* pendingPluginThreadRequests = new std::vector< PluginThreadCall* >();
+
+/**
+ * Given a context number, constructs a message prefix to send to Java
+ *
+ * @param context The context of the request
+ * @return The string prefix (allocated on heap)
+ */
+
+void
+IcedTeaPluginUtilities::constructMessagePrefix(int context, std::string *result)
+{
+	std::string context_str = std::string();
+
+	itoa(context, &context_str);
+
+	result->append("context ");
+	result->append(context_str);
+	result->append(" reference -1");
+
+}
+
+/**
+ * Given a context number, and reference number, constructs a message prefix to
+ * send to Java
+ *
+ * @param context The context of the request
+ * @param rerefence The reference number of the request
+ * @param result The message
+ */
+
+void
+IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference, std::string* result)
+{
+    // Until security is implemented, use file:// source for _everything_
+
+	std::string context_str = std::string();
+	std::string reference_str = std::string();
+
+	itoa(context, &context_str);
+	itoa(reference, &reference_str);
+
+	*result += "context ";
+	result->append(context_str);
+	*result += " reference ";
+	result->append(reference_str);
+}
+
+/**
+ * Given a context number, reference number, and source location, constructs
+ * a message prefix to send to Java
+ *
+ * @param context The context of the request
+ * @param rerefence The reference number of the request
+ * @param address The address for the script that made the request
+ * @param result The message
+ */
+
+void
+IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference,
+		                                       std::string address,
+		                                       std::string* result)
+{
+	std::string context_str = std::string();
+	std::string reference_str = std::string();
+
+	itoa(context, &context_str);
+	itoa(reference, &reference_str);
+
+	*result += "context ";
+	result->append(context_str);
+	*result += " reference ";
+	result->append(reference_str);
+
+	if (address.length() > 0)
+	{
+	    *result += " src ";
+        result->append(address);
+	}
+}
+
+/**
+ * Returns a string representation of a void pointer
+ *
+ * @param id The pointer
+ * @param result The string representation
+ */
+
+void
+IcedTeaPluginUtilities::JSIDToString(void* id, std::string* result)
+{
+
+	char* id_str = (char*) malloc(sizeof(char)*20); // max = long long = 8446744073709551615 == 19 chars
+
+	if (sizeof(void*) == sizeof(long long))
+	{
+		sprintf(id_str, "%llu", id);
+	}
+	else
+	{
+		sprintf(id_str, "%lu", id); // else use long
+	}
+
+	result->append(id_str);
+
+	PLUGIN_DEBUG("Converting pointer %p to %s\n", id, id_str);
+	free(id_str);
+}
+
+/**
+ * Returns a void pointer from a string representation
+ *
+ * @param id_str The string representation
+ * @return The pointer
+ */
+
+void*
+IcedTeaPluginUtilities::stringToJSID(std::string id_str)
+{
+	void* ptr;
+	if (sizeof(void*) == sizeof(long long))
+	{
+		PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str.c_str(), strtoull(id_str.c_str(), NULL, 0));
+		ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str.c_str(), NULL, 0));
+	} else
+	{
+		PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str.c_str(), strtoul(id_str.c_str(), NULL, 0));
+		ptr = reinterpret_cast <void*> ((unsigned long)  strtoul(id_str.c_str(), NULL, 0));
+	}
+
+	PLUGIN_DEBUG("Casted: %p\n", ptr);
+
+	return ptr;
+}
+
+/**
+ * Returns a void pointer from a string representation
+ *
+ * @param id_str The pointer to the string representation
+ * @return The pointer
+ */
+
+void*
+IcedTeaPluginUtilities::stringToJSID(std::string* id_str)
+{
+    void* ptr;
+    if (sizeof(void*) == sizeof(long long))
+    {
+        PLUGIN_DEBUG("Casting (long long) \"%s\" -- %llu\n", id_str->c_str(), strtoull(id_str->c_str(), NULL, 0));
+        ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str->c_str(), NULL, 0));
+    } else
+    {
+        PLUGIN_DEBUG("Casting (long) \"%s\" -- %lu\n", id_str->c_str(), strtoul(id_str->c_str(), NULL, 0));
+        ptr = reinterpret_cast <void*> ((unsigned long)  strtoul(id_str->c_str(), NULL, 0));
+    }
+
+    PLUGIN_DEBUG("Casted: %p\n", ptr);
+
+    return ptr;
+}
+
+/**
+ * Increments the global reference number and returns it.
+ *
+ * This function is thread-safe.
+ */
+int
+IcedTeaPluginUtilities::getReference()
+{
+	pthread_mutex_lock(&reference_mutex);
+
+	// If we are nearing the max, reset
+	if (reference < -0x7FFFFFFF + 10) {
+	    reference = -1;
+	}
+
+	reference--;
+	pthread_mutex_unlock(&reference_mutex);
+
+	return reference;
+}
+
+/**
+ * Decrements the global reference number.
+ *
+ * This function is thread-safe.
+ */
+void
+IcedTeaPluginUtilities::releaseReference()
+{
+    // do nothing for now
+}
+
+/**
+ * Converts integer to char*
+ *
+ * @param i The integer to convert to ascii
+ * @param result The resulting string
+ */
+void
+IcedTeaPluginUtilities::itoa(int i, std::string* result)
+{
+	// largest possible integer is 10 digits long
+	char* int_str = (char*) malloc(sizeof(char)*11);
+	sprintf(int_str, "%d", i);
+	result->append(int_str);
+
+	free(int_str);
+}
+
+/**
+ * Frees memory from a string* vector
+ *
+ * The vector deconstructor will only delete string pointers upon being
+ * called. This function frees the associated string memory as well.
+ *
+ * @param v The vector whose strings are to be freed
+ */
+void
+IcedTeaPluginUtilities::freeStringPtrVector(std::vector<std::string*>* v)
+{
+	if (v)
+	{
+		for (int i=0; i < v->size(); i++) {
+			delete v->at(i);
+		}
+
+		delete v;
+	}
+
+}
+
+/**
+ * Given a string, splits it on the given delimiters.
+ *
+ * @param str The string to split
+ * @param The delimiters to split on
+ * @return A string vector containing the aplit components
+ */
+
+std::vector<std::string*>*
+IcedTeaPluginUtilities::strSplit(const char* str, const char* delim)
+{
+	std::vector<std::string*>* v = new std::vector<std::string*>();
+	v->reserve(strlen(str)/2);
+	char* copy;
+
+	// Tokening is done on a copy
+	copy = (char*) malloc (sizeof(char)*strlen(str) + 1);
+	strcpy(copy, str);
+
+	char* tok_ptr;
+	tok_ptr = strtok (copy, delim);
+
+	while (tok_ptr != NULL)
+	{
+	    // Allocation on heap since caller has no way to knowing how much will
+	    // be needed. Make sure caller cleans up!
+		std::string* s = new std::string();
+		s->append(tok_ptr);
+		v->push_back(s);
+		tok_ptr = strtok (NULL, " ");
+	}
+
+	return v;
+}
+
+/**
+ * Given a unicode byte array, converts it to a UTF8 string
+ *
+ * The actual contents in the array may be surrounded by other data.
+ *
+ * e.g. with length 5, begin = 3,
+ * unicode_byte_array = "37 28 5 48 45 4c 4c 4f 9e 47":
+ *
+ * We'd start at 3 i.e. "48" and go on for 5 i.e. upto and including "4f".
+ * So we convert "48 45 4c 4c 4f" which is "hello"
+ *
+ * @param length The length of the string
+ * @param begin Where in the array to begin conversion
+ * @param result_unicode_str The return variable in which the
+ *        converted string is placed
+ */
+
+void
+IcedTeaPluginUtilities::getUTF8String(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::string* result_unicode_str)
+{
+	result_unicode_str->clear();
+	result_unicode_str->reserve(unicode_byte_array->size()/2);
+	for (int i = begin; i < begin+length; i++)
+	    result_unicode_str->push_back((char) strtol(unicode_byte_array->at(i)->c_str(), NULL, 16));
+
+	PLUGIN_DEBUG("Converted UTF-8 string: %s. Length=%d\n", result_unicode_str->c_str(), result_unicode_str->length());
+}
+
+/**
+ * Given a UTF8 string, converts it to a space delimited string of hex characters
+ *
+ * The first element in the return array is the length of the string
+ *
+ * e.g. "hello" would convert to: "5 48 45 4c 4c 4f"
+ *
+ * @param str The string to convert
+ * @param urt_str The result
+ */
+
+void
+IcedTeaPluginUtilities::convertStringToUTF8(std::string* str, std::string* utf_str)
+{
+	std::ostringstream ostream;
+
+	std::string length = std::string();
+	itoa(str->length(), &length);
+
+	ostream << length;
+
+	// UTF-8 characters are 4-bytes max + space + '\0'
+	char* hex_value = (char*) malloc(sizeof(char)*10);
+
+	for (int i = 0; i < str->length(); i++)
+	{
+		sprintf(hex_value, " %hx", str->at(i));
+		ostream << hex_value;
+	}
+
+	utf_str->clear();
+	*utf_str = ostream.str();
+
+	free(hex_value);
+	PLUGIN_DEBUG("Converted %s to UTF-8 string %s\n", str->c_str(), utf_str->c_str());
+}
+
+/**
+ * Given a unicode byte array, converts it to a UTF16LE/UCS-2 string
+ *
+ * This works in a manner similar to getUTF8String, except that it reads 2
+ * slots for each byte.
+ *
+ * @param length The length of the string
+ * @param begin Where in the array to begin conversion
+ * @param result_unicode_str The return variable in which the
+ *        converted string is placed
+ */
+void
+IcedTeaPluginUtilities::getUTF16LEString(int length, int begin, std::vector<std::string*>* unicode_byte_array, std::wstring* result_unicode_str)
+{
+
+	wchar_t c;
+
+	if (plugin_debug) printf("Converted UTF-16LE string: ");
+
+	result_unicode_str->clear();
+	for (int i = begin; i < begin+length; i+=2)
+	{
+		int low = strtol(unicode_byte_array->at(i)->c_str(), NULL, 16);
+		int high = strtol(unicode_byte_array->at(i+1)->c_str(), NULL, 16);
+
+        c = ((high << 8) | low);
+
+        if ((c >= 'a' && c <= 'z') ||
+        	(c >= 'A' && c <= 'Z') ||
+        	(c >= '0' && c <= '9'))
+        {
+        	if (plugin_debug) printf("%c", c);
+        }
+
+        result_unicode_str->push_back(c);
+	}
+
+	// not routing via debug print macros due to wide-string issues
+	if (plugin_debug) printf(". Length=%d\n", result_unicode_str->length());
+}
+
+/*
+ * Prints the given string vector (if debug is true)
+ *
+ * @param prefix The prefix to print before printing the vector contents
+ * @param cv The string vector whose contents are to be printed
+ */
+void
+IcedTeaPluginUtilities::printStringVector(const char* prefix, std::vector<std::string>* str_vector)
+{
+
+        // This is a CPU intensive function. Run only if debugging
+        if (!plugin_debug)
+            return;
+
+	std::string* str = new std::string();
+	*str += "{ ";
+	for (int i=0; i < str_vector->size(); i++)
+	{
+		*str += str_vector->at(i);
+
+		if (i != str_vector->size() - 1)
+			*str += ", ";
+	}
+
+	*str += " }";
+
+	PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
+
+	delete str;
+}
+
+const char*
+IcedTeaPluginUtilities::getSourceFromInstance(NPP instance)
+{
+    // At the moment, src cannot be securely fetched via NPAPI
+    // See:
+    // http://www.mail-archive.com/chromium-dev@googlegroups.com/msg04872.html
+
+    // Since we use the insecure window.location.href attribute to compute
+    // source, we cannot use it to make security decisions. Therefore,
+    // instance associated source will always return empty
+
+    //ITNPPluginData* data = (ITNPPluginData*) instance->pdata;
+    //return (data->source) ? data->source : "";
+
+    return "http://null.null";
+}
+
+/**
+ * Stores a window pointer <-> instance mapping
+ *
+ * @param member_ptr The pointer key
+ * @param instance The instance to associate with this pointer
+ */
+
+void
+IcedTeaPluginUtilities::storeInstanceID(void* member_ptr, NPP instance)
+{
+    PLUGIN_DEBUG("Storing instance %p with key %p\n", instance, member_ptr);
+    instance_map->insert(std::make_pair(member_ptr, instance));
+}
+
+/**
+ * Removes a window pointer <-> instance mapping
+ *
+ * @param member_ptr The key to remove
+ */
+
+void
+IcedTeaPluginUtilities::removeInstanceID(void* member_ptr)
+{
+    PLUGIN_DEBUG("Removing key %p from instance map\n", member_ptr);
+    instance_map->erase(member_ptr);
+}
+
+/**
+ * Removes all mappings to a given instance, and all associated objects
+ */
+void
+IcedTeaPluginUtilities::invalidateInstance(NPP instance)
+{
+    PLUGIN_DEBUG("Invalidating instance %p\n", instance);
+
+    std::map<void*,NPP>::iterator iterator;
+
+    for (iterator = instance_map->begin(); iterator != instance_map->end(); )
+    {
+        if ((*iterator).second == instance)
+        {
+            instance_map->erase(iterator++);
+        }
+        else
+        {
+            ++iterator;
+        }
+    }
+}
+
+/**
+ * Given the window pointer, returns the instance associated with it
+ *
+ * @param member_ptr The pointer key
+ * @return The associated instance
+ */
+
+NPP
+IcedTeaPluginUtilities::getInstanceFromMemberPtr(void* member_ptr)
+{
+
+    NPP instance = NULL;
+    PLUGIN_DEBUG("getInstanceFromMemberPtr looking for %p\n", member_ptr);
+
+    std::map<void*, NPP>::iterator iterator = instance_map->find(member_ptr);
+
+    if (iterator != instance_map->end())
+    {
+        instance = instance_map->find(member_ptr)->second;
+        PLUGIN_DEBUG("getInstanceFromMemberPtr found %p. Instance = %p\n", member_ptr, instance);
+    }
+
+    return instance;
+}
+
+/**
+ * Given a java id key ('classid:instanceid'), returns the associated valid NPObject, if any
+ *
+ * @param key the key
+ * @return The associated active NPObject, NULL otherwise
+ */
+
+NPObject*
+IcedTeaPluginUtilities::getNPObjectFromJavaKey(std::string key)
+{
+
+    NPObject* object = NULL;
+    PLUGIN_DEBUG("getNPObjectFromJavaKey looking for %s\n", key.c_str());
+
+    std::map<std::string, NPObject*>::iterator iterator = object_map->find(key);
+
+    if (iterator != object_map->end())
+    {
+        NPObject* mapped_object = object_map->find(key)->second;
+
+        if (getInstanceFromMemberPtr(mapped_object) != NULL)
+        {
+            object = mapped_object;
+            PLUGIN_DEBUG("getNPObjectFromJavaKey found %s. NPObject = %p\n", key.c_str(), object);
+        }
+    }
+
+    return object;
+}
+
+/**
+ * Stores a java id key <-> NPObject mapping
+ *
+ * @param key The Java ID Key
+ * @param object The object to map to
+ */
+
+void
+IcedTeaPluginUtilities::storeObjectMapping(std::string key, NPObject* object)
+{
+    PLUGIN_DEBUG("Storing object %p with key %s\n", object, key.c_str());
+    object_map->insert(std::make_pair(key, object));
+}
+
+/**
+ * Removes a java id key <-> NPObject mapping
+ *
+ * @param key The key to remove
+ */
+
+void
+IcedTeaPluginUtilities::removeObjectMapping(std::string key)
+{
+    PLUGIN_DEBUG("Removing key %s from object map\n", key.c_str());
+    object_map->erase(key);
+}
+
+/*
+ * Similar to printStringVector, but takes a vector of string pointers instead
+ *
+ * @param prefix The prefix to print before printing the vector contents
+ * @param cv The string* vector whose contents are to be printed
+ */
+
+void
+IcedTeaPluginUtilities::printStringPtrVector(const char* prefix, std::vector<std::string*>* str_ptr_vector)
+{
+        // This is a CPU intensive function. Run only if debugging
+        if (!plugin_debug)
+            return;
+
+	std::string* str = new std::string();
+	*str += "{ ";
+	for (int i=0; i < str_ptr_vector->size(); i++)
+	{
+		*str += *(str_ptr_vector->at(i));
+
+		if (i != str_ptr_vector->size() - 1)
+			*str += ", ";
+	}
+
+	*str += " }";
+
+	PLUGIN_DEBUG("%s %s\n", prefix, str->c_str());
+
+	delete str;
+}
+
+void
+IcedTeaPluginUtilities::printNPVariant(NPVariant variant)
+{
+    // This is a CPU intensive function. Run only if debugging
+    if (!plugin_debug)
+        return;
+
+    if (NPVARIANT_IS_VOID(variant))
+    {
+    	PLUGIN_DEBUG("VOID %d\n", variant);
+    }
+    else if (NPVARIANT_IS_NULL(variant))
+    {
+    	PLUGIN_DEBUG("NULL\n", variant);
+    }
+    else if (NPVARIANT_IS_BOOLEAN(variant))
+    {
+    	PLUGIN_DEBUG("BOOL: %d\n", NPVARIANT_TO_BOOLEAN(variant));
+    }
+    else if (NPVARIANT_IS_INT32(variant))
+    {
+    	PLUGIN_DEBUG("INT32: %d\n", NPVARIANT_TO_INT32(variant));
+    }
+    else if (NPVARIANT_IS_DOUBLE(variant))
+    {
+    	PLUGIN_DEBUG("DOUBLE: %f\n", NPVARIANT_TO_DOUBLE(variant));
+    }
+    else if (NPVARIANT_IS_STRING(variant))
+    {
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+    	PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).utf8characters);
+#else
+    	PLUGIN_DEBUG("STRING: %s\n", NPVARIANT_TO_STRING(variant).UTF8Characters);
+#endif
+    }
+    else
+    {
+    	PLUGIN_DEBUG("OBJ: %p\n", NPVARIANT_TO_OBJECT(variant));
+    }
+}
+
+void
+IcedTeaPluginUtilities::NPVariantToString(NPVariant variant, std::string* result)
+{
+	char* str = (char*) malloc(sizeof(char)*32); // enough for everything except string
+
+    if (NPVARIANT_IS_VOID(variant))
+    {
+        sprintf(str, "%p", variant);
+    }
+    else if (NPVARIANT_IS_NULL(variant))
+    {
+    	sprintf(str, "NULL");
+    }
+    else if (NPVARIANT_IS_BOOLEAN(variant))
+    {
+    	if (NPVARIANT_TO_BOOLEAN(variant))
+    		sprintf(str, "true");
+    	else
+    		sprintf(str, "false");
+    }
+    else if (NPVARIANT_IS_INT32(variant))
+    {
+    	sprintf(str, "%d", NPVARIANT_TO_INT32(variant));
+    }
+    else if (NPVARIANT_IS_DOUBLE(variant))
+    {
+    	sprintf(str, "%f", NPVARIANT_TO_DOUBLE(variant));;
+    }
+    else if (NPVARIANT_IS_STRING(variant))
+    {
+    	free(str);
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+    	str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).utf8length);
+    	sprintf(str, "%s", NPVARIANT_TO_STRING(variant).utf8characters);
+#else
+        str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).UTF8Length);
+        sprintf(str, "%s", NPVARIANT_TO_STRING(variant).UTF8Characters);
+#endif
+    }
+    else
+    {
+        sprintf(str, "[Object %p]", variant);
+    }
+
+    result->append(str);
+    free(str);
+}
+
+bool
+IcedTeaPluginUtilities::javaResultToNPVariant(NPP instance,
+                                              std::string* java_value,
+                                              NPVariant* variant)
+{
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    if (java_value->find("literalreturn") == 0)
+    {
+        // 'literalreturn ' == 14 to skip
+        std::string value = java_value->substr(14);
+
+        // VOID/BOOLEAN/NUMBER
+
+        if (value == "void")
+        {
+            PLUGIN_DEBUG("Method call returned void\n");
+            VOID_TO_NPVARIANT(*variant);
+        } else if (value == "null")
+        {
+            PLUGIN_DEBUG("Method call returned null\n");
+            NULL_TO_NPVARIANT(*variant);
+        }else if (value == "true")
+        {
+            PLUGIN_DEBUG("Method call returned a boolean (true)\n");
+            BOOLEAN_TO_NPVARIANT(true, *variant);
+        } else if (value == "false")
+        {
+            PLUGIN_DEBUG("Method call returned a boolean (false)\n");
+            BOOLEAN_TO_NPVARIANT(false, *variant);
+        } else
+        {
+            double d = strtod(value.c_str(), NULL);
+
+            // See if it is convertible to int
+            if (value.find(".") != std::string::npos ||
+                d < -(0x7fffffffL - 1L) ||
+                d > 0x7fffffffL)
+            {
+                PLUGIN_DEBUG("Method call returned a double %f\n", d);
+                DOUBLE_TO_NPVARIANT(d, *variant);
+            } else
+            {
+                int32_t i = (int32_t) d;
+                PLUGIN_DEBUG("Method call returned an int %d\n", i);
+                INT32_TO_NPVARIANT(i, *variant);
+            }
+        }
+    } else {
+        // Else this is a complex java object
+
+        // To keep code a little bit cleaner, we create variables with proper descriptive names
+        std::string return_obj_instance_id = std::string();
+        std::string return_obj_class_id = std::string();
+        std::string return_obj_class_name = std::string();
+        return_obj_instance_id.append(*java_value);
+
+        // Find out the class name first, because string is a special case
+        java_result = java_request.getClassName(return_obj_instance_id);
+
+        if (java_result->error_occurred)
+        {
+            return false;
+        }
+
+        return_obj_class_name.append(*(java_result->return_string));
+
+        if (return_obj_class_name == "java.lang.String")
+        {
+            // String is a special case as NPVariant can handle it directly
+            java_result = java_request.getString(return_obj_instance_id);
+
+            if (java_result->error_occurred)
+            {
+                return false;
+            }
+
+            // needs to be on the heap
+            NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
+            strcpy(return_str, java_result->return_string->c_str());
+
+            PLUGIN_DEBUG("Method call returned a string: \"%s\"\n", return_str);
+            STRINGZ_TO_NPVARIANT(return_str, *variant);
+
+        } else {
+
+            // Else this is a regular class. Reference the class object so
+            // we can construct an NPObject with it and the instance
+            java_result = java_request.getClassID(return_obj_instance_id);
+
+            if (java_result->error_occurred)
+            {
+                return false;
+            }
+
+            return_obj_class_id.append(*(java_result->return_string));
+
+            NPObject* obj;
+
+            if (return_obj_class_name.find('[') == 0) // array
+                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                                instance,
+                                return_obj_class_id, return_obj_instance_id, true);
+            else
+                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                                                instance,
+                                                return_obj_class_id, return_obj_instance_id, false);
+
+            OBJECT_TO_NPVARIANT(obj, *variant);
+        }
+    }
+
+    return true;
+}
+
+bool
+IcedTeaPluginUtilities::isObjectJSArray(NPP instance, NPObject* object)
+{
+
+    NPVariant constructor_v = NPVariant();
+    NPIdentifier constructor_id = browser_functions.getstringidentifier("constructor");
+    browser_functions.getproperty(instance, object, constructor_id, &constructor_v);
+    IcedTeaPluginUtilities::printNPVariant(constructor_v);
+
+    // void constructor => not an array
+    if (NPVARIANT_IS_VOID(constructor_v))
+        return false;
+
+    NPObject* constructor = NPVARIANT_TO_OBJECT(constructor_v);
+
+    NPVariant constructor_str;
+    NPIdentifier toString = browser_functions.getstringidentifier("toString");
+    browser_functions.invoke(instance, constructor, toString, NULL, 0, &constructor_str);
+    IcedTeaPluginUtilities::printNPVariant(constructor_str);
+
+    std::string constructor_name = std::string();
+
+#if MOZILLA_VERSION_COLLAPSED < 1090200
+    constructor_name.append(NPVARIANT_TO_STRING(constructor_str).utf8characters);
+#else
+    constructor_name.append(NPVARIANT_TO_STRING(constructor_str).UTF8Characters);
+#endif
+
+    PLUGIN_DEBUG("Constructor for NPObject is %s\n", constructor_name.c_str());
+
+    return constructor_name.find("function Array") == 0;
+}
+
+void
+IcedTeaPluginUtilities::decodeURL(const gchar* url, gchar** decoded_url)
+{
+
+    PLUGIN_DEBUG("GOT URL: %s -- %s\n", url, *decoded_url);
+    int length = strlen(url);
+    for (int i=0; i < length; i++)
+    {
+        if (url[i] == '%' && i < length - 2)
+        {
+            unsigned char code1 = (unsigned char) url[i+1];
+            unsigned char code2 = (unsigned char) url[i+2];
+
+            if (!IS_VALID_HEX(&code1) || !IS_VALID_HEX(&code2))
+                continue;
+
+            // Convert hex value to integer
+            int converted1 = HEX_TO_INT(&code1);
+            int converted2 = HEX_TO_INT(&code2);
+
+            // bitshift 4 to simulate *16
+            int value = (converted1 << 4) + converted2;
+            char decoded = value;
+
+            strncat(*decoded_url, &decoded, 1);
+
+            i += 2;
+        } else
+        {
+            strncat(*decoded_url, &url[i], 1);
+        }
+    }
+
+    PLUGIN_DEBUG("SENDING URL: %s\n", *decoded_url);
+}
+
+
+/**
+ * Posts a function for execution on the plug-in thread and wait for result.
+ *
+ * @param instance The NPP instance
+ * @param func The function to post
+ * @param data Arguments to *func
+ */
+void
+IcedTeaPluginUtilities::callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data)
+{
+
+    struct timespec t;
+    struct timespec curr_t;
+#ifdef __OS2__
+    t.tv_sec = time(NULL);
+    t.tv_nsec = 0;
+    curr_t.tv_sec = curr_t.tv_nsec = 0;
+#else
+    clock_gettime(CLOCK_REALTIME, &t);
+#endif
+    t.tv_sec += REQUESTTIMEOUT; // timeout
+
+    // post request
+    postPluginThreadAsyncCall(instance, func, data);
+
+    do
+    {
+#ifdef __OS2__
+        curr_t.tv_sec = time(NULL);
+#else
+        clock_gettime(CLOCK_REALTIME, &curr_t);
+#endif
+        if (data != NULL && !data->result_ready && (curr_t.tv_sec < t.tv_sec))
+        {
+            usleep(2000);
+        } else
+        {
+            break;
+        }
+    } while (1);
+}
+
+
+/**
+ * Posts a request that needs to be handled in a plugin thread.
+ *
+ * @param instance The plugin instance
+ * @param func The function to execute
+ * @param userData The userData for the function to consume/write to
+ * @return if the call was posted successfully
+ */
+
+bool
+IcedTeaPluginUtilities::postPluginThreadAsyncCall(NPP instance, void (*func) (void *), void* data)
+{
+    if (instance)
+    {
+        PluginThreadCall* call = new PluginThreadCall();
+        call->instance = instance;
+        call->func = func;
+        call->userData = data;
+
+        pthread_mutex_lock(&pluginAsyncCallMutex);
+        pendingPluginThreadRequests->push_back(call);
+        pthread_mutex_unlock(&pluginAsyncCallMutex);
+
+        browser_functions.pluginthreadasynccall(instance, &processAsyncCallQueue, NULL); // Always returns immediately
+
+        PLUGIN_DEBUG("Pushed back call evt %p\n", call);
+
+        return true;
+    }
+
+    // Else
+    PLUGIN_DEBUG("Instance is not active. Call rejected.\n");
+    return false;
+}
+
+/**
+ * Runs through the async call wait queue and executes all calls
+ *
+ * @param param Ignored -- required to conform to NPN_PluginThreadAsynCall API
+ */
+void
+processAsyncCallQueue(void* param /* ignored */)
+{
+    do {
+        PluginThreadCall* call = NULL;
+
+        pthread_mutex_lock(&pluginAsyncCallMutex);
+        if (pendingPluginThreadRequests->size() > 0)
+        {
+            call = pendingPluginThreadRequests->front();
+            pendingPluginThreadRequests->erase(pendingPluginThreadRequests->begin());
+        }
+        pthread_mutex_unlock(&pluginAsyncCallMutex);
+
+        if (call)
+        {
+            PLUGIN_DEBUG("Processing call evt %p\n", call);
+            call->func(call->userData);
+            PLUGIN_DEBUG("Call evt %p processed\n", call);
+
+            delete call;
+        } else
+        {
+            break;
+        }
+    } while(1);
+}
+
+/******************************************
+ * Begin JavaMessageSender implementation *
+ ******************************************
+ *
+ * This implementation is very simple and is therefore folded into this file
+ * rather than a new one.
+ */
+
+/**
+ * Sends to the Java side
+ *
+ * @param message The message to send.
+ * @param returns whether the message was consumable (always true)
+ */
+
+bool
+JavaMessageSender::newMessageOnBus(const char* message)
+{
+	char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
+	strcpy(msg, message);
+	plugin_send_message_to_appletviewer(msg);
+
+	free(msg);
+	msg = NULL;
+
+	// Always successful
+	return true;
+}
+
+/***********************************
+ * Begin MessageBus implementation *
+ ***********************************/
+
+/**
+ * Constructor.
+ *
+ * Initializes the mutexes needed by the other functions.
+ */
+MessageBus::MessageBus()
+{
+	int ret;
+
+	ret = pthread_mutex_init(&subscriber_mutex, NULL);
+
+	if(ret)
+		PLUGIN_DEBUG("Error: Unable to initialize subscriber mutex: %d\n", ret);
+
+	ret = pthread_mutex_init(&msg_queue_mutex, NULL);
+	if(ret)
+		PLUGIN_DEBUG("Error: Unable to initialize message queue mutex: %d\n", ret);
+
+	PLUGIN_DEBUG("Mutexs %p and %p initialized\n", &subscriber_mutex, &msg_queue_mutex);
+}
+
+/**
+ * Destructor.
+ *
+ * Destroy the mutexes initialized by the constructor.
+ */
+
+MessageBus::~MessageBus()
+{
+    PLUGIN_DEBUG("MessageBus::~MessageBus\n");
+
+	int ret;
+
+	ret = pthread_mutex_destroy(&subscriber_mutex);
+	if(ret)
+		PLUGIN_DEBUG("Error: Unable to destroy subscriber mutex: %d\n", ret);
+
+	ret = pthread_mutex_destroy(&msg_queue_mutex);
+	if(ret)
+			PLUGIN_DEBUG("Error: Unable to destroy message queue mutex: %d\n", ret);
+}
+
+/**
+ * Adds the given BusSubscriber as a subscriber to self
+ *
+ * @param b The BusSubscriber to subscribe
+ */
+void
+MessageBus::subscribe(BusSubscriber* b)
+{
+    // Applets may initialize in parallel. So lock before pushing.
+
+	PLUGIN_DEBUG("Subscribing %p to bus %p\n", b, this);
+    pthread_mutex_lock(&subscriber_mutex);
+    subscribers.push_back(b);
+    pthread_mutex_unlock(&subscriber_mutex);
+}
+
+/**
+ * Removes the given BusSubscriber from the subscriber list
+ *
+ * @param b The BusSubscriber to ubsubscribe
+ */
+void
+MessageBus::unSubscribe(BusSubscriber* b)
+{
+    // Applets may initialize in parallel. So lock before pushing.
+
+	PLUGIN_DEBUG("Un-subscribing %p from bus %p\n", b, this);
+    pthread_mutex_lock(&subscriber_mutex);
+    subscribers.remove(b);
+    pthread_mutex_unlock(&subscriber_mutex);
+}
+
+/**
+ * Notifies all subscribers with the given message
+ *
+ * @param message The message to send to the subscribers
+ */
+void
+MessageBus::post(const char* message)
+{
+	char* msg = (char*) malloc(sizeof(char)*strlen(message) + 1);
+	bool message_consumed = false;
+
+	// consumer frees this memory
+	strcpy(msg, message);
+
+	PLUGIN_DEBUG("Trying to lock %p...\n", &msg_queue_mutex);
+	pthread_mutex_lock(&subscriber_mutex);
+
+    PLUGIN_DEBUG("Message %s received on bus. Notifying subscribers.\n", msg);
+
+    std::list<BusSubscriber*>::const_iterator i;
+    for( i = subscribers.begin(); i != subscribers.end() && !message_consumed; ++i ) {
+    	PLUGIN_DEBUG("Notifying subscriber %p of %s\n", *i, msg);
+    	message_consumed = ((BusSubscriber*) *i)->newMessageOnBus(msg);
+    }
+
+    pthread_mutex_unlock(&subscriber_mutex);
+
+    if (!message_consumed)
+    	PLUGIN_DEBUG("Warning: No consumer found for message %s\n", msg);
+
+    PLUGIN_DEBUG("%p unlocked...\n", &msg_queue_mutex);
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaPluginUtils.h	(revision 403)
@@ -0,0 +1,333 @@
+/* IcedTeaPluginUtils.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+/**
+ * Utility classes for the IcedTeaPlugin
+ */
+
+#ifndef __ICEDTEAPLUGINUTILS_H__
+#define __ICEDTEAPLUGINUTILS_H__
+
+#include <pthread.h>
+#include <stdio.h>
+
+#include <cstring>
+#include <iostream>
+#include <list>
+#include <map>
+#include <queue>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <npapi.h>
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+#include <npupp.h>
+#else
+#include <npapi.h>
+#include <npruntime.h>
+#endif
+
+extern int plugin_debug; // defined in IcedTeaNPPlugin.cc
+
+#define PLUGIN_DEBUG(...) \
+  do                                                          \
+  {                                                           \
+    if (plugin_debug)                                         \
+    {                                                         \
+      fprintf (stderr, "ITNPP Thread# %ld: ", pthread_self()); \
+      fprintf (stderr, __VA_ARGS__);                          \
+    }                                                         \
+  } while (0)
+
+#define CHECK_JAVA_RESULT(result_data)                               \
+{                                                                    \
+    if (((JavaResultData*) result_data)->error_occurred)             \
+    {                                                                \
+        printf("Error: Error occurred on Java side: %s.\n",          \
+               ((JavaResultData*) result_data)->error_msg->c_str()); \
+        return;                                                      \
+    }                                                                \
+}
+
+#define HEX_TO_INT(c) \
+    ((*c >= 'a') ? *c - 'a' + 10 : \
+     (*c >= 'A') ? *c - 'A' + 10 : \
+     *c - '0')
+
+#define IS_VALID_HEX(c) \
+    ((*c >= '0' && *c <= '9') || \
+     (*c >= 'a' && *c <= 'f') || \
+     (*c >= 'A' && *c <= 'F'))
+
+/*
+ * This struct holds data specific to a Java operation requested by the plugin
+ */
+typedef struct java_result_data
+{
+
+    // Return identifier (if applicable)
+    int return_identifier;
+
+    // Return string (if applicable)
+    std::string* return_string;
+
+    // Return wide/mb string (if applicable)
+    std::wstring* return_wstring;
+
+    // Error message (if an error occurred)
+    std::string* error_msg;
+
+    // Boolean indicating if an error occurred
+    bool error_occurred;
+
+} JavaResultData;
+
+/**
+ * This struct holds data to do calls that need to be run in the plugin thread
+ */
+typedef struct plugin_thread_call
+{
+   // The plugin instance
+   NPP instance;
+
+   // The function to call
+   void (*func) (void *);
+
+   // The data to pass to the function
+   void *userData;
+
+} PluginThreadCall;
+
+/**
+ * Data structure passed to functions called in a new thread.
+ */
+
+typedef struct async_call_thread_data
+{
+    std::vector<void*> parameters;
+    std::string result;
+    bool result_ready;
+    bool call_successful;
+} AsyncCallThreadData;
+
+/*
+ * Misc. utility functions
+ *
+ * This class is never instantiated and should contain static functions only
+ */
+
+/* Function to process all pending async calls */
+void processAsyncCallQueue(void*);
+
+class IcedTeaPluginUtilities
+{
+
+    private:
+        static int reference; /* Reference count */
+
+        /* Mutex lock for updating reference count */
+        static pthread_mutex_t reference_mutex;
+
+        /* Map holding window pointer<->instance relationships */
+        static std::map<void*, NPP>* instance_map;
+
+        /* Map holding java-side-obj-key->NPObject relationship  */
+        static std::map<std::string, NPObject*>* object_map;
+
+        /* Posts a call in the async call queue */
+        static bool postPluginThreadAsyncCall(NPP instance, void (*func) (void *), void* data);
+
+    public:
+
+    	/* Constructs message prefix with given context */
+    	static void constructMessagePrefix(int context,
+                                           std::string* result);
+
+    	/* Constructs message prefix with given context and reference */
+    	static void constructMessagePrefix(int context, int reference,
+                                           std::string* result);
+
+    	/* Constructs message prefix with given context, reference and src */
+    	static void constructMessagePrefix(int context, int reference,
+                                           std::string address,
+                                           std::string* result);
+
+    	/* Converts given pointer to a string representation */
+    	static void JSIDToString(void* id, std::string* result);
+
+    	/* Converts the given string representation to a pointer */
+    	static void* stringToJSID(std::string id_str);
+    	static void* stringToJSID(std::string* id_str);
+
+    	/* Increments reference count and returns it */
+    	static int getReference();
+
+    	/* Decrements reference count */
+    	static void releaseReference();
+
+    	/* Converts the given integer to a string */
+    	static void itoa(int i, std::string* result);
+
+    	/* Frees the given vector and the strings that its contents point to */
+    	static void freeStringPtrVector(std::vector<std::string*>* v);
+
+    	/* Splits the given string based on the delimiter provided */
+    	static std::vector<std::string*>* strSplit(const char* str,
+    			                                  const char* delim);
+
+    	/* Converts given unicode integer byte array to UTF8 string  */
+    	static void getUTF8String(int length, int begin,
+    			std::vector<std::string*>* unicode_byte_array,
+    			std::string* result_unicode_str);
+
+    	/* Converts given UTF8 string to unicode integer byte array */
+    	static void convertStringToUTF8(std::string* str,
+    			                        std::string* utf_str);
+
+    	/* Converts given unicode integer byte array to UTF16LE/UCS-2 string */
+    	static void getUTF16LEString(int length, int begin,
+    			std::vector<std::string*>* unicode_byte_array,
+    			std::wstring* result_unicode_str);
+
+    	/* Prints contents of given string vector */
+    	static void printStringVector(const char* prefix, std::vector<std::string>* cv);
+
+    	/* Prints contents of given string pointer vector */
+    	static void printStringPtrVector(const char* prefix, std::vector<std::string*>* cv);
+
+    	static std::string* variantToClassName(NPVariant variant);
+
+    	static void printNPVariant(NPVariant variant);
+
+    	static void NPVariantToString(NPVariant variant, std::string* result);
+
+        static bool javaResultToNPVariant(NPP instance,
+                                          std::string* java_result,
+                                          NPVariant* variant);
+
+    	static const char* getSourceFromInstance(NPP instance);
+
+    	static void storeInstanceID(void* member_ptr, NPP instance);
+
+    	static void	removeInstanceID(void* member_ptr);
+
+        static NPP getInstanceFromMemberPtr(void* member_ptr);
+
+    	static NPObject* getNPObjectFromJavaKey(std::string key);
+
+    	static void storeObjectMapping(std::string key, NPObject* object);
+
+    	static void removeObjectMapping(std::string key);
+
+    	static void invalidateInstance(NPP instance);
+
+    	static bool isObjectJSArray(NPP instance, NPObject* object);
+
+    	static void decodeURL(const char* url, char** decoded_url);
+
+    	/* Posts call in async queue and waits till execution completes */
+    	static void callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data);
+};
+
+/*
+ * A bus subscriber interface. Implementors must implement the newMessageOnBus
+ * method.
+ */
+class BusSubscriber
+{
+    private:
+
+    public:
+    	BusSubscriber() {}
+
+    	/* Notifies this subscriber that a new message as arrived */
+        virtual bool newMessageOnBus(const char* message) = 0;
+};
+
+/*
+ * This implementation is very simple and is therefore folded into this file
+ * rather than a new one.
+ */
+class JavaMessageSender : public BusSubscriber
+{
+    private:
+    public:
+
+    	/* Sends given message to Java side */
+        virtual bool newMessageOnBus(const char* message);
+};
+
+/*
+ * Represents a message bus.
+ * The bus can also have subscribers who are notified when a new message
+ * arrives.
+ */
+class MessageBus
+{
+    private:
+    	/* Mutex for locking the message queue */
+    	pthread_mutex_t msg_queue_mutex;
+
+    	/* Mutex used when adjusting subscriber list */
+    	pthread_mutex_t subscriber_mutex;
+
+    	/* Subscriber list */
+        std::list<BusSubscriber*> subscribers;
+
+        /* Queued messages */
+        std::queue<char*> msgQueue;
+
+    public:
+    	MessageBus();
+
+        ~MessageBus();
+
+        /* subscribe to this bus */
+        void subscribe(BusSubscriber* b);
+
+        /* unsubscribe from this bus */
+        void unSubscribe(BusSubscriber* b);
+
+        /* Post a message on to the bus (it is safe to free the message pointer
+           after this function returns) */
+        void post(const char* message);
+};
+
+#endif // __ICEDTEAPLUGINUTILS_H__
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.cc	(revision 403)
@@ -0,0 +1,75 @@
+/* IcedTeaRunnable.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include <stdio.h>
+#include "IcedTeaRunnable.h"
+
+NS_IMPL_ISUPPORTS1 (IcedTeaRunnable, nsIRunnable)
+
+IcedTeaRunnable::IcedTeaRunnable ()
+{
+}
+
+IcedTeaRunnable::~IcedTeaRunnable ()
+{
+}
+
+NS_IMETHODIMP
+IcedTeaRunnable::Run ()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+IcedTeaRunnableMethod::IcedTeaRunnableMethod (Method method, void* thread_data, void* result)
+: method (method),
+  thread_data(thread_data),
+  result(result)
+{
+}
+
+IcedTeaRunnableMethod::~IcedTeaRunnableMethod ()
+{
+ }
+
+NS_IMETHODIMP
+IcedTeaRunnableMethod::Run ()
+{
+    printf("Running method...\n");
+    (*method) (thread_data, result);
+    return NS_OK;
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaRunnable.h	(revision 403)
@@ -0,0 +1,104 @@
+/* IcedTeaRunnable.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __ICEDTEARUNNABLE_H__
+#define __ICEDTEARUNNABLE_H__
+
+#define MOZILLA 1
+#if MOZILLA
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+#include <nsIRunnable.h>
+#include <string>
+#endif
+
+/*
+ * This struct holds the result from the main-thread dispatched method
+ */
+typedef struct result_data
+{
+	// Return identifier (if applicable)
+    int return_identifier;
+
+    // Return string (if applicable)
+    std::string* return_string;
+
+    // Return wide/mb string (if applicable)
+    std::wstring* return_wstring;
+
+    // Error message (if an error occurred)
+    std::string* error_msg;
+
+    // Boolean indicating if an error occurred
+    bool error_occured;
+
+    // If this result is ready
+    bool result_ready;
+
+} ResultData;
+
+class IcedTeaRunnable : public nsIRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+
+  IcedTeaRunnable ();
+
+  ~IcedTeaRunnable ();
+};
+
+class IcedTeaRunnableMethod : public IcedTeaRunnable
+{
+public:
+
+  typedef void* (*Method) (void*, void*);
+
+  IcedTeaRunnableMethod (Method, void* thread_data, void* result);
+  NS_IMETHOD Run ();
+
+  ~IcedTeaRunnableMethod ();
+
+  Method method;
+  void* thread_data;
+  void* result;
+};
+
+#endif /* MOZILLA */
+
+#endif /* __ICEDTEARUNNABLE_H__ */
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	(revision 403)
@@ -0,0 +1,895 @@
+/* IcedTeaScriptablePluginObject.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include <typeinfo>
+
+#include "IcedTeaScriptablePluginObject.h"
+
+IcedTeaScriptablePluginObject::IcedTeaScriptablePluginObject(NPP instance)
+{
+	this->instance = instance;
+	IcedTeaPluginUtilities::storeInstanceID(this, instance);
+}
+
+void
+IcedTeaScriptablePluginObject::deAllocate(NPObject *npobj)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::deAllocate %p\n", npobj);
+}
+
+void
+IcedTeaScriptablePluginObject::invalidate(NPObject *npobj)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::invalidate %p\n", npobj);
+}
+
+bool
+IcedTeaScriptablePluginObject::hasMethod(NPObject *npobj, NPIdentifier name)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::hasMethod %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+			uint32_t argCount,NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::invoke %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::invokeDefault(NPObject *npobj, const NPVariant *args,
+			       uint32_t argCount, NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::invokeDefault %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::hasProperty(NPObject *npobj, NPIdentifier name)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::hasProperty %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
+{
+	// Package request?
+	if (!strcmp(browser_functions.utf8fromidentifier(name), "java"))
+	{
+		//NPObject* obj = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(getInstanceFromMemberPtr(npobj), name);
+		//OBJECT_TO_NPVARIANT(obj, *result);
+
+		//printf ("Filling variant %p with object %p\n", result);
+	}
+
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::setProperty %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::removeProperty(NPObject *npobj, NPIdentifier name)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::removeProperty %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::enumerate %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptablePluginObject::construct(NPObject *npobj, const NPVariant *args, uint32_t argCount,
+	           NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptablePluginObject::construct %p\n", npobj);
+	return false;
+}
+
+NPObject*
+allocate_scriptable_jp_object(NPP npp, NPClass *aClass)
+{
+    PLUGIN_DEBUG("Allocating new scriptable Java Package object\n");
+    return new IcedTeaScriptableJavaPackageObject(npp);
+}
+
+NPObject*
+IcedTeaScriptablePluginObject::get_scriptable_java_package_object(NPP instance, const NPUTF8* name)
+{
+
+	NPObject* scriptable_object;
+
+	NPClass* np_class = new NPClass();
+	np_class->structVersion = NP_CLASS_STRUCT_VERSION;
+	np_class->allocate = allocate_scriptable_jp_object;
+	np_class->deallocate = IcedTeaScriptableJavaPackageObject::deAllocate;
+	np_class->invalidate = IcedTeaScriptableJavaPackageObject::invalidate;
+	np_class->hasMethod = IcedTeaScriptableJavaPackageObject::hasMethod;
+	np_class->invoke = IcedTeaScriptableJavaPackageObject::invoke;
+	np_class->invokeDefault = IcedTeaScriptableJavaPackageObject::invokeDefault;
+	np_class->hasProperty = IcedTeaScriptableJavaPackageObject::hasProperty;
+	np_class->getProperty = IcedTeaScriptableJavaPackageObject::getProperty;
+	np_class->setProperty = IcedTeaScriptableJavaPackageObject::setProperty;
+	np_class->removeProperty = IcedTeaScriptableJavaPackageObject::removeProperty;
+	np_class->enumerate = IcedTeaScriptableJavaPackageObject::enumerate;
+	np_class->construct = IcedTeaScriptableJavaPackageObject::construct;
+
+	scriptable_object = browser_functions.createobject(instance, np_class);
+	PLUGIN_DEBUG("Returning new scriptable package class: %p from instance %p with name %s\n", scriptable_object, instance, name);
+
+    ((IcedTeaScriptableJavaPackageObject*) scriptable_object)->setPackageName(name);
+
+    IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance);
+
+	return scriptable_object;
+}
+
+IcedTeaScriptableJavaPackageObject::IcedTeaScriptableJavaPackageObject(NPP instance)
+{
+    PLUGIN_DEBUG("Constructing new scriptable java package object\n");
+	this->instance = instance;
+	this->package_name = new std::string();
+}
+
+IcedTeaScriptableJavaPackageObject::~IcedTeaScriptableJavaPackageObject()
+{
+    delete this->package_name;
+}
+
+void
+IcedTeaScriptableJavaPackageObject::setPackageName(const NPUTF8* name)
+{
+    this->package_name->append(name);
+}
+
+std::string
+IcedTeaScriptableJavaPackageObject::getPackageName()
+{
+    return this->package_name->c_str();
+}
+
+void
+IcedTeaScriptableJavaPackageObject::deAllocate(NPObject *npobj)
+{
+    browser_functions.releaseobject(npobj);
+}
+
+void
+IcedTeaScriptableJavaPackageObject::invalidate(NPObject *npobj)
+{
+	// nothing to do for these
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::hasMethod(NPObject *npobj, NPIdentifier name)
+{
+    // Silly caller. Methods are for objects!
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+			uint32_t argCount,NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::invoke %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::invokeDefault(NPObject *npobj, const NPVariant *args,
+			       uint32_t argCount, NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::invokeDefault %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::hasProperty(NPObject *npobj, NPIdentifier name)
+{
+	PLUGIN_DEBUG("IcedTeaScriptableJavaPackageObject::hasProperty %s\n", browser_functions.utf8fromidentifier(name));
+
+	bool hasProperty = false;
+	JavaResultData* java_result;
+	JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+    int plugin_instance_id = get_id_from_instance(instance);
+
+	PLUGIN_DEBUG("Object package name: \"%s\"\n", ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().c_str());
+
+	// "^java" is always a package
+	if (((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().length() == 0 &&
+	    (  !strcmp(browser_functions.utf8fromidentifier(name), "java") ||
+	       !strcmp(browser_functions.utf8fromidentifier(name), "javax")))
+	{
+	    return true;
+	}
+
+	std::string property_name = ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName();
+	if (property_name.length() > 0)
+	    property_name += ".";
+	property_name += browser_functions.utf8fromidentifier(name);
+
+	PLUGIN_DEBUG("Looking for name \"%s\"\n", property_name.c_str());
+
+	java_result = java_request->hasPackage(plugin_instance_id, property_name);
+
+	if (!java_result->error_occurred && java_result->return_identifier != 0) hasProperty = true;
+
+	// No such package. Do we have a class with that name?
+	if (!hasProperty)
+	{
+		java_result = java_request->findClass(plugin_instance_id, property_name);
+	}
+
+	if (java_result->return_identifier != 0) hasProperty = true;
+
+	delete java_request;
+
+	return hasProperty;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
+{
+
+	PLUGIN_DEBUG("IcedTeaScriptableJavaPackageObject::getProperty %s\n", browser_functions.utf8fromidentifier(name));
+
+	if (!browser_functions.utf8fromidentifier(name))
+	    return false;
+
+	bool isPropertyClass = false;
+	JavaResultData* java_result;
+	JavaRequestProcessor java_request = JavaRequestProcessor();
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+    int plugin_instance_id = get_id_from_instance(instance);
+
+	std::string property_name = ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName();
+	if (property_name.length() > 0)
+	    property_name += ".";
+	property_name += browser_functions.utf8fromidentifier(name);
+
+	java_result = java_request.findClass(plugin_instance_id, property_name);
+	isPropertyClass = (java_result->return_identifier == 0);
+
+	//NPIdentifier property = browser_functions.getstringidentifier(property_name.c_str());
+
+	NPObject* obj;
+
+	if (isPropertyClass)
+	{
+		PLUGIN_DEBUG("Returning package object\n");
+		obj = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(
+                                  IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                                  property_name.c_str());
+	}
+	else
+	{
+		PLUGIN_DEBUG("Returning Java object\n");
+		obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+		                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+		                *(java_result->return_string), "0", false);
+	}
+
+	OBJECT_TO_NPVARIANT(obj, *result);
+
+	return true;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
+{
+	// Can't be going around setting properties on namespaces.. that's madness!
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::removeProperty(NPObject *npobj, NPIdentifier name)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::removeProperty %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::enumerate %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::construct(NPObject *npobj, const NPVariant *args, uint32_t argCount,
+	           NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::construct %p\n", npobj);
+	return false;
+}
+
+NPObject*
+allocate_scriptable_java_object(NPP npp, NPClass *aClass)
+{
+    PLUGIN_DEBUG("Allocating new scriptable Java object\n");
+    return new IcedTeaScriptableJavaObject(npp);
+}
+
+NPObject*
+IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(NPP instance,
+                                    std::string class_id,
+                                    std::string instance_id,
+                                    bool isArray)
+{
+    NPObject* scriptable_object;
+
+    std::string obj_key = std::string();
+    obj_key += class_id;
+    obj_key += ":";
+    obj_key += instance_id;
+
+    PLUGIN_DEBUG("get_scriptable_java_object searching for %s...\n", obj_key.c_str());
+    scriptable_object = IcedTeaPluginUtilities::getNPObjectFromJavaKey(obj_key);
+
+    if (scriptable_object != NULL)
+    {
+        PLUGIN_DEBUG("Returning existing object %p\n", scriptable_object);
+        browser_functions.retainobject(scriptable_object);
+        return scriptable_object;
+    }
+
+
+	NPClass* np_class = new NPClass();
+	np_class->structVersion = NP_CLASS_STRUCT_VERSION;
+	np_class->allocate = allocate_scriptable_java_object;
+	np_class->deallocate = IcedTeaScriptableJavaObject::deAllocate;
+	np_class->invalidate = IcedTeaScriptableJavaObject::invalidate;
+	np_class->hasMethod = IcedTeaScriptableJavaObject::hasMethod;
+	np_class->invoke = IcedTeaScriptableJavaObject::invoke;
+	np_class->invokeDefault = IcedTeaScriptableJavaObject::invokeDefault;
+	np_class->hasProperty = IcedTeaScriptableJavaObject::hasProperty;
+	np_class->getProperty = IcedTeaScriptableJavaObject::getProperty;
+	np_class->setProperty = IcedTeaScriptableJavaObject::setProperty;
+	np_class->removeProperty = IcedTeaScriptableJavaObject::removeProperty;
+	np_class->enumerate = IcedTeaScriptableJavaObject::enumerate;
+	np_class->construct = IcedTeaScriptableJavaObject::construct;
+
+	// try to create normally
+    scriptable_object =  browser_functions.createobject(instance, np_class);
+
+    // didn't work? try creating asynch
+    if (!scriptable_object)
+    {
+        AsyncCallThreadData thread_data = AsyncCallThreadData();
+        thread_data.result_ready = false;
+        thread_data.parameters = std::vector<void*>();
+        thread_data.result = std::string();
+
+        thread_data.parameters.push_back(instance);
+        thread_data.parameters.push_back(np_class);
+        thread_data.parameters.push_back(&scriptable_object);
+
+        IcedTeaPluginUtilities::callAndWaitForResult(instance, &_createAndRetainJavaObject, &thread_data);
+    } else
+    {
+        // Else retain object and continue
+        browser_functions.retainobject(scriptable_object);
+    }
+
+    PLUGIN_DEBUG("Constructed new Java Object with classid=%s, instanceid=%s, isArray=%d and scriptable_object=%p\n", class_id.c_str(), instance_id.c_str(), isArray, scriptable_object);
+
+	((IcedTeaScriptableJavaObject*) scriptable_object)->setClassIdentifier(class_id);
+    ((IcedTeaScriptableJavaObject*) scriptable_object)->setIsArray(isArray);
+
+	if (instance_id != "0")
+	    ((IcedTeaScriptableJavaObject*) scriptable_object)->setInstanceIdentifier(instance_id);
+
+	IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance);
+	IcedTeaPluginUtilities::storeObjectMapping(obj_key, scriptable_object);
+
+	PLUGIN_DEBUG("Inserting into object_map key %s->%p\n", obj_key.c_str(), scriptable_object);
+	return scriptable_object;
+}
+
+/* Creates and retains a scriptable java object (intended to be called asynch.) */
+void
+_createAndRetainJavaObject(void* data)
+{
+    PLUGIN_DEBUG("Asynchronously creating/retaining object ...\n");
+
+    std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters;
+    NPP instance = (NPP) parameters.at(0);
+    NPClass* np_class = (NPClass*) parameters.at(1);
+    NPObject** scriptable_object = (NPObject**) parameters.at(2);
+
+    *scriptable_object = browser_functions.createobject(instance, np_class);
+    browser_functions.retainobject(*scriptable_object);
+
+    ((AsyncCallThreadData*) data)->result_ready = true;
+}
+
+bool
+IcedTeaScriptableJavaPackageObject::is_valid_java_object(NPObject* object_ptr) {
+    return IcedTeaPluginUtilities::getInstanceFromMemberPtr(object_ptr) != NULL;
+}
+
+IcedTeaScriptableJavaObject::IcedTeaScriptableJavaObject(NPP instance)
+{
+	this->instance = instance;
+	this->class_id = new std::string();
+	this->instance_id = new std::string();
+}
+
+IcedTeaScriptableJavaObject::~IcedTeaScriptableJavaObject()
+{
+	delete this->class_id;
+	delete this->instance_id;
+}
+
+void
+IcedTeaScriptableJavaObject::setClassIdentifier(std::string class_id)
+{
+	this->class_id->append(class_id);
+}
+
+void
+IcedTeaScriptableJavaObject::setInstanceIdentifier(std::string instance_id)
+{
+	this->instance_id->append(instance_id);
+}
+
+void
+IcedTeaScriptableJavaObject::setIsArray(bool isArray)
+{
+    this->isObjectArray = isArray;
+}
+
+void
+IcedTeaScriptableJavaObject::deAllocate(NPObject *npobj)
+{
+	browser_functions.releaseobject(npobj);
+}
+
+void
+IcedTeaScriptableJavaObject::invalidate(NPObject *npobj)
+{
+	IcedTeaPluginUtilities::removeInstanceID(npobj);
+
+	std::string obj_key = std::string();
+	obj_key += ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+	obj_key += ":";
+	obj_key += ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+
+	IcedTeaPluginUtilities::removeObjectMapping(obj_key);
+}
+
+bool
+IcedTeaScriptableJavaObject::hasMethod(NPObject *npobj, NPIdentifier name)
+{
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasMethod %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+    bool hasMethod = false;
+
+    // If object is an array and requested "method" may be a number, check for it first
+    if ( !((IcedTeaScriptableJavaObject*) npobj)->isArray()  ||
+         (browser_functions.intfromidentifier(name) < 0))
+    {
+
+        if (!browser_functions.utf8fromidentifier(name))
+            return false;
+
+        JavaResultData* java_result;
+        JavaRequestProcessor java_request = JavaRequestProcessor();
+
+        std::string classId = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
+        std::string methodName = browser_functions.utf8fromidentifier(name);
+
+        java_result = java_request.hasMethod(classId, methodName);
+        hasMethod = java_result->return_identifier != 0;
+    }
+
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasMethod returning %d\n", hasMethod);
+    return hasMethod;
+}
+
+bool
+IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+			uint32_t argCount, NPVariant *result)
+{
+    NPUTF8* method_name = browser_functions.utf8fromidentifier(name);
+
+    // Extract arg type array
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::invoke %s. Args follow.\n", method_name);
+    for (int i=0; i < argCount; i++)
+    {
+        IcedTeaPluginUtilities::printNPVariant(args[i]);
+    }
+
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+    std::string callee;
+    std::string source;
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
+    // First, load the arguments into the java-side table
+    std::string id = std::string();
+    std::vector<std::string> arg_ids = std::vector<std::string>();
+    for (int i=0; i < argCount; i++) {
+        id.clear();
+        createJavaObjectFromVariant(instance, args[i], &id);
+
+        if (id == "-1")
+        {
+            printf("Unable to create arguments on Java side\n");
+            return false;
+        }
+
+        arg_ids.push_back(id);
+    }
+
+    if (instance_id.length() == 0) // Static
+    {
+        PLUGIN_DEBUG("Calling static method\n");
+        callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+        java_result = java_request.callStaticMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), arg_ids);
+    } else
+    {
+        PLUGIN_DEBUG("Calling method normally\n");
+        callee = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+        java_result = java_request.callMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), arg_ids);
+    }
+
+    if (java_result->error_occurred)
+    {
+        // error message must be allocated on heap
+        char* error_msg = (char*) malloc(java_result->error_msg->length()*sizeof(char));
+        strcpy(error_msg, java_result->error_msg->c_str());
+        browser_functions.setexception(npobj, error_msg);
+        return false;
+    }
+
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::invoke converting and returning.\n");
+    return IcedTeaPluginUtilities::javaResultToNPVariant(instance, java_result->return_string, result);
+}
+
+bool
+IcedTeaScriptableJavaObject::invokeDefault(NPObject *npobj, const NPVariant *args,
+			       uint32_t argCount, NPVariant *result)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaObject::invokeDefault %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaObject::hasProperty(NPObject *npobj, NPIdentifier name)
+{
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasProperty %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+    bool hasProperty = false;
+
+    // If it is an array, only length and indexes are valid
+    if (((IcedTeaScriptableJavaObject*) npobj)->isArray())
+    {
+        if (browser_functions.intfromidentifier(name) >= 0 ||
+            !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+            hasProperty = true;
+
+    } else
+    {
+
+        if (!browser_functions.utf8fromidentifier(name))
+            return false;
+
+        if (!strcmp(browser_functions.utf8fromidentifier(name), "Packages"))
+        {
+            hasProperty = true;
+        } else {
+
+            JavaResultData* java_result;
+            JavaRequestProcessor java_request = JavaRequestProcessor();
+
+            std::string class_id = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
+            std::string fieldName = browser_functions.utf8fromidentifier(name);
+
+            java_result = java_request.hasField(class_id, fieldName);
+
+            hasProperty = java_result->return_identifier != 0;
+        }
+    }
+
+	PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasProperty returning %d\n", hasProperty);
+	return hasProperty;
+}
+
+bool
+IcedTeaScriptableJavaObject::getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
+{
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::getProperty %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+
+    bool isPropertyClass = false;
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+    NPP instance = ((IcedTeaScriptableJavaObject*) npobj)->getInstance();
+
+    if (instance_id.length() > 0) // Could be an array or a simple object
+    {
+        // If array and requesting length
+        if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+             browser_functions.utf8fromidentifier(name) &&
+             !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+        {
+            java_result = java_request.getArrayLength(instance_id);
+        } else if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+                    browser_functions.intfromidentifier(name) >= 0) // else if array and requesting index
+        {
+
+            java_result = java_request.getArrayLength(instance_id);
+            if (java_result->error_occurred)
+            {
+                printf("ERROR: Couldn't fetch array length\n");
+                return false;
+            }
+
+            int length = atoi(java_result->return_string->c_str());
+
+            // Access beyond size?
+            if (browser_functions.intfromidentifier(name) >= length)
+            {
+                VOID_TO_NPVARIANT(*result);
+                return true;
+            }
+
+            std::string index = std::string();
+            IcedTeaPluginUtilities::itoa(browser_functions.intfromidentifier(name), &index);
+            java_result = java_request.getSlot(instance_id, index);
+
+        } else // Everything else
+        {
+            if (!browser_functions.utf8fromidentifier(name))
+                return false;
+
+            if (!strcmp(browser_functions.utf8fromidentifier(name), "Packages"))
+            {
+                NPObject* pkgObject = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(instance, "");
+                OBJECT_TO_NPVARIANT(pkgObject, *result);
+                return true;
+            }
+
+            java_result = java_request.getField(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        class_id, instance_id, browser_functions.utf8fromidentifier(name));
+        }
+    }
+    else
+    {
+        if (!browser_functions.utf8fromidentifier(name))
+            return true;
+
+        java_result = java_request.getStaticField(
+                                IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                                class_id, browser_functions.utf8fromidentifier(name));
+    }
+
+    if (java_result->error_occurred)
+    {
+        return false;
+    }
+
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::getProperty converting and returning.\n");
+    return IcedTeaPluginUtilities::javaResultToNPVariant(instance, java_result->return_string, result);
+}
+
+bool
+IcedTeaScriptableJavaObject::setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
+{
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::setProperty %s (ival=%d) to:\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+    IcedTeaPluginUtilities::printNPVariant(*value);
+
+    bool isPropertyClass = false;
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
+    if (instance_id.length() > 0) // Could be an array or a simple object
+    {
+        // If array
+        if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+             browser_functions.utf8fromidentifier(name) &&
+             !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+        {
+            printf("ERROR: Array length is not a modifiable property\n");
+            return false;
+        } else if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+                    browser_functions.intfromidentifier(name) >= 0) // else if array and requesting index
+        {
+
+            java_result = java_request.getArrayLength(instance_id);
+            if (java_result->error_occurred)
+            {
+                printf("ERROR: Couldn't fetch array length\n");
+                return false;
+            }
+
+            int length = atoi(java_result->return_string->c_str());
+
+            // Access beyond size?
+            if (browser_functions.intfromidentifier(name) >= length)
+            {
+                return true;
+            }
+
+            std::string index = std::string();
+            IcedTeaPluginUtilities::itoa(browser_functions.intfromidentifier(name), &index);
+
+            std::string value_id = std::string();
+            createJavaObjectFromVariant(instance, *value, &value_id);
+
+            java_result = java_request.setSlot(instance_id, index, value_id);
+
+        } else // Everything else
+        {
+            std::string value_id = std::string();
+            createJavaObjectFromVariant(instance, *value, &value_id);
+
+            java_result = java_request.setField(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        class_id, instance_id, browser_functions.utf8fromidentifier(name), value_id);
+        }
+    }
+    else
+    {
+        std::string value_id = std::string();
+        createJavaObjectFromVariant(instance, *value, &value_id);
+
+        java_result = java_request.setStaticField(
+                                IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                                class_id, browser_functions.utf8fromidentifier(name), value_id);
+    }
+
+    if (java_result->error_occurred)
+    {
+        return false;
+    }
+
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::setProperty returning.\n");
+    return true;
+}
+
+bool
+IcedTeaScriptableJavaObject::removeProperty(NPObject *npobj, NPIdentifier name)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaObject::removeProperty %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaObject::enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
+{
+	printf ("** Unimplemented: IcedTeaScriptableJavaObject::enumerate %p\n", npobj);
+	return false;
+}
+
+bool
+IcedTeaScriptableJavaObject::construct(NPObject *npobj, const NPVariant *args, uint32_t argCount,
+	           NPVariant *result)
+{
+    // Extract arg type array
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::construct %s. Args follow.\n", ((IcedTeaScriptableJavaObject*) npobj)->getClassID().c_str());
+    for (int i=0; i < argCount; i++)
+    {
+        IcedTeaPluginUtilities::printNPVariant(args[i]);
+    }
+
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
+    // First, load the arguments into the java-side table
+    std::string id = std::string();
+    std::vector<std::string> arg_ids = std::vector<std::string>();
+    for (int i=0; i < argCount; i++) {
+        id.clear();
+        createJavaObjectFromVariant(instance, args[i], &id);
+        if (id == "0")
+        {
+            // error message must be allocated on heap
+            char* error_msg = (char*) malloc(1024*sizeof(char));
+            strcpy(error_msg, "Unable to create argument on Java side");
+
+            browser_functions.setexception(npobj, error_msg);
+            return false;
+        }
+
+        arg_ids.push_back(id);
+    }
+
+    java_result = java_request.newObject(
+                            IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                            class_id,
+                            arg_ids);
+
+    if (java_result->error_occurred)
+    {
+        // error message must be allocated on heap
+        int length = java_result->error_msg->length();
+        char* error_msg = (char*) malloc((length+1)*sizeof(char));
+        strcpy(error_msg, java_result->error_msg->c_str());
+
+        browser_functions.setexception(npobj, error_msg);
+        return false;
+    }
+
+    std::string return_obj_instance_id = std::string();
+    std::string return_obj_class_id = class_id;
+    return_obj_instance_id.append(*(java_result->return_string));
+
+    obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                                return_obj_class_id, return_obj_instance_id, false);
+
+    OBJECT_TO_NPVARIANT(obj, *result);
+
+    PLUGIN_DEBUG("IcedTeaScriptableJavaObject::construct returning.\n");
+    return true;
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/IcedTeaScriptablePluginObject.h	(revision 403)
@@ -0,0 +1,212 @@
+/* IcedTeaScriptablePluginObject.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __ICEDTEASCRIPTABLEPLUGINOBJECT_H_
+#define __ICEDTEASCRIPTABLEPLUGINOBJECT_H_
+
+#if MOZILLA_VERSION_COLLAPSED < 1090100
+#include "npupp.h"
+#else
+#include <npapi.h>
+#include <npruntime.h>
+#endif
+
+#include "IcedTeaJavaRequestProcessor.h"
+#include "IcedTeaNPPlugin.h"
+
+/**
+ * IcedTeaScriptablePluginObject, an extended NPObject that implements
+ * static functions whose pointers are supplied to NPClass.
+ */
+
+class IcedTeaScriptablePluginObject: public NPObject
+{
+
+    private:
+    	NPP instance;
+
+    public:
+        IcedTeaScriptablePluginObject(NPP instance);
+
+        static void deAllocate(NPObject *npobj);
+
+        static void invalidate(NPObject *npobj);
+
+        static bool hasMethod(NPObject *npobj, NPIdentifier name);
+
+        static bool invoke(NPObject *npobj, NPIdentifier name,
+                const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+        static bool invokeDefault(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+
+        static bool hasProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool getProperty(NPObject *npobj, NPIdentifier name,
+                NPVariant *result);
+
+        static bool setProperty(NPObject *npobj, NPIdentifier name,
+                const NPVariant *value);
+
+        static bool removeProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool enumerate(NPObject *npobj, NPIdentifier **value,
+                uint32_t *count);
+
+        static bool construct(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+
+        static NPObject* get_scriptable_java_package_object(NPP instance, const NPUTF8* name);
+};
+
+NPObject* allocate_scriptable_jp_object(NPP npp, NPClass *aClass);
+
+class IcedTeaScriptableJavaPackageObject: public NPObject
+{
+
+    private:
+    	NPP instance;
+    	std::string* package_name;
+
+    public:
+    	IcedTeaScriptableJavaPackageObject(NPP instance);
+
+    	~IcedTeaScriptableJavaPackageObject();
+
+    	void setPackageName(const NPUTF8* name);
+
+    	std::string getPackageName();
+
+        static void deAllocate(NPObject *npobj);
+
+        static void invalidate(NPObject *npobj);
+
+        static bool hasMethod(NPObject *npobj, NPIdentifier name);
+
+        static bool invoke(NPObject *npobj, NPIdentifier name,
+                const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+        static bool invokeDefault(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+
+        static bool hasProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool getProperty(NPObject *npobj, NPIdentifier name,
+                NPVariant *result);
+
+        static bool setProperty(NPObject *npobj, NPIdentifier name,
+                const NPVariant *value);
+
+        static bool removeProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool enumerate(NPObject *npobj, NPIdentifier **value,
+                uint32_t *count);
+
+        static bool construct(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+
+        static NPObject* get_scriptable_java_object(NPP instance,
+                                                    std::string class_id,
+                                                    std::string instance_id,
+                                                    bool isArray);
+
+        static bool is_valid_java_object(NPObject* object_ptr);
+};
+
+class IcedTeaScriptableJavaObject: public NPObject
+{
+
+    private:
+    	NPP instance;
+    	bool isObjectArray;
+    	std::string* class_id;
+    	std::string* instance_id;
+
+    public:
+    	IcedTeaScriptableJavaObject(NPP instance);
+
+    	~IcedTeaScriptableJavaObject();
+
+    	void setClassIdentifier(std::string class_id);
+
+    	void setInstanceIdentifier(std::string instance_id);
+
+    	void setIsArray(bool isArray);
+
+    	std::string getClassID() { return *class_id; }
+
+    	std::string getInstanceID() { return *instance_id; }
+
+    	NPP getInstance() { return instance; }
+
+    	bool isArray() { return isObjectArray; }
+
+        static void deAllocate(NPObject *npobj);
+
+        static void invalidate(NPObject *npobj);
+
+        static bool hasMethod(NPObject *npobj, NPIdentifier name);
+
+        static bool invoke(NPObject *npobj, NPIdentifier name,
+                const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+        static bool invokeDefault(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+
+        static bool hasProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool getProperty(NPObject *npobj, NPIdentifier name,
+                NPVariant *result);
+
+        static bool setProperty(NPObject *npobj, NPIdentifier name,
+                const NPVariant *value);
+
+        static bool removeProperty(NPObject *npobj, NPIdentifier name);
+
+        static bool enumerate(NPObject *npobj, NPIdentifier **value,
+                uint32_t *count);
+
+        static bool construct(NPObject *npobj, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
+};
+
+/* Creates and retains a scriptable java object (intended to be called asynch.) */
+
+void _createAndRetainJavaObject(void* data);
+
+#endif /* __ICEDTEASCRIPTABLEPLUGINOBJECT_H_ */
Index: /tags/icedtea-web/beta/plugin/icedteanp/Makefile.kmk
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/Makefile.kmk	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/Makefile.kmk	(revision 403)
@@ -0,0 +1,116 @@
+## @file
+#
+
+SUB_DEPTH = ../..
+include $(KBUILD_PATH)/subheader.kmk
+
+PLUGIN_NAME     = IcedTea-Web Plugin
+PLUGIN_VERSION  = IcedTea-Web $(FULL_VERSION)
+
+#
+# Plugin DLL
+#
+
+DLLS               += npicedt
+npicedt_TEMPLATE    = Cxx
+npicedt_INCS        = . $(PATH_MOZILLA_INCS) $(PATH_GLIB_INCS)
+npicedt_INCS.os2    = os2
+npicedt_DEFS        = MOZILLA_VERSION_COLLAPSED=$(MOZILLA_VERSION_COLLAPSED) \
+                      DETECT_DATA_DIR=$(DETECT_DATA_DIR) \
+                      DETECT_JRE_DIR=$(DETECT_JRE_DIR) \
+                      WITHOUT_GTK
+npicedt_CXXFLAGS    = -DJDK_UPDATE_VERSION="\"$(JDK_UPDATE_VERSION)\"" \
+                      -DPLUGIN_NAME="\"$(PLUGIN_NAME)\"" \
+                      -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \
+                      -DPACKAGE_URL="\"$(PACKAGE_URL)\"" \
+                      $(if $(ICEDTEA_WEB_JRE_DIR),-DICEDTEA_WEB_JRE_DIR="\"$(ICEDTEA_WEB_JRE_DIR)\"") \
+                      -DICEDTEA_WEB_JRE="$(ICEDTEA_WEB_JRE)" \
+                      $(if $(ICEDTEA_WEB_DATA_DIR),-DICEDTEA_WEB_DATA_DIR="\"$(ICEDTEA_WEB_DATA_DIR)\"") \
+                      -DPLUGIN_BOOTCLASSPATH="$(PLUGIN_BOOTCLASSPATH)"
+npicedt_LIBS        = $(PATH_GLIB_LIBS) pthread
+npicedt_LIBS.os2    = kernel32.lib user32.lib
+npicedt_LIBPATH     = $(PATH_GLIB_LIBPATH)
+npicedt_LIBPATH.os2 = kernel32.lib user32.lib $(SDK_ODIN_LIBPATH)
+
+npicedt_SOURCES     = \
+    IcedTeaNPPlugin.cc \
+    IcedTeaScriptablePluginObject.cc \
+    IcedTeaJavaRequestProcessor.cc \
+    IcedTeaPluginRequestProcessor.cc \
+    IcedTeaPluginUtils.cc
+
+npicedt_SOURCES.os2 = \
+    os2/OS_OS2.cc \
+    os2/OS_OS2_WinOS2.cc \
+    $(PATH_ROOT)/plugin_os2.def
+
+os2/OS_OS2_WinOS2.cc_SDKS.os2 += ODIN
+
+PLUGIN_RC           = $(npicedt_0_OUTDIR)/plugin_os2.rc
+OTHER_CLEAN        += $(PLUGIN_RC)
+npicedt_SOURCES    += $(PLUGIN_RC)
+
+$$(PLUGIN_RC): $(PATH_ROOT)/plugin_os2.rc.in | $$(call DIRDEP,$$(dir $$(@)))
+	sed " \
+        s/@PLUGIN_NAME@/$(PLUGIN_NAME)/g; \
+        s/@PLUGIN_VERSION@/$(PLUGIN_VERSION)/g; \
+        s/@PACKAGE_VER_MAJOR@/$(PACKAGE_VER_MAJOR)/g; \
+        s/@PACKAGE_VER_MINOR@/$(PACKAGE_VER_MINOR)/g; \
+        s/@PACKAGE_VER_PATCH@/$(PACKAGE_VER_PATCH)/g; \
+        s/@PACKAGE_VER_PATCH@/$(PACKAGE_VER_PATCH)/g; \
+        s/@TIMESTAMP@/$(TIMESTAMP)/g; \
+        s/@HOSTNAME@/$(HOSTNAME)/g; \
+        s/@BUILDDATE@/$(shell LANG=C date '+%d %b %Y %T')   /g; \
+        " < $^ > $@
+
+#
+# Plugin JAR
+#
+
+OTHERS += liveconnect
+BLDDIRS += $(liveconnect_0_OUTDIR)
+
+liveconnect_JAVASRCDIRS := $(PATH_SUB_CURRENT)/java
+ifeq ($(KBUILD_TARGET),os2)
+liveconnect_JAVASRCDIRS += $(PATH_SUB_CURRENT)/os2/java
+else # assume Linux
+liveconnect_JAVASRCDIRS += $(PATH_SUB_CURRENT)/x11/java
+endif
+
+liveconnect_JAVASRCLIST = $(liveconnect_0_OUTDIR)/javasrc.list
+BLDDIRS += $(dir $(liveconnect_JAVASRCLIST))
+OTHER_CLEAN += $(liveconnect_JAVASRCLIST) $(liveconnect_JAVASRCLIST).stamp
+
+liveconnect_JARFILE = $(PATH_STAGE)/lib/plugin.jar
+BLDDIRS += $(dir $(liveconnect_JARFILE))
+OTHER_CLEAN += $(liveconnect_JARFILE)
+
+$$(liveconnect_JAVASRCLIST): $(MAKEFILE) | $$(call DIRDEP,$$(dir $$(@)))
+	@echo 'JAVASRC = \' > $@
+	find $(liveconnect_JAVASRCDIRS) -name '*.java' \
+        -printf '%p \\\n' >> $@
+
+$$(liveconnect_JAVASRCLIST).stamp: $$(JAVASRC) | $(PATH_STAGE)/lib/netx.jar $$(call DIRDEP,$$(dir $$(@)))
+	$(call MSG_COMPILE,liveconnect,$(words $?) sources,$@,JAVA)
+	@echo $? > $(liveconnect_JAVASRCLIST).rsp
+	$(PATH_BOOTSTRAP_JDK)/bin/javac $(IT_JAVACFLAGS) \
+        -d "$(liveconnect_0_OUTDIR)" \
+        -classpath "$(liveconnect_0_OUTDIR)" \
+        -sourcepath "$(subst ; ,;,$(foreach d,$(liveconnect_JAVASRCDIRS),$(d);))" \
+        -bootclasspath "$(BOOTSTRAP_JDK_RUNTIME);$(PATH_STAGE)/lib/netx.jar" \
+        @"$(liveconnect_JAVASRCLIST).rsp"
+	@$(RM) "$(liveconnect_JAVASRCLIST).rsp"
+	@touch "$@"
+
+$$(liveconnect_JARFILE): $$(liveconnect_JAVASRCLIST).stamp | $$(call DIRDEP,$$(dir $$(@)))
+	(cd $(liveconnect_0_OUTDIR); \
+        $(PATH_BOOTSTRAP_JDK)/bin/jar cf $(liveconnect_JARFILE) \
+            netscape sun/applet)
+
+liveconnect: $$(liveconnect_JARFILE)
+
+install:: liveconnect
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
+-include $(liveconnect_JAVASRCLIST)
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSException.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSException.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSException.java	(revision 403)
@@ -0,0 +1,141 @@
+/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package netscape.javascript;
+
+/**
+ * JSException is an exception which is thrown when JavaScript code
+ * returns an error.
+ */
+
+public class JSException extends RuntimeException {
+    public static final int EXCEPTION_TYPE_EMPTY = -1;
+    public static final int EXCEPTION_TYPE_VOID = 0;
+    public static final int EXCEPTION_TYPE_OBJECT = 1;
+    public static final int EXCEPTION_TYPE_FUNCTION = 2;
+    public static final int EXCEPTION_TYPE_STRING = 3;
+    public static final int EXCEPTION_TYPE_NUMBER = 4;
+    public static final int EXCEPTION_TYPE_BOOLEAN = 5;
+    public static final int EXCEPTION_TYPE_ERROR = 6;
+
+    public String filename;
+    public int lineno;
+    public String source;
+    public int tokenIndex;
+    public int wrappedExceptionType;
+    public Object wrappedException;
+
+    /**
+     * Constructs a JSException without a detail message.
+     * A detail message is a String that describes this particular exception.
+     *
+     * @deprecated Not for public use in future versions.
+     */
+    @Deprecated
+    public JSException() {
+        super();
+        filename = "unknown";
+        lineno = 0;
+        source = "";
+        tokenIndex = 0;
+        wrappedExceptionType = EXCEPTION_TYPE_EMPTY;
+    }
+
+    /**
+     * Constructs a JSException with a detail message.
+     * A detail message is a String that describes this particular exception.
+     * @param s the detail message
+     *
+     * @deprecated Not for public use in future versions.
+     */
+    @Deprecated
+    public JSException(String s) {
+        super(s);
+        filename = "unknown";
+        lineno = 0;
+        source = "";
+        tokenIndex = 0;
+        wrappedExceptionType = EXCEPTION_TYPE_EMPTY;
+    }
+
+    /**
+     * Constructs a JSException with a wrapped JavaScript exception object.
+     * This constructor needs to be public so that Java users can throw
+     * exceptions to JS cleanly.
+     */
+    public JSException(int wrappedExceptionType, Object wrappedException) {
+        super();
+        this.wrappedExceptionType = wrappedExceptionType;
+        this.wrappedException = wrappedException;
+    }
+
+    /**
+     * Constructs a JSException with a detail message and all the
+     * other info that usually comes with a JavaScript error.
+     * @param s the detail message
+     *
+     * @deprecated Not for public use in future versions.
+     */
+    @Deprecated
+    public JSException(String s, String filename, int lineno,
+                       String source, int tokenIndex) {
+        super(s);
+        this.filename = filename;
+        this.lineno = lineno;
+        this.source = source;
+        this.tokenIndex = tokenIndex;
+        wrappedExceptionType = EXCEPTION_TYPE_EMPTY;
+    }
+
+    /**
+     * Instance method getWrappedExceptionType returns the int mapping of the
+     * type of the wrappedException Object.
+     */
+    public int getWrappedExceptionType() {
+        return wrappedExceptionType;
+    }
+
+    /**
+     * Instance method getWrappedException.
+     */
+    public Object getWrappedException() {
+        return wrappedException;
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObject.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObject.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObject.java	(revision 403)
@@ -0,0 +1,266 @@
+/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* more doc TODO:
+ *  threads
+ *  gc
+ *
+ *
+ */
+
+package netscape.javascript;
+
+import java.applet.Applet;
+import java.security.AccessControlException;
+import java.security.AccessController;
+
+import sun.applet.PluginAppletViewer;
+import sun.applet.PluginDebug;
+
+/**
+ * JSObject allows Java to manipulate objects that are
+ * defined in JavaScript.
+ * Values passed from Java to JavaScript are converted as
+ * follows:<ul>
+ * <li>JSObject is converted to the original JavaScript object
+ * <li>Any other Java object is converted to a JavaScript wrapper,
+ *   which can be used to access methods and fields of the java object.
+ *   Converting this wrapper to a string will call the toString method
+ *   on the original object, converting to a number will call the
+ *   doubleValue method if possible and fail otherwise.  Converting
+ *   to a boolean will try to call the booleanValue method in the
+ *   same way.
+ * <li>Java arrays are wrapped with a JavaScript object that understands
+ *   array.length and array[index]
+ * <li>A Java boolean is converted to a JavaScript boolean
+ * <li>Java byte, char, short, int, long, float, and double are converted
+ *   to JavaScript numbers
+ * </ul>
+ * Values passed from JavaScript to Java are converted as follows:<ul>
+ * <li>objects which are wrappers around java objects are unwrapped
+ * <li>other objects are wrapped with a JSObject
+ * <li>strings, numbers and booleans are converted to String, Double,
+ *   and Boolean objects respectively
+ * </ul>
+ * This means that all JavaScript values show up as some kind
+ * of java.lang.Object in Java.  In order to make much use of them,
+ * you will have to cast them to the appropriate subclass of Object,
+ * e.g. <code>(String) window.getMember("name");</code> or
+ * <code>(JSObject) window.getMember("document");</code>.
+ */
+public final class JSObject {
+    /* the internal object data */
+    private long internal;
+
+    /**
+     * initialize
+     */
+    private static void initClass() {
+        PluginDebug.debug("JSObject.initClass");
+    }
+
+    static {
+        PluginDebug.debug("JSObject INITIALIZER");
+    }
+
+    /**
+     * it is illegal to construct a JSObject manually
+     */
+    public JSObject(int jsobj_addr) {
+        this((long) jsobj_addr);
+    }
+
+    /**
+     * it is illegal to construct a JSObject manually
+     */
+    public JSObject(String jsobj_addr) {
+        this(Long.parseLong(jsobj_addr));
+    }
+
+    public JSObject(long jsobj_addr) {
+
+        // See if the caller has permission
+
+        try {
+            AccessController.getContext().checkPermission(new JSObjectCreatePermission());
+        } catch (AccessControlException ace) {
+
+            // If not, only caller with JSObject.getWindow on the stack may
+            // make this call unprivileged.
+
+            // Although this check is inefficient, it should happen only once
+            // during applet init, so we look the other way
+
+            StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+            boolean mayProceed = false;
+
+            for (int i = 0; i < stack.length; i++) {
+                if (stack[i].getClassName().equals("netscape.javascript.JSObject") &&
+                        stack[i].getMethodName().equals("getWindow")) {
+                    mayProceed = true;
+                }
+            }
+
+            if (!mayProceed)
+                throw ace;
+        }
+
+        PluginDebug.debug("JSObject long CONSTRUCTOR");
+        internal = jsobj_addr;
+    }
+
+    /**
+     * Retrieves a named member of a JavaScript object.
+     * Equivalent to "this.<i>name</i>" in JavaScript.
+     */
+    public Object getMember(String name) {
+        PluginDebug.debug("JSObject.getMember ", name);
+
+        Object o = PluginAppletViewer.getMember(internal, name);
+        PluginDebug.debug("JSObject.getMember GOT ", o);
+        return o;
+    }
+
+    /**
+     * Retrieves an indexed member of a JavaScript object.
+     * Equivalent to "this[<i>index</i>]" in JavaScript.
+     */
+    //    public Object         getMember(int index) { return getSlot(index); }
+    public Object getSlot(int index) {
+        PluginDebug.debug("JSObject.getSlot ", index);
+
+        return PluginAppletViewer.getSlot(internal, index);
+    }
+
+    /**
+     * Sets a named member of a JavaScript object.
+     * Equivalent to "this.<i>name</i> = <i>value</i>" in JavaScript.
+     */
+    public void setMember(String name, Object value) {
+        PluginDebug.debug("JSObject.setMember ", name, " ", value);
+
+        PluginAppletViewer.setMember(internal, name, value);
+    }
+
+    /**
+     * Sets an indexed member of a JavaScript object.
+     * Equivalent to "this[<i>index</i>] = <i>value</i>" in JavaScript.
+     */
+    //    public void           setMember(int index, Object value) {
+    //        setSlot(index, value);
+    //    }
+    public void setSlot(int index, Object value) {
+        PluginDebug.debug("JSObject.setSlot ", index, " ", value);
+
+        PluginAppletViewer.setSlot(internal, index, value);
+    }
+
+    /**
+     * Removes a named member of a JavaScript object.
+     */
+    public void removeMember(String name) {
+        PluginDebug.debug("JSObject.removeMember ", name);
+
+        PluginAppletViewer.removeMember(internal, name);
+    }
+
+    /**
+     * Calls a JavaScript method.
+     * Equivalent to "this.<i>methodName</i>(<i>args</i>[0], <i>args</i>[1], ...)" in JavaScript.
+     */
+    public Object call(String methodName, Object args[]) {
+        if (args == null)
+            args = new Object[0];
+
+        PluginDebug.debug("JSObject.call ", methodName);
+        for (int i = 0; i < args.length; i++)
+            PluginDebug.debug(" ", args[i]);
+        PluginDebug.debug("");
+        return PluginAppletViewer.call(internal, methodName, args);
+    }
+
+    /**
+     * Evaluates a JavaScript expression. The expression is a string
+     * of JavaScript source code which will be evaluated in the context
+     * given by "this".
+     */
+    public Object eval(String s) {
+        PluginDebug.debug("JSObject.eval ", s);
+        return PluginAppletViewer.eval(internal, s);
+    }
+
+    /**
+     * Converts a JSObject to a String.
+     */
+    public String toString() {
+        PluginDebug.debug("JSObject.toString");
+        return PluginAppletViewer.javascriptToString(internal);
+    }
+
+    // should use some sort of identifier rather than String
+    // is "property" the right word?
+    //    native String[]                         listProperties();
+
+    /**
+     * get a JSObject for the window containing the given applet
+     */
+    public static JSObject getWindow(Applet applet) {
+        PluginDebug.debug("JSObject.getWindow");
+        // FIXME: handle long case as well.
+        long internal = 0;
+        internal = ((PluginAppletViewer)
+                    applet.getAppletContext()).getWindow();
+        PluginDebug.debug("GOT IT: ", internal);
+        return new JSObject(internal);
+    }
+
+    /**
+     * Finalization decrements the reference count on the corresponding
+     * JavaScript object.
+     */
+    protected void finalize() {
+
+        // Proceed if this is a valid object (0L == default long == invalid)
+        if (internal == 0L)
+            return;
+
+        PluginDebug.debug("JSObject.finalize ");
+        PluginAppletViewer.JavaScriptFinalize(internal);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObjectCreatePermission.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObjectCreatePermission.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSObjectCreatePermission.java	(revision 403)
@@ -0,0 +1,46 @@
+/* JSObjectCreatePermission.java
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package netscape.javascript;
+
+import java.security.BasicPermission;
+
+public class JSObjectCreatePermission extends BasicPermission {
+    public JSObjectCreatePermission() {
+        super("JSObjectCreate");
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSProxy.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSProxy.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSProxy.java	(revision 403)
@@ -0,0 +1,67 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The JSProxy interface allows applets and plugins to
+ * share javascript contexts.
+ */
+
+package netscape.javascript;
+
+import java.applet.Applet;
+
+public interface JSProxy {
+    Object getMember(JSObject jso, String name);
+
+    Object getSlot(JSObject jso, int index);
+
+    void setMember(JSObject jso, String name, Object value);
+
+    void setSlot(JSObject jso, int index, Object value);
+
+    void removeMember(JSObject jso, String name);
+
+    Object call(JSObject jso, String methodName, Object args[]);
+
+    Object eval(JSObject jso, String s);
+
+    String toString(JSObject jso);
+
+    JSObject getWindow(Applet applet);
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSRunnable.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSRunnable.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSRunnable.java	(revision 403)
@@ -0,0 +1,72 @@
+/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package netscape.javascript;
+
+import sun.applet.PluginDebug;
+
+/**
+ * Runs a JavaScript object with a run() method in a separate thread.
+ */
+public class JSRunnable implements Runnable {
+    private JSObject runnable;
+
+    public JSRunnable(JSObject runnable) {
+        this.runnable = runnable;
+        synchronized (this) {
+            new Thread(this).start();
+            try {
+                this.wait();
+            } catch (InterruptedException ie) {
+            }
+        }
+    }
+
+    public void run() {
+        try {
+            runnable.call("run", null);
+            synchronized (this) {
+                notifyAll();
+            }
+        } catch (Throwable t) {
+            PluginDebug.debug(t.toString());
+            t.printStackTrace(System.err);
+        }
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSUtil.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSUtil.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/javascript/JSUtil.java	(revision 403)
@@ -0,0 +1,60 @@
+/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/* ** */
+
+package netscape.javascript;
+
+import java.io.*;
+
+public class JSUtil {
+
+    /* Return the stack trace of an exception or error as a String */
+    public static String getStackTrace(Throwable t) {
+        ByteArrayOutputStream captureStream;
+        PrintWriter p;
+
+        captureStream = new ByteArrayOutputStream();
+        p = new PrintWriter(captureStream);
+
+        t.printStackTrace(p);
+        p.flush();
+
+        return captureStream.toString();
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/ForbiddenTargetException.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/ForbiddenTargetException.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/ForbiddenTargetException.java	(revision 403)
@@ -0,0 +1,52 @@
+/* ForbiddenTargetException.java
+   Copyright (C) 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package netscape.security;
+
+public class ForbiddenTargetException extends RuntimeException {
+
+    private static final long serialVersionUID = 1271219852541058396L;
+
+    public ForbiddenTargetException() {
+        super();
+    }
+
+    public ForbiddenTargetException(String s) {
+        super(s);
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/PrivilegeManager.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/PrivilegeManager.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/netscape/security/PrivilegeManager.java	(revision 403)
@@ -0,0 +1,75 @@
+/*
+   PrivilegeManager.java
+   Copyright (C) 2011  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. 
+*/
+
+/**
+ *
+ * This class does not implement any functionality and exists for backward 
+ * compatibility only.
+ *
+ * At one point Netscape required applets to request specific permissions to
+ * do things. This is not longer the case with IcedTea-Web (and other modern
+ * plug-ins). However because some old applets may still have code calling 
+ * this class, an empty stub is needed to prevent a ClassNotFoundException.
+ *
+ */
+
+package netscape.security;
+
+import sun.applet.PluginDebug;
+
+public class PrivilegeManager {
+
+    /**
+     * Stub for enablePrivilege. Not used by IcedTea-Web, kept for compatibility
+     * 
+     * @param privilege
+     */
+    public static void  enablePrivilege(String privilege) {
+        PluginDebug.debug("netscape.security.enablePrivilege stub called");
+    }
+    
+    /**
+     * Stub for disablePrivilege. Not used by IcedTea-Web, kept for compatibility
+     * 
+     * @param privilege
+     */
+    public static void  disablePrivilege(String privilege) {
+        PluginDebug.debug("netscape.security.disablePrivilege stub called");
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java	(revision 403)
@@ -0,0 +1,70 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.security.AccessControlContext;
+import java.util.HashMap;
+
+public class AppletSecurityContextManager {
+
+    // Context identifier -> PluginAppletSecurityContext object.
+    private static HashMap<Integer, PluginAppletSecurityContext> contexts =
+            new HashMap<Integer, PluginAppletSecurityContext>();
+
+    public static void addContext(int identifier, PluginAppletSecurityContext context) {
+        contexts.put(identifier, context);
+    }
+
+    public static PluginAppletSecurityContext getSecurityContext(int identifier) {
+        return contexts.get(identifier);
+    }
+
+    public static void dumpStore(int identifier) {
+        contexts.get(identifier).dumpStore();
+    }
+
+    public static void handleMessage(int identifier, int reference, String src, String[] privileges, String message) {
+        PluginDebug.debug(identifier, " -- ", src, " -- ", reference, " -- ", message, " CONTEXT= ", contexts.get(identifier));
+        AccessControlContext callContext = null;
+
+        privileges = privileges != null ? privileges : new String[0];
+        callContext = contexts.get(identifier).getAccessControlContext(privileges, src);
+
+        contexts.get(identifier).handleMessage(reference, src, callContext, message);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java	(revision 403)
@@ -0,0 +1,61 @@
+/* GetMemberPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class GetMemberPluginCallRequest extends PluginCallRequest {
+    Object object = null;
+
+    public GetMemberPluginCallRequest(String message, Long reference) {
+        super(message, reference);
+        PluginDebug.debug("GetMemberPluginCall ", message);
+    }
+
+    public void parseReturn(String message) {
+        PluginDebug.debug("GetMemberParseReturn GOT: ", message);
+        String[] args = message.split(" ");
+        // FIXME: Is it even possible to distinguish between null and void
+        // here?
+        if (args[3] != "null" && args[3] != "void")
+            object = AppletSecurityContextManager.getSecurityContext(0).getObject(Integer.parseInt(args[3]));
+        setDone(true);
+    }
+
+    public Object getObject() {
+        return this.object;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java	(revision 403)
@@ -0,0 +1,60 @@
+/* GetWindowPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class GetWindowPluginCallRequest extends PluginCallRequest {
+    // FIXME: look into int vs long JavaScript internal values.
+    long internal;
+
+    public GetWindowPluginCallRequest(String message, Long reference) {
+        super(message, reference);
+    }
+
+    public void parseReturn(String message) {
+        PluginDebug.debug("GetWindowParseReturn GOT: ", message);
+        String[] args = message.split(" ");
+        // FIXME: add thread ID to messages to support multiple
+        // threads using the netscape.javascript package.
+        internal = Long.parseLong(args[3]);
+        setDone(true);
+    }
+
+    public Long getObject() {
+        return this.internal;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/JavaConsole.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/JavaConsole.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/JavaConsole.java	(revision 403)
@@ -0,0 +1,370 @@
+/* JavaConsole -- A java console for the plugin
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * A simple Java console for IcedTeaPlugin
+ * 
+ */
+public class JavaConsole {
+
+    private boolean initialized = false;
+
+    JFrame consoleWindow;
+    JTextArea stdErrText;
+    JTextArea stdOutText;
+
+    /**
+     * Initialize the console
+     */
+    public void initialize() {
+
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        final String logDir = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR);
+
+        consoleWindow = new JFrame("Java Console");
+
+        JPanel contentPanel = new JPanel();
+        contentPanel.setLayout(new GridBagLayout());
+
+        GridBagConstraints c;
+
+        Font monoSpace = new Font("Monospaced", Font.PLAIN, 12);
+
+        /* std out */
+
+        stdOutText = new JTextArea();
+        JScrollPane stdOutScrollPane = new JScrollPane(stdOutText);
+        stdOutScrollPane.setBorder(new TitledBorder(
+                new EmptyBorder(5, 5, 5, 5), "System.out"));
+        stdOutText.setEditable(false);
+        stdOutText.setFont(monoSpace);
+
+        TextAreaUpdater stdOutUpdater = new TextAreaUpdater(new File(logDir,
+                PluginMain.PLUGIN_STDOUT_FILE), stdOutText);
+        stdOutUpdater.setName("IcedteaPlugin Console Thread(System.out)");
+
+        /* std err */
+
+        stdErrText = new JTextArea();
+        JScrollPane stdErrScrollPane = new JScrollPane(stdErrText);
+        stdErrScrollPane.setBorder(new TitledBorder(
+                new EmptyBorder(5, 5, 5, 5), "System.err"));
+        stdErrText.setEditable(false);
+        stdErrText.setFont(monoSpace);
+
+        TextAreaUpdater stdErrUpdater = new TextAreaUpdater(new File(logDir,
+                PluginMain.PLUGIN_STDERR_FILE), stdErrText);
+        stdErrUpdater.setName("IcedteaPlugin Console Thread(System.err)");
+
+        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+                stdOutScrollPane, stdErrScrollPane);
+
+        c = new GridBagConstraints();
+        c.fill = GridBagConstraints.BOTH;
+        c.gridheight = 10;
+        c.weighty = 1;
+
+        contentPanel.add(splitPane, c);
+
+        /* buttons */
+
+        c = new GridBagConstraints();
+        c.gridy = 10;
+        c.gridheight = 1;
+        c.weightx = 0.5;
+        c.weighty = 0;
+
+        JPanel buttonPanel = new JPanel();
+        contentPanel.add(buttonPanel, c);
+
+        JButton gcButton = new JButton("Run GC");
+        buttonPanel.add(gcButton);
+        gcButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                printMemoryInfo();
+                System.out.print("Performing Garbage Collection....");
+                System.gc();
+                System.out.println("Done");
+                printMemoryInfo();
+            }
+
+        });
+
+        JButton finalizersButton = new JButton("Run Finalizers");
+        buttonPanel.add(finalizersButton);
+        finalizersButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                printMemoryInfo();
+                System.out.print("Running finalization....");
+                Runtime.getRuntime().runFinalization();
+                System.out.println("Done");
+                printMemoryInfo();
+            }
+        });
+
+        JButton memoryButton = new JButton("Memory Info");
+        buttonPanel.add(memoryButton);
+        memoryButton.addActionListener(new ActionListener() {
+
+            public void actionPerformed(ActionEvent e) {
+                printMemoryInfo();
+            }
+
+        });
+
+        JButton systemPropertiesButton = new JButton("System Properties");
+        buttonPanel.add(systemPropertiesButton);
+        systemPropertiesButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                printSystemProperties();
+            }
+
+        });
+
+        JButton classloadersButton = new JButton("Classloaders");
+        buttonPanel.add(classloadersButton);
+        classloadersButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                printClassLoaders();
+            }
+
+        });
+
+        JButton threadListButton = new JButton("Thread List");
+        buttonPanel.add(threadListButton);
+        threadListButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                printThreadInfo();
+            }
+
+        });
+
+        JButton closeButton = new JButton("Close");
+        buttonPanel.add(closeButton);
+        closeButton.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                SwingUtilities.invokeLater(new Runnable() {
+                    public void run() {
+                        hideConsole();
+                    }
+                });
+            }
+        });
+
+        stdOutUpdater.start();
+        stdErrUpdater.start();
+
+        consoleWindow.add(contentPanel);
+        consoleWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+        consoleWindow.pack();
+        consoleWindow.setSize(new Dimension(900, 600));
+        consoleWindow.setMinimumSize(new Dimension(900, 300));
+
+        initialized = true;
+
+        splitPane.setDividerLocation(0.5);
+        splitPane.setResizeWeight(0.5);
+    }
+
+    public void showConsole() {
+
+        if (!initialized) {
+            initialize();
+        }
+
+        consoleWindow.setVisible(true);
+    }
+
+    public void hideConsole() {
+        consoleWindow.setVisible(false);
+    }
+
+    protected void printSystemProperties() {
+
+        System.out.println(" ----");
+        System.out.println("System Properties:");
+        System.out.println();
+        Properties p = System.getProperties();
+        Set<Object> keys = p.keySet();
+        for (Object key : keys) {
+            System.out.println(key.toString() + ": " + p.get(key));
+        }
+
+        System.out.println(" ----");
+    }
+
+    private void printClassLoaders() {
+        System.out.println(" ----");
+        System.out.println("Available Classloaders: ");
+        Set<String> loaders = PluginAppletSecurityContext.getLoaderInfo().keySet();
+        for (String loader : loaders) {
+            System.out.println(loader + "\n"
+                    + "  codebase = "
+                    + PluginAppletSecurityContext.getLoaderInfo().get(loader));
+        }
+        System.out.println(" ----");
+    }
+
+    private void printMemoryInfo() {
+        System.out.println(" ----- ");
+        System.out.println("  Memory Info:");
+        System.out.println("    Max Memory:   "
+                + String.format("%1$10d", Runtime.getRuntime().maxMemory()));
+        System.out.println("    Total Memory: "
+                + String.format("%1$10d", Runtime.getRuntime().totalMemory()));
+        System.out.println("    Free Memory:  "
+                + String.format("%1$10d", Runtime.getRuntime().freeMemory()));
+        System.out.println(" ----");
+
+    }
+
+    private void printThreadInfo() {
+        Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
+        Set<Thread> keys = map.keySet();
+        for (Thread key : keys) {
+            System.out.println("Thread " + key.getId() + ": " + key.getName());
+            for (StackTraceElement element : map.get(key)) {
+                System.out.println("  " + element);
+            }
+
+        }
+    }
+
+    public static void main(String[] args) {
+
+        final JavaConsole console = new JavaConsole();
+
+        boolean toShowConsole = false;
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i] == "--show-console") {
+                toShowConsole = true;
+            }
+        }
+
+        if (toShowConsole) {
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    console.showConsole();
+                }
+            });
+        }
+
+    }
+
+    /**
+     * This thread updates the text on a JTextArea based on the text in a file
+     */
+    class TextAreaUpdater extends Thread {
+
+        File fileToRead;
+        JTextArea outputTextArea;
+
+        public TextAreaUpdater(File file, JTextArea textArea) {
+            fileToRead = file;
+            outputTextArea = textArea;
+            setDaemon(true);
+        }
+
+        public void run() {
+
+            try {
+                BufferedReader reader = new BufferedReader(new FileReader(
+                        fileToRead));
+                String line;
+                while (true) {
+                    while ((line = reader.readLine()) != null) {
+                        outputTextArea.insert(line + "\n", outputTextArea
+                                .getDocument().getLength());
+                        outputTextArea.setCaretPosition(outputTextArea
+                                .getText().length());
+                    }
+                    Thread.sleep(1000);
+                }
+
+            } catch (FileNotFoundException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+                Thread.currentThread().interrupt();
+            }
+
+        }
+
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	(revision 403)
@@ -0,0 +1,742 @@
+/* MethodOverloadResolver -- Resolves overloaded methods
+   Copyright (C) 2009 Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/*
+ * This class resolved overloaded methods in Java objects using a cost
+ * based-approach as described here:
+ *
+ * http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/#OVERLOADED_METHODS
+ */
+
+public class MethodOverloadResolver {
+
+    private static boolean debugging = false;
+
+    public static void main(String[] args) {
+        testMethodResolver();
+    }
+
+    public static void testMethodResolver() {
+        debugging = true;
+
+        ArrayList<Object[]> list = new ArrayList<Object[]>(20);
+        FooClass fc = new FooClass();
+
+        // Numeric to java primitive
+        // foo_i has Integer and int params
+        String s1 = "foo_string_int(S,I)";
+        String s1a = "foo_string_int(S,S)";
+        Object[] o1 = { fc.getClass(), "foo_string_int", "blah", 42 };
+        list.add(o1);
+        Object[] o1a = { fc.getClass(), "foo_string_int", "blah", "42.42" };
+        list.add(o1a);
+
+        // Null to non-primitive type
+        // foo_i is overloaded with Integer and int
+        String s2 = "foo_string_int(N)";
+        Object[] o2 = { fc.getClass(), "foo_string_int", "blah", null };
+        list.add(o2);
+
+        // foo_jsobj is overloaded with JSObject and String params
+        String s3 = "foo_jsobj(LLowCostSignatureComputer/JSObject;)";
+        Object[] o3 = { fc.getClass(), "foo_jsobj", new JSObject() };
+        list.add(o3);
+
+        // foo_classtype is overloaded with Number and Integer
+        String s4 = "foo_classtype(Ljava/lang/Integer;)";
+        Object[] o4 = { fc.getClass(), "foo_classtype", 42 };
+        list.add(o4);
+
+        // foo_multiprim is overloaded with int, long and float types
+        String s5 = "foo_multiprim(I)";
+        String s6 = "foo_multiprim(F)";
+        String s6a = "foo_multiprim(D)";
+
+        Object[] o5 = { fc.getClass(), "foo_multiprim", new Integer(42) };
+        Object[] o6 = { fc.getClass(), "foo_multiprim", new Float(42.42) };
+        Object[] o6a = { fc.getClass(), "foo_multiprim", new Double(42.42) };
+        list.add(o5);
+        list.add(o6);
+        list.add(o6a);
+
+        // foo_float has float, String and JSObject type
+        String s7 = "foo_float(I)";
+        Object[] o7 = { fc.getClass(), "foo_float", new Integer(42) };
+        list.add(o7);
+
+        // foo_multiprim(float) is what this should convert
+        String s8 = "foo_float(S)";
+        Object[] o8 = { fc.getClass(), "foo_float", "42" };
+        list.add(o8);
+
+        // foo_class is overloaded with BarClass 2 and 3
+        String s9 = "foo_class(LLowCostSignatureComputer/BarClass3;)";
+        Object[] o9 = { fc.getClass(), "foo_class", new BarClass3() };
+        list.add(o9);
+
+        // foo_strandbyteonly takes string and byte
+        String s10 = "foo_strandbyteonly(I)";
+        Object[] o10 = { fc.getClass(), "foo_strandbyteonly", 42 };
+        list.add(o10);
+
+        // JSOBject to string
+        String s11 = "foo_strandbyteonly(LLowCostSignatureComputer/JSObject;)";
+        Object[] o11 = { fc.getClass(), "foo_strandbyteonly", new JSObject() };
+        list.add(o11);
+
+        // jsobject to string and int to float
+        String s12 = "foo_str_and_float(S,I)";
+        Object[] o12 = { fc.getClass(), "foo_str_and_float", new JSObject(), new Integer(42) };
+        list.add(o12);
+
+        // call for which no match will be found
+        String s13 = "foo_int_only(JSObject)";
+        Object[] o13 = { fc.getClass(), "foo_int_only", new JSObject() };
+        list.add(o13);
+
+        // method with no args
+        String s14 = "foo_noargs()";
+        Object[] o14 = { fc.getClass(), "foo_noargs" };
+        list.add(o14);
+
+        // method which takes a primitive bool, given a Boolean
+        String s15 = "foo_boolonly()";
+        Object[] o15 = { fc.getClass(), "foo_boolonly", new Boolean(true) };
+        list.add(o15);
+
+        for (Object[] o : list) {
+            Object[] methodAndArgs = getMatchingMethod(o);
+            if (debugging)
+                if (methodAndArgs != null)
+                    System.out.println("Best match: " + methodAndArgs[0] + "\n");
+                else
+                    System.out.println("No match found.\n");
+
+        }
+
+    }
+
+    /*
+     * Cost based overload resolution algorithm based on cost rules specified here:
+     *
+     * http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/#OVERLOADED_METHODS
+     */
+
+    public static Object[] getMatchingMethod(Object[] callList) {
+        Object[] ret = null;
+        Class<?> c = (Class<?>) callList[0];
+        String methodName = (String) callList[1];
+
+        Method[] matchingMethods = getMatchingMethods(c, methodName, callList.length - 2);
+
+        if (debugging)
+            System.out.println("getMatchingMethod called with: " + printList(callList));
+
+        int lowestCost = Integer.MAX_VALUE;
+
+        for (Method matchingMethod : matchingMethods) {
+
+            int methodCost = 0;
+            Class[] paramTypes = matchingMethod.getParameterTypes();
+            Object[] methodAndArgs = new Object[paramTypes.length + 1];
+            methodAndArgs[0] = matchingMethod;
+
+            // Figure out which of the matched methods best represents what we
+            // want
+            for (int i = 0; i < paramTypes.length; i++) {
+                Class<?> paramTypeClass = paramTypes[i];
+                Object suppliedParam = callList[i + 2];
+                Class<?> suppliedParamClass = suppliedParam != null ? suppliedParam
+                        .getClass()
+                        : null;
+
+                Object[] costAndCastedObj = getCostAndCastedObject(
+                        suppliedParam, paramTypeClass);
+                methodCost += (Integer) costAndCastedObj[0];
+
+                if ((Integer) costAndCastedObj[0] < 0)
+                    break;
+
+                Object castedObj = paramTypeClass.isPrimitive() ? costAndCastedObj[1]
+                        : paramTypeClass.cast(costAndCastedObj[1]);
+                methodAndArgs[i + 1] = castedObj;
+
+                Class<?> castedObjClass = castedObj == null ? null : castedObj
+                        .getClass();
+                Boolean castedObjIsPrim = castedObj == null ? null : castedObj
+                        .getClass().isPrimitive();
+
+                if (debugging)
+                    System.out.println("Param " + i + " of method "
+                            + matchingMethod + " has cost "
+                            + (Integer) costAndCastedObj[0]
+                            + " original param type " + suppliedParamClass
+                            + " casted to " + castedObjClass + " isPrimitive="
+                            + castedObjIsPrim + " value " + castedObj);
+            }
+
+            if ((methodCost > 0 && methodCost < lowestCost) ||
+                    paramTypes.length == 0) {
+                ret = methodAndArgs;
+                lowestCost = methodCost;
+            }
+
+        }
+
+        return ret;
+    }
+
+    public static Object[] getMatchingConstructor(Object[] callList) {
+        Object[] ret = null;
+        Class<?> c = (Class<?>) callList[0];
+
+        Constructor[] matchingConstructors = getMatchingConstructors(c, callList.length - 1);
+
+        if (debugging)
+            System.out.println("getMatchingConstructor called with: " + printList(callList));
+
+        int lowestCost = Integer.MAX_VALUE;
+
+        for (Constructor matchingConstructor : matchingConstructors) {
+
+            int constructorCost = 0;
+            Class<?>[] paramTypes = matchingConstructor.getParameterTypes();
+            Object[] constructorAndArgs = new Object[paramTypes.length + 1];
+            constructorAndArgs[0] = matchingConstructor;
+
+            // Figure out which of the matched methods best represents what we
+            // want
+            for (int i = 0; i < paramTypes.length; i++) {
+                Class<?> paramTypeClass = paramTypes[i];
+                Object suppliedParam = callList[i + 1];
+                Class suppliedParamClass = suppliedParam != null ? suppliedParam
+                        .getClass()
+                        : null;
+
+                Object[] costAndCastedObj = getCostAndCastedObject(
+                        suppliedParam, paramTypeClass);
+                constructorCost += (Integer) costAndCastedObj[0];
+
+                if ((Integer) costAndCastedObj[0] < 0)
+                    break;
+
+                Object castedObj = paramTypeClass.isPrimitive() ? costAndCastedObj[1]
+                        : paramTypeClass.cast(costAndCastedObj[1]);
+                constructorAndArgs[i + 1] = castedObj;
+
+                Class<?> castedObjClass = castedObj == null ? null : castedObj
+                        .getClass();
+                Boolean castedObjIsPrim = castedObj == null ? null : castedObj
+                        .getClass().isPrimitive();
+
+                if (debugging)
+                    System.out.println("Param " + i + " of constructor "
+                            + matchingConstructor + " has cost "
+                            + (Integer) costAndCastedObj[0]
+                            + " original param type " + suppliedParamClass
+                            + " casted to " + castedObjClass + " isPrimitive="
+                            + castedObjIsPrim + " value " + castedObj);
+            }
+
+            if ((constructorCost > 0 && constructorCost < lowestCost) ||
+                    paramTypes.length == 0) {
+                ret = constructorAndArgs;
+                lowestCost = constructorCost;
+            }
+        }
+
+        return ret;
+    }
+
+    public static Object[] getCostAndCastedObject(Object suppliedParam, Class<?> paramTypeClass) {
+
+        Object[] ret = new Object[2];
+        Integer cost = new Integer(0);
+        Object castedObj;
+
+        Class<?> suppliedParamClass = suppliedParam != null ? suppliedParam.getClass() : null;
+
+        // Either both are an array, or neither are
+        boolean suppliedParamIsArray = suppliedParamClass != null && suppliedParamClass.isArray();
+        if (paramTypeClass.isArray() != suppliedParamIsArray &&
+                !paramTypeClass.equals(Object.class) &&
+                !paramTypeClass.equals(String.class)) {
+            ret[0] = Integer.MIN_VALUE; // Not allowed
+            ret[1] = suppliedParam;
+            return ret;
+        }
+
+        // If param type is an array, supplied obj must be an array, Object or String (guaranteed by checks above)
+        // If it is an array, we need to copy/cast as we scan the array
+        // If it an object, we return "as is" [Everything can be narrowed to an object, cost=6]
+        // If it is a string, we need to convert according to the JS engine rules
+
+        if (paramTypeClass.isArray()) {
+
+            Object newArray = Array.newInstance(paramTypeClass.getComponentType(), Array.getLength(suppliedParam));
+            for (int i = 0; i < Array.getLength(suppliedParam); i++) {
+                Object original = Array.get(suppliedParam, i);
+
+                // When dealing with arrays, we represent empty slots with
+                // null. We need to convert this to 0 before recursive
+                // calling, since normal transformation does not allow
+                // null -> primitive
+
+                if (original == null && paramTypeClass.getComponentType().isPrimitive())
+                    original = 0;
+
+                Object[] costAndCastedObject = getCostAndCastedObject(original, paramTypeClass.getComponentType());
+
+                if ((Integer) costAndCastedObject[0] < 0) {
+                    ret[0] = Integer.MIN_VALUE; // Not allowed
+                    ret[1] = suppliedParam;
+                    return ret;
+                }
+
+                Array.set(newArray, i, costAndCastedObject[1]);
+            }
+
+            ret[0] = 9;
+            ret[1] = newArray;
+            return ret;
+        }
+
+        if (suppliedParamIsArray && paramTypeClass.equals(String.class)) {
+
+            ret[0] = 9;
+            ret[1] = getArrayAsString(suppliedParam);
+            return ret;
+        }
+
+        // If this is null, there are only 2 possible cases
+        if (suppliedParamClass == null) {
+            castedObj = null; // if value is null.. well, it is null
+
+            if (!paramTypeClass.isPrimitive()) {
+                cost += 2; // Null to any non-primitive type
+            } else {
+                cost = Integer.MIN_VALUE; // Null to primitive not allowed
+            }
+        } else if (paramTypeClass.isPrimitive() && paramTypeClass.equals(getPrimitive(suppliedParam))) {
+            cost += 1; // Numeric type to the analogous Java primitive type
+            castedObj = suppliedParam; // Let auto-boxing handle it
+        } else if (suppliedParamClass.equals(paramTypeClass)) {
+            cost += 3; // Class type to Class type where the types are equal
+            castedObj = suppliedParam;
+        } else if (isNum(suppliedParam) &&
+                       (paramTypeClass.isPrimitive() ||
+                               java.lang.Number.class.isAssignableFrom(paramTypeClass) ||
+                               java.lang.Character.class.isAssignableFrom(paramTypeClass) ||
+                        java.lang.Byte.class.isAssignableFrom(paramTypeClass)
+                       )) {
+            cost += 4; // Numeric type to a different primitive type
+
+            if (suppliedParam.toString().equals("true"))
+                suppliedParam = "1";
+            else if (suppliedParam.toString().equals("false"))
+                suppliedParam = "0";
+
+            if (paramTypeClass.equals(Boolean.TYPE))
+                castedObj = getNum(suppliedParam.toString(), paramTypeClass).doubleValue() != 0D;
+            else if (paramTypeClass.equals(Character.TYPE))
+                castedObj = (char) Short.decode(suppliedParam.toString()).shortValue();
+            else
+                castedObj = getNum(suppliedParam.toString(), paramTypeClass);
+        } else if (suppliedParam instanceof java.lang.String &&
+                    isNum(suppliedParam) &&
+                        (paramTypeClass.isInstance(java.lang.Number.class) ||
+                                paramTypeClass.isInstance(java.lang.Character.class) ||
+                                paramTypeClass.isInstance(java.lang.Byte.class) ||
+                         paramTypeClass.isPrimitive())) {
+            cost += 5; // String to numeric type
+
+            if (suppliedParam.toString().equals("true"))
+                suppliedParam = "1";
+            else if (suppliedParam.toString().equals("false"))
+                suppliedParam = "0";
+
+            if (paramTypeClass.equals(Character.TYPE))
+                castedObj = (char) Short.decode(suppliedParam.toString()).shortValue();
+            else
+                castedObj = getNum(suppliedParam.toString(), paramTypeClass);
+        } else if (suppliedParam instanceof java.lang.String &&
+                     (paramTypeClass.equals(java.lang.Boolean.class) ||
+                      paramTypeClass.equals(java.lang.Boolean.TYPE))) {
+
+            cost += 5; // Same cost as above
+            castedObj = new Boolean(suppliedParam.toString().length() > 0);
+        } else if (paramTypeClass.isAssignableFrom(suppliedParamClass)) {
+            cost += 6; // Class type to superclass type;
+            castedObj = paramTypeClass.cast(suppliedParam);
+        } else if (paramTypeClass.equals(String.class)) {
+            cost += 7; // Any Java value to String
+            castedObj = suppliedParam.toString();
+        } else if (suppliedParam instanceof JSObject &&
+                   paramTypeClass.isArray()) {
+            cost += 8; // JSObject to Java array
+            castedObj = (JSObject) suppliedParam;
+        } else {
+            cost = Integer.MIN_VALUE; // Not allowed
+            castedObj = suppliedParam;
+        }
+
+        ret[0] = cost;
+        ret[1] = castedObj;
+
+        return ret;
+
+    }
+
+    private static Method[] getMatchingMethods(Class<?> c, String name, int paramCount) {
+        Method[] allMethods = c.getMethods();
+        ArrayList<Method> matchingMethods = new ArrayList<Method>(5);
+
+        for (Method m : allMethods) {
+            if (m.getName().equals(name) && m.getParameterTypes().length == paramCount)
+                matchingMethods.add(m);
+        }
+
+        return matchingMethods.toArray(new Method[0]);
+    }
+
+    private static Constructor[] getMatchingConstructors(Class<?> c, int paramCount) {
+        Constructor[] allConstructors = c.getConstructors();
+        ArrayList<Constructor> matchingConstructors = new ArrayList<Constructor>(5);
+
+        for (Constructor cs : allConstructors) {
+            if (cs.getParameterTypes().length == paramCount)
+                matchingConstructors.add(cs);
+        }
+
+        return matchingConstructors.toArray(new Constructor[0]);
+    }
+
+    private static Class getPrimitive(Object o) {
+
+        if (o instanceof java.lang.Byte) {
+            return java.lang.Byte.TYPE;
+        } else if (o instanceof java.lang.Character) {
+            return java.lang.Character.TYPE;
+        } else if (o instanceof java.lang.Short) {
+            return java.lang.Short.TYPE;
+        } else if (o instanceof java.lang.Integer) {
+            return java.lang.Integer.TYPE;
+        } else if (o instanceof java.lang.Long) {
+            return java.lang.Long.TYPE;
+        } else if (o instanceof java.lang.Float) {
+            return java.lang.Float.TYPE;
+        } else if (o instanceof java.lang.Double) {
+            return java.lang.Double.TYPE;
+        } else if (o instanceof java.lang.Boolean) {
+            return java.lang.Boolean.TYPE;
+        }
+
+        return o.getClass();
+    }
+
+    private static boolean isNum(Object o) {
+
+        if (o instanceof java.lang.Number)
+            return true;
+
+        // Boolean is changeable to number as well
+        if (o instanceof java.lang.Boolean)
+            return true;
+
+        // At this point, it _has_ to be a string else automatically
+        // return false
+        if (!(o instanceof java.lang.String))
+            return false;
+
+        try {
+            Long.parseLong((String) o); // whole number test
+            return true;
+        } catch (NumberFormatException nfe) {
+        }
+
+        try {
+            Float.parseFloat((String) o); // decimal
+            return true;
+        } catch (NumberFormatException nfe) {
+        }
+
+        return false;
+    }
+
+    private static Number getNum(String s, Class<?> c) throws NumberFormatException {
+
+        Number n;
+        if (s.contains("."))
+            n = new Double(s);
+        else
+            n = new Long(s);
+
+        // See if we need to collapse first
+        if (c.equals(java.lang.Integer.class) ||
+                c.equals(java.lang.Integer.TYPE)) {
+            return n.intValue();
+        }
+
+        if (c.equals(java.lang.Long.class) ||
+                c.equals(java.lang.Long.TYPE)) {
+            return n.longValue();
+        }
+
+        if (c.equals(java.lang.Short.class) ||
+                c.equals(java.lang.Short.TYPE)) {
+            return n.shortValue();
+        }
+
+        if (c.equals(java.lang.Float.class) ||
+                c.equals(java.lang.Float.TYPE)) {
+            return n.floatValue();
+        }
+
+        if (c.equals(java.lang.Double.class) ||
+                c.equals(java.lang.Double.TYPE)) {
+            return n.doubleValue();
+        }
+
+        if (c.equals(java.lang.Byte.class) ||
+                c.equals(java.lang.Byte.TYPE)) {
+            return n.byteValue();
+        }
+
+        return n;
+    }
+
+    private static String printList(Object[] oList) {
+
+        String ret = "";
+
+        ret += "{ ";
+        for (Object o : oList) {
+
+            String oStr = o != null ? o.toString() + " [" + o.getClass() + "]" : "null";
+
+            ret += oStr;
+            ret += ", ";
+        }
+        ret = ret.substring(0, ret.length() - 2); // remove last ", "
+        ret += " }";
+
+        return ret;
+    }
+
+    private static String getArrayAsString(Object array) {
+        // We are guaranteed that supplied object is a String
+
+        String ret = new String();
+
+        for (int i = 0; i < Array.getLength(array); i++) {
+            Object element = Array.get(array, i);
+
+            if (element != null) {
+                if (element.getClass().isArray()) {
+                    ret += getArrayAsString(element);
+                } else {
+                    ret += element;
+                }
+            }
+
+            ret += ",";
+        }
+
+        // Trim the final ","
+        if (ret.length() > 0) {
+            ret = ret.substring(0, ret.length() - 1);
+        }
+
+        return ret;
+    }
+}
+
+/** Begin test classes **/
+
+class FooClass {
+
+    public FooClass() {
+    }
+
+    public FooClass(Boolean b, int i) {
+    }
+
+    public FooClass(Boolean b, Integer i) {
+    }
+
+    public FooClass(Boolean b, short s) {
+    }
+
+    public FooClass(String s, int i) {
+    }
+
+    public FooClass(String s, Integer i) {
+    }
+
+    public FooClass(java.lang.Number num) {
+    }
+
+    public FooClass(java.lang.Integer integer) {
+    }
+
+    public FooClass(long l) {
+    }
+
+    public FooClass(double d) {
+    }
+
+    public FooClass(float f) {
+    }
+
+    public FooClass(JSObject j) {
+    }
+
+    public FooClass(BarClass1 b) {
+    }
+
+    public FooClass(BarClass2 b) {
+    }
+
+    public FooClass(String s) {
+    }
+
+    public FooClass(byte b) {
+    }
+
+    public FooClass(String s, Float f) {
+    }
+
+    public FooClass(int i) {
+    }
+
+    public void FooClass() {
+    }
+
+    public void FooClass(boolean b) {
+    }
+
+    public void foo(Boolean b, int i) {
+    }
+
+    public void foo(Boolean b, Integer i) {
+    }
+
+    public void foo(Boolean b, short s) {
+    }
+
+    public void foo_string_int(String s, int i) {
+    }
+
+    public void foo_string_int(String s, Integer i) {
+    }
+
+    public void foo_jsobj(JSObject j) {
+    }
+
+    public void foo_jsobj(String s) {
+    }
+
+    public void foo_classtype(java.lang.Number num) {
+    }
+
+    public void foo_classtype(java.lang.Integer integer) {
+    }
+
+    public void foo_multiprim(int i) {
+    }
+
+    public void foo_multiprim(long l) {
+    }
+
+    public void foo_multiprim(float f) {
+    }
+
+    public void foo_multiprim(double d) {
+    }
+
+    public void foo_float(float f) {
+    }
+
+    public void foo_float(String s) {
+    }
+
+    public void foo_float(JSObject j) {
+    }
+
+    public void foo_class(BarClass1 b) {
+    }
+
+    public void foo_class(BarClass2 b) {
+    }
+
+    public void foo_strandbyteonly(String s) {
+    }
+
+    public void foo_strandbyteonly(byte b) {
+    }
+
+    public void foo_str_and_float(String s, Float f) {
+    }
+
+    public void foo_int_only(int i) {
+    }
+
+    public void foo_noargs() {
+    }
+
+    public void foo_boolonly(boolean b) {
+    }
+}
+
+class BarClass1 {
+}
+
+class BarClass2 extends BarClass1 {
+}
+
+class BarClass3 extends BarClass2 {
+}
+
+class JSObject {
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	(revision 403)
@@ -0,0 +1,1353 @@
+/* PluginAppletSecurityContext -- execute plugin JNI messages
+   Copyright (C) 2008, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.BasicPermission;
+import java.security.CodeSource;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.DefaultLaunchHandler;
+import netscape.javascript.JSObjectCreatePermission;
+
+class Signature {
+    private String signature;
+    private int currentIndex;
+    private List<Class> typeList;
+    private static final char ARRAY = '[';
+    private static final char OBJECT = 'L';
+    private static final char SIGNATURE_ENDCLASS = ';';
+    private static final char SIGNATURE_FUNC = '(';
+    private static final char SIGNATURE_ENDFUNC = ')';
+    private static final char VOID = 'V';
+    private static final char BOOLEAN = 'Z';
+    private static final char BYTE = 'B';
+    private static final char CHARACTER = 'C';
+    private static final char SHORT = 'S';
+    private static final char INTEGER = 'I';
+    private static final char LONG = 'J';
+    private static final char FLOAT = 'F';
+    private static final char DOUBLE = 'D';
+
+    private String nextTypeName() {
+        char key = signature.charAt(currentIndex++);
+
+        switch (key) {
+            case ARRAY:
+                return nextTypeName() + "[]";
+
+            case OBJECT:
+                int endClass = signature.indexOf(SIGNATURE_ENDCLASS, currentIndex);
+                String retVal = signature.substring(currentIndex, endClass);
+                retVal = retVal.replace('/', '.');
+                currentIndex = endClass + 1;
+                return retVal;
+
+                // FIXME: generated bytecode with classes named after
+                // primitives will not work in this scheme -- those
+                // classes will be incorrectly treated as primitive
+                // types.
+            case VOID:
+                return "void";
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHARACTER:
+                return "char";
+            case SHORT:
+                return "short";
+            case INTEGER:
+                return "int";
+            case LONG:
+                return "long";
+            case FLOAT:
+                return "float";
+            case DOUBLE:
+                return "double";
+
+            case SIGNATURE_ENDFUNC:
+                return null;
+
+            case SIGNATURE_FUNC:
+                return nextTypeName();
+
+            default:
+                throw new IllegalArgumentException(
+                                        "Invalid JNI signature character '" + key + "'");
+        }
+    }
+
+    public Signature(String signature, ClassLoader cl) {
+        this.signature = signature;
+        currentIndex = 0;
+        typeList = new ArrayList<Class>(10);
+
+        String elem;
+        while (currentIndex < signature.length()) {
+            elem = nextTypeName();
+
+            if (elem == null) // end of signature
+                continue;
+
+            Class primitive = primitiveNameToType(elem);
+            if (primitive != null)
+                typeList.add(primitive);
+            else {
+                int dimsize = 0;
+                int n = elem.indexOf('[');
+                if (n != -1) {
+                    String arrayType = elem.substring(0, n);
+                    dimsize++;
+                    n = elem.indexOf('[', n + 1);
+                    while (n != -1) {
+                        dimsize++;
+                        n = elem.indexOf('[', n + 1);
+                    }
+                    int[] dims = new int[dimsize];
+                    primitive = primitiveNameToType(arrayType);
+                    if (primitive != null) {
+                        typeList.add(Array.newInstance(primitive, dims)
+                                                                .getClass());
+                    } else
+                        typeList.add(Array.newInstance(
+                                                                getClass(arrayType, cl), dims).getClass());
+                } else {
+                    typeList.add(getClass(elem, cl));
+                }
+            }
+        }
+        if (signature.length() < 2) {
+            throw new IllegalArgumentException("Invalid JNI signature '"
+                                        + signature + "'");
+        }
+    }
+
+    public static Class getClass(String name, ClassLoader cl) {
+
+        Class c = null;
+
+        try {
+            c = Class.forName(name);
+        } catch (ClassNotFoundException cnfe) {
+
+            PluginDebug.debug("Class ", name, " not found in primordial loader. Looking in ", cl);
+            try {
+                c = cl.loadClass(name);
+            } catch (ClassNotFoundException e) {
+                throw (new RuntimeException(new ClassNotFoundException("Unable to find class " + name)));
+            }
+        }
+
+        return c;
+    }
+
+    public static Class primitiveNameToType(String name) {
+        if (name.equals("void"))
+            return Void.TYPE;
+        else if (name.equals("boolean"))
+            return Boolean.TYPE;
+        else if (name.equals("byte"))
+            return Byte.TYPE;
+        else if (name.equals("char"))
+            return Character.TYPE;
+        else if (name.equals("short"))
+            return Short.TYPE;
+        else if (name.equals("int"))
+            return Integer.TYPE;
+        else if (name.equals("long"))
+            return Long.TYPE;
+        else if (name.equals("float"))
+            return Float.TYPE;
+        else if (name.equals("double"))
+            return Double.TYPE;
+        else
+            return null;
+    }
+
+    public Class[] getClassArray() {
+        return typeList.subList(0, typeList.size()).toArray(new Class[] {});
+    }
+}
+
+public class PluginAppletSecurityContext {
+
+    private static Hashtable<ClassLoader, URL> classLoaders = new Hashtable<ClassLoader, URL>();
+    private static Hashtable<Integer, ClassLoader> instanceClassLoaders = new Hashtable<Integer, ClassLoader>();
+
+    private PluginObjectStore store = PluginObjectStore.getInstance();
+    private Throwable throwable = null;
+    private ClassLoader liveconnectLoader = ClassLoader.getSystemClassLoader();
+    int identifier = 0;
+
+    public static PluginStreamHandler streamhandler;
+
+    long startTime = 0;
+
+    public PluginAppletSecurityContext(int identifier) {
+        this.identifier = identifier;
+
+        // We need a security manager.. and since there is a good chance that
+        // an applet will be loaded at some point, we should make it the SM
+        // that JNLPRuntime will try to install
+        if (System.getSecurityManager() == null) {
+            JNLPRuntime.initialize(/* isApplication */false);
+            JNLPRuntime.setDefaultLaunchHandler(new DefaultLaunchHandler());
+        }
+
+        JNLPRuntime.disableExit();
+
+        URL u = null;
+        try {
+            u = new URL("file://");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        this.classLoaders.put(liveconnectLoader, u);
+    }
+
+    private static <V> V parseCall(String s, ClassLoader cl, Class<V> c) {
+        if (c == Integer.class)
+            return c.cast(new Integer(s));
+        else if (c == String.class)
+            return c.cast(new String(s));
+        else if (c == Signature.class)
+            return c.cast(new Signature(s, cl));
+        else
+            throw new RuntimeException("Unexpected call value.");
+    }
+
+    private Object parseArgs(String s, Class c) {
+        if (c == Boolean.TYPE || c == Boolean.class)
+            return new Boolean(s);
+        else if (c == Byte.TYPE || c == Byte.class)
+            return new Byte(s);
+        else if (c == Character.TYPE || c == Character.class) {
+            String[] bytes = s.split("_");
+            int low = Integer.parseInt(bytes[0]);
+            int high = Integer.parseInt(bytes[1]);
+            int full = ((high << 8) & 0x0ff00) | (low & 0x0ff);
+            return new Character((char) full);
+        } else if (c == Short.TYPE || c == Short.class)
+            return new Short(s);
+        else if (c == Integer.TYPE || c == Integer.class)
+            return new Integer(s);
+        else if (c == Long.TYPE || c == Long.class)
+            return new Long(s);
+        else if (c == Float.TYPE || c == Float.class)
+            return new Float(s);
+        else if (c == Double.TYPE || c == Double.class)
+            return new Double(s);
+        else
+            return store.getObject(new Integer(s));
+    }
+
+    public void associateSrc(ClassLoader cl, URL src) {
+        PluginDebug.debug("Associating ", cl, " with ", src);
+        this.classLoaders.put(cl, src);
+    }
+
+    public void associateInstance(Integer i, ClassLoader cl) {
+        PluginDebug.debug("Associating ", cl, " with instance ", i);
+        this.instanceClassLoaders.put(i, cl);
+    }
+
+    public static void setStreamhandler(PluginStreamHandler sh) {
+        streamhandler = sh;
+    }
+
+    public static Map<String, String> getLoaderInfo() {
+        Hashtable<String, String> map = new Hashtable<String, String>();
+
+        for (ClassLoader loader : PluginAppletSecurityContext.classLoaders.keySet()) {
+            map.put(loader.getClass().getName(), classLoaders.get(loader).toString());
+        }
+
+        return map;
+    }
+
+    public void handleMessage(int reference, String src, AccessControlContext callContext, String message) {
+
+        startTime = new java.util.Date().getTime();
+
+        try {
+            if (message.startsWith("FindClass")) {
+                ClassLoader cl = null;
+                Class c = null;
+                cl = liveconnectLoader;
+                String[] args = message.split(" ");
+                Integer instance = new Integer(args[1]);
+                String className = args[2].replace('/', '.');
+                PluginDebug.debug("Searching for class ", className, " in ", cl);
+
+                try {
+                    c = cl.loadClass(className);
+                    store.reference(c);
+                    write(reference, "FindClass " + store.getIdentifier(c));
+                } catch (ClassNotFoundException cnfe) {
+
+                    cl = this.instanceClassLoaders.get(instance);
+                    PluginDebug.debug("Not found. Looking in ", cl);
+
+                    if (instance != 0 && cl != null) {
+                        try {
+                            c = cl.loadClass(className);
+                            store.reference(c);
+                            write(reference, "FindClass " + store.getIdentifier(c));
+                        } catch (ClassNotFoundException cnfe2) {
+                            write(reference, "FindClass 0");
+                        }
+                    } else {
+                        write(reference, "FindClass 0");
+                    }
+                }
+
+            } else if (message.startsWith("GetStaticMethodID")
+                                        || message.startsWith("GetMethodID")) {
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                String methodName = parseCall(args[2], null, String.class);
+                Signature signature = parseCall(args[3], ((Class) store.getObject(classID)).getClassLoader(), Signature.class);
+                Object[] a = signature.getClassArray();
+
+                Class<?> c;
+
+                if (message.startsWith("GetStaticMethodID") ||
+                                    methodName.equals("<init>") ||
+                                    methodName.equals("<clinit>"))
+                    c = (Class<?>) store.getObject(classID);
+                else
+                    c = store.getObject(classID).getClass();
+
+                Method m = null;
+                Constructor cs = null;
+                Object o = null;
+                if (methodName.equals("<init>")
+                                                || methodName.equals("<clinit>")) {
+                    o = cs = c.getConstructor(signature.getClassArray());
+                    store.reference(cs);
+                } else {
+                    o = m = c.getMethod(methodName, signature.getClassArray());
+                    store.reference(m);
+                }
+                PluginDebug.debug(o, " has id ", store.getIdentifier(o));
+                write(reference, args[0] + " " + store.getIdentifier(o));
+            } else if (message.startsWith("GetStaticFieldID")
+                                        || message.startsWith("GetFieldID")) {
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Integer fieldID = parseCall(args[2], null, Integer.class);
+                String fieldName = (String) store.getObject(fieldID);
+
+                Class<?> c = (Class<?>) store.getObject(classID);
+
+                PluginDebug.debug("GetStaticFieldID/GetFieldID got class=", c.getName());
+
+                Field f = null;
+                f = c.getField(fieldName);
+
+                store.reference(f);
+
+                write(reference, "GetStaticFieldID " + store.getIdentifier(f));
+            } else if (message.startsWith("GetStaticField")) {
+                String[] args = message.split(" ");
+                String type = parseCall(args[1], null, String.class);
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Integer fieldID = parseCall(args[2], null, Integer.class);
+
+                final Class<?> c = (Class<?>) store.getObject(classID);
+                final Field f = (Field) store.getObject(fieldID);
+
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+                checkPermission(src, c, acc);
+
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            return f.get(c);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                if (ret == null) {
+                    write(reference, "GetStaticField literalreturn null");
+                } else if (f.getType() == Boolean.TYPE
+                        || f.getType() == Byte.TYPE
+                        || f.getType() == Short.TYPE
+                        || f.getType() == Integer.TYPE
+                        || f.getType() == Long.TYPE) {
+                    write(reference, "GetStaticField literalreturn " + ret);
+                } else if (f.getType() == Float.TYPE
+                                || f.getType() == Double.TYPE) {
+                    write(reference, "GetStaticField literalreturn " + String.format("%308.308e", ret));
+                } else if (f.getType() == Character.TYPE) {
+                    write(reference, "GetStaticField literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetStaticField " + store.getIdentifier(ret));
+                }
+            } else if (message.startsWith("GetValue")) {
+                String[] args = message.split(" ");
+                Integer index = parseCall(args[1], null, Integer.class);
+
+                Object ret = store.getObject(index);
+
+                if (ret == null) {
+                    write(reference, "GetValue literalreturn null");
+                } else if (ret.getClass() == Boolean.TYPE
+                        || ret.getClass() == Boolean.class
+                        || ret.getClass() == Byte.TYPE
+                        || ret.getClass() == Byte.class
+                        || ret.getClass() == Short.TYPE
+                        || ret.getClass() == Short.class
+                        || ret.getClass() == Integer.TYPE
+                        || ret.getClass() == Integer.class
+                        || ret.getClass() == Long.TYPE
+                        || ret.getClass() == Long.class) {
+                    write(reference, "GetValue literalreturn " + ret);
+                } else if (ret.getClass() == Float.TYPE
+                        || ret.getClass() == Float.class
+                        || ret.getClass() == Double.TYPE
+                        || ret.getClass() == Double.class) {
+                    write(reference, "GetValue literalreturn " + String.format("%308.308e", ret));
+                } else if (ret.getClass() == Character.TYPE
+                        || ret.getClass() == Character.class) {
+                    write(reference, "GetValue literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetValue " + store.getIdentifier(ret));
+                }
+            } else if (message.startsWith("SetStaticField") ||
+                                   message.startsWith("SetField")) {
+                String[] args = message.split(" ");
+                Integer classOrObjectID = parseCall(args[1], null, Integer.class);
+                Integer fieldID = parseCall(args[2], null, Integer.class);
+                Object value = store.getObject(parseCall(args[3], null, Integer.class));
+
+                final Object o = store.getObject(classOrObjectID);
+                final Field f = (Field) store.getObject(fieldID);
+
+                final Object fValue = MethodOverloadResolver.getCostAndCastedObject(value, f.getType())[1];
+
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+                checkPermission(src,
+                                                message.startsWith("SetStaticField") ? (Class) o : o.getClass(),
+                                                acc);
+
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            f.set(o, fValue);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+
+                        return null;
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                write(reference, "SetField");
+            } else if (message.startsWith("GetObjectArrayElement")) {
+                String[] args = message.split(" ");
+                Integer arrayID = parseCall(args[1], null, Integer.class);
+                Integer index = parseCall(args[2], null, Integer.class);
+
+                Object ret = Array.get(store.getObject(arrayID), index);
+                Class retClass = store.getObject(arrayID).getClass().getComponentType(); // prevent auto-boxing influence
+
+                if (ret == null) {
+                    write(reference, "GetObjectArrayElement literalreturn null");
+                } else if (retClass == Boolean.TYPE
+                        || retClass == Byte.TYPE
+                        || retClass == Short.TYPE
+                        || retClass == Integer.TYPE
+                        || retClass == Long.TYPE) {
+                    write(reference, "GetObjectArrayElement literalreturn " + ret);
+                } else if (retClass == Float.TYPE
+                                || retClass == Double.TYPE) {
+                    write(reference, "GetObjectArrayElement literalreturn " + String.format("%308.308e", ret));
+                } else if (retClass == Character.TYPE) {
+                    write(reference, "GetObjectArrayElement literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetObjectArrayElement " + store.getIdentifier(ret));
+                }
+
+            } else if (message.startsWith("SetObjectArrayElement")) {
+                String[] args = message.split(" ");
+                Integer arrayID = parseCall(args[1], null, Integer.class);
+                Integer index = parseCall(args[2], null, Integer.class);
+                Integer objectID = parseCall(args[3], null, Integer.class);
+
+                Object value = store.getObject(objectID);
+
+                // Cast the object to appropriate type before insertion
+                value = MethodOverloadResolver.getCostAndCastedObject(value, store.getObject(arrayID).getClass().getComponentType())[1];
+
+                Array.set(store.getObject(arrayID), index, value);
+
+                write(reference, "SetObjectArrayElement");
+            } else if (message.startsWith("GetArrayLength")) {
+                String[] args = message.split(" ");
+                Integer arrayID = parseCall(args[1], null, Integer.class);
+
+                Object o = store.getObject(arrayID);
+                int len = 0;
+                len = Array.getLength(o);
+
+                write(reference, "GetArrayLength " + Array.getLength(o));
+            } else if (message.startsWith("GetField")) {
+                String[] args = message.split(" ");
+                String type = parseCall(args[1], null, String.class);
+                Integer objectID = parseCall(args[1], null, Integer.class);
+                Integer fieldID = parseCall(args[2], null, Integer.class);
+
+                final Object o = store.getObject(objectID);
+                final Field f = (Field) store.getObject(fieldID);
+
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+                checkPermission(src, o.getClass(), acc);
+
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            return f.get(o);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                if (ret == null) {
+                    write(reference, "GetField literalreturn null");
+                } else if (f.getType() == Boolean.TYPE
+                        || f.getType() == Byte.TYPE
+                        || f.getType() == Short.TYPE
+                        || f.getType() == Integer.TYPE
+                        || f.getType() == Long.TYPE) {
+                    write(reference, "GetField literalreturn " + ret);
+                } else if (f.getType() == Float.TYPE
+                                || f.getType() == Double.TYPE) {
+                    write(reference, "GetField literalreturn " + String.format("%308.308e", ret));
+                } else if (f.getType() == Character.TYPE) {
+                    write(reference, "GetField literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetField " + store.getIdentifier(ret));
+                }
+
+            } else if (message.startsWith("GetObjectClass")) {
+                int oid = Integer.parseInt(message.substring("GetObjectClass"
+                                                .length() + 1));
+                Class<?> c = store.getObject(oid).getClass();
+                store.reference(c);
+
+                write(reference, "GetObjectClass " + store.getIdentifier(c));
+            } else if (message.startsWith("CallMethod") ||
+                                           message.startsWith("CallStaticMethod")) {
+                String[] args = message.split(" ");
+                Integer objectID = parseCall(args[1], null, Integer.class);
+                String methodName = parseCall(args[2], null, String.class);
+                Object o = null;
+                Class<?> c;
+
+                if (message.startsWith("CallMethod")) {
+                    o = store.getObject(objectID);
+                    c = o.getClass();
+                } else {
+                    c = (Class<?>) store.getObject(objectID);
+                }
+
+                // length -3 to discard first 3, + 2 for holding object
+                // and method name
+                Object[] arguments = new Object[args.length - 1];
+                arguments[0] = c;
+                arguments[1] = methodName;
+                for (int i = 0; i < args.length - 3; i++) {
+                    arguments[i + 2] = store.getObject(parseCall(args[3 + i], null, Integer.class));
+                    PluginDebug.debug("GOT ARG: ", arguments[i + 2]);
+                }
+
+                Object[] matchingMethodAndArgs = MethodOverloadResolver.getMatchingMethod(arguments);
+
+                if (matchingMethodAndArgs == null) {
+                    write(reference, "Error: No suitable method named " + methodName + " with matching args found");
+                    return;
+                }
+
+                final Method m = (Method) matchingMethodAndArgs[0];
+                Object[] castedArgs = new Object[matchingMethodAndArgs.length - 1];
+                for (int i = 0; i < castedArgs.length; i++) {
+                    castedArgs[i] = matchingMethodAndArgs[i + 1];
+                }
+
+                String collapsedArgs = "";
+                for (Object arg : castedArgs) {
+                    collapsedArgs += " " + arg;
+                }
+
+                PluginDebug.debug("Calling method ", m, " on object ", o
+                                                , " (", c, ") with ", collapsedArgs);
+
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+                checkPermission(src, c, acc);
+
+                final Object[] fArguments = castedArgs;
+                final Object callableObject = o;
+                // Set the method accessible prior to calling. See:
+                // http://forums.sun.com/thread.jspa?threadID=332001&start=15&tstart=0
+                m.setAccessible(true);
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            return m.invoke(callableObject, fArguments);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                String retO;
+                if (ret == null) {
+                    retO = "null";
+                } else {
+                    retO = m.getReturnType().toString();
+                }
+
+                PluginDebug.debug("Calling ", m, " on ", o, " with "
+                                                , collapsedArgs, " and that returned: ", ret
+                                                , " of type ", retO);
+
+                if (m.getReturnType().equals(java.lang.Void.class) ||
+                                    m.getReturnType().equals(java.lang.Void.TYPE)) {
+                    write(reference, "CallMethod literalreturn void");
+                } else if (ret == null) {
+                    write(reference, "CallMethod literalreturn null");
+                } else if (m.getReturnType() == Boolean.TYPE
+                                                || m.getReturnType() == Byte.TYPE
+                                                || m.getReturnType() == Short.TYPE
+                                                || m.getReturnType() == Integer.TYPE
+                                                || m.getReturnType() == Long.TYPE) {
+                    write(reference, "CallMethod literalreturn " + ret);
+                } else if (m.getReturnType() == Float.TYPE
+                                || m.getReturnType() == Double.TYPE) {
+                    write(reference, "CallMethod literalreturn " + String.format("%308.308e", ret));
+                } else if (m.getReturnType() == Character.TYPE) {
+                    write(reference, "CallMethod literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "CallMethod " + store.getIdentifier(ret));
+                }
+            } else if (message.startsWith("GetSuperclass")) {
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Class<?> c = null;
+                Class<?> ret = null;
+
+                c = (Class) store.getObject(classID);
+                ret = c.getSuperclass();
+                store.reference(ret);
+
+                write(reference, "GetSuperclass " + store.getIdentifier(ret));
+            } else if (message.startsWith("IsAssignableFrom")) {
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Integer superclassID = parseCall(args[2], null, Integer.class);
+
+                boolean result = false;
+                Class<?> clz = (Class<?>) store.getObject(classID);
+                Class<?> sup = (Class<?>) store.getObject(superclassID);
+
+                result = sup.isAssignableFrom(clz);
+
+                write(reference, "IsAssignableFrom " + (result ? "1" : "0"));
+            } else if (message.startsWith("IsInstanceOf")) {
+                String[] args = message.split(" ");
+                Integer objectID = parseCall(args[1], null, Integer.class);
+                Integer classID = parseCall(args[2], null, Integer.class);
+
+                boolean result = false;
+                Object o = store.getObject(objectID);
+                Class<?> c = (Class<?>) store.getObject(classID);
+
+                result = c.isInstance(o);
+
+                write(reference, "IsInstanceOf " + (result ? "1" : "0"));
+            } else if (message.startsWith("GetStringUTFLength")) {
+                String[] args = message.split(" ");
+                Integer stringID = parseCall(args[1], null, Integer.class);
+
+                String o = null;
+                byte[] b = null;
+                o = (String) store.getObject(stringID);
+                b = o.getBytes("UTF-8");
+
+                write(reference, "GetStringUTFLength " + o.length());
+            } else if (message.startsWith("GetStringLength")) {
+                String[] args = message.split(" ");
+                Integer stringID = parseCall(args[1], null, Integer.class);
+
+                String o = null;
+                byte[] b = null;
+                o = (String) store.getObject(stringID);
+                b = o.getBytes("UTF-16LE");
+
+                write(reference, "GetStringLength " + o.length());
+            } else if (message.startsWith("GetStringUTFChars")) {
+                String[] args = message.split(" ");
+                Integer stringID = parseCall(args[1], null, Integer.class);
+
+                String o = null;
+                byte[] b = null;
+                StringBuffer buf = null;
+                o = (String) store.getObject(stringID);
+                b = o.getBytes("UTF-8");
+                buf = new StringBuffer(b.length * 2);
+                buf.append(b.length);
+                for (int i = 0; i < b.length; i++)
+                    buf
+                                                        .append(" "
+                                                                        + Integer
+                                                                                        .toString(((int) b[i]) & 0x0ff, 16));
+
+                write(reference, "GetStringUTFChars " + buf);
+            } else if (message.startsWith("GetStringChars")) {
+                String[] args = message.split(" ");
+                Integer stringID = parseCall(args[1], null, Integer.class);
+
+                String o = null;
+                byte[] b = null;
+                StringBuffer buf = null;
+                o = (String) store.getObject(stringID);
+                // FIXME: LiveConnect uses UCS-2.
+                b = o.getBytes("UTF-16LE");
+                buf = new StringBuffer(b.length * 2);
+                buf.append(b.length);
+                for (int i = 0; i < b.length; i++)
+                    buf
+                                                        .append(" "
+                                                                        + Integer
+                                                                                        .toString(((int) b[i]) & 0x0ff, 16));
+
+                PluginDebug.debug("Java: GetStringChars: ", o);
+                PluginDebug.debug("  String BYTES: ", buf);
+                write(reference, "GetStringChars " + buf);
+            } else if (message.startsWith("GetToStringValue")) {
+                String[] args = message.split(" ");
+                Integer objectID = parseCall(args[1], null, Integer.class);
+
+                String o = null;
+                byte[] b = null;
+                StringBuffer buf = null;
+                o = store.getObject(objectID).toString();
+                b = o.getBytes("UTF-8");
+                buf = new StringBuffer(b.length * 2);
+                buf.append(b.length);
+                for (int i = 0; i < b.length; i++)
+                    buf
+                            .append(" "
+                                    + Integer
+                                            .toString(((int) b[i]) & 0x0ff, 16));
+
+                write(reference, "GetToStringValue " + buf);
+            } else if (message.startsWith("NewArray")) {
+                String[] args = message.split(" ");
+                String type = parseCall(args[1], null, String.class);
+                Integer length = parseCall(args[2], null, Integer.class);
+
+                Object newArray = null;
+
+                Class c;
+                if (type.equals("bool")) {
+                    c = Boolean.class;
+                } else if (type.equals("double")) {
+                    c = Double.class;
+                } else if (type.equals("int")) {
+                    c = Integer.class;
+                } else if (type.equals("string")) {
+                    c = String.class;
+                } else if (isInt(type)) {
+                    c = (Class<?>) store.getObject(Integer.parseInt(type));
+                } else {
+                    c = JSObject.class;
+                }
+
+                if (args.length > 3)
+                    newArray = Array.newInstance(c, new int[] { length, parseCall(args[3], null, Integer.class) });
+                else
+                    newArray = Array.newInstance(c, length);
+
+                store.reference(newArray);
+                write(reference, "NewArray " + store.getIdentifier(newArray));
+            } else if (message.startsWith("HasMethod")) {
+                String[] args = message.split(" ");
+                Integer classNameID = parseCall(args[1], null, Integer.class);
+                Integer methodNameID = parseCall(args[2], null, Integer.class);
+
+                Class c = (Class<?>) store.getObject(classNameID);
+                String methodName = (String) store.getObject(methodNameID);
+
+                Method method = null;
+                Method[] classMethods = c.getMethods();
+                for (Method m : classMethods) {
+                    if (m.getName().equals(methodName)) {
+                        method = m;
+                        break;
+                    }
+                }
+
+                int hasMethod = (method != null) ? 1 : 0;
+
+                write(reference, "HasMethod " + hasMethod);
+            } else if (message.startsWith("HasPackage")) {
+                String[] args = message.split(" ");
+                Integer instance = parseCall(args[1], null, Integer.class);
+                Integer nameID = parseCall(args[2], null, Integer.class);
+                String pkgName = (String) store.getObject(nameID);
+
+                Package pkg = Package.getPackage(pkgName);
+                int hasPkg = (pkg != null) ? 1 : 0;
+
+                write(reference, "HasPackage " + hasPkg);
+
+            } else if (message.startsWith("HasField")) {
+                String[] args = message.split(" ");
+                Integer classNameID = parseCall(args[1], null, Integer.class);
+                Integer fieldNameID = parseCall(args[2], null, Integer.class);
+
+                Class c = (Class) store.getObject(classNameID);
+                String fieldName = (String) store.getObject(fieldNameID);
+
+                Field field = null;
+                Field[] classFields = c.getFields();
+                for (Field f : classFields) {
+                    if (f.getName().equals(fieldName)) {
+                        field = f;
+                        break;
+                    }
+                }
+
+                int hasField = (field != null) ? 1 : 0;
+
+                write(reference, "HasField " + hasField);
+            } else if (message.startsWith("NewObjectArray")) {
+                String[] args = message.split(" ");
+                Integer length = parseCall(args[1], null, Integer.class);
+                Integer classID = parseCall(args[2], null, Integer.class);
+                Integer objectID = parseCall(args[3], null, Integer.class);
+
+                Object newArray = null;
+                newArray = Array.newInstance((Class) store.getObject(classID),
+                                                length);
+
+                Object[] array = (Object[]) newArray;
+                for (int i = 0; i < array.length; i++)
+                    array[i] = store.getObject(objectID);
+                store.reference(newArray);
+                write(reference, "NewObjectArray "
+                                                + store.getIdentifier(newArray));
+            } else if (message.startsWith("NewObjectWithConstructor")) {
+
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Integer methodID = parseCall(args[2], null, Integer.class);
+
+                final Constructor m = (Constructor) store.getObject(methodID);
+                Class[] argTypes = m.getParameterTypes();
+
+                Object[] arguments = new Object[argTypes.length];
+                for (int i = 0; i < argTypes.length; i++) {
+                    arguments[i] = parseArgs(args[3 + i], argTypes[i]);
+                }
+
+                final Object[] fArguments = arguments;
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+
+                Class c = (Class) store.getObject(classID);
+                checkPermission(src, c, acc);
+
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            return m.newInstance(fArguments);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                store.reference(ret);
+
+                write(reference, "NewObject " + store.getIdentifier(ret));
+
+            } else if (message.startsWith("NewObject")) {
+                String[] args = message.split(" ");
+                Integer classID = parseCall(args[1], null, Integer.class);
+                Class c = (Class) store.getObject(classID);
+                final Constructor cons;
+                final Object[] fArguments;
+
+                Object[] arguments = new Object[args.length - 1];
+                arguments[0] = c;
+                for (int i = 0; i < args.length - 2; i++) {
+                    arguments[i + 1] = store.getObject(parseCall(args[2 + i],
+                            null, Integer.class));
+                    PluginDebug.debug("GOT ARG: ", arguments[i + 1]);
+                }
+
+                Object[] matchingConstructorAndArgs = MethodOverloadResolver
+                        .getMatchingConstructor(arguments);
+
+                if (matchingConstructorAndArgs == null) {
+                    write(reference,
+                            "Error: No suitable constructor with matching args found");
+                    return;
+                }
+
+                Object[] castedArgs = new Object[matchingConstructorAndArgs.length - 1];
+                for (int i = 0; i < castedArgs.length; i++) {
+                    castedArgs[i] = matchingConstructorAndArgs[i + 1];
+                }
+
+                cons = (Constructor) matchingConstructorAndArgs[0];
+                fArguments = castedArgs;
+
+                String collapsedArgs = "";
+                for (Object arg : fArguments) {
+                    collapsedArgs += " " + arg.toString();
+                }
+
+                PluginDebug.debug("Calling constructor on class ", c,
+                                   " with ", collapsedArgs);
+
+                AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
+                checkPermission(src, c, acc);
+
+                Object ret = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        try {
+                            return cons.newInstance(fArguments);
+                        } catch (Throwable t) {
+                            return t;
+                        }
+                    }
+                }, acc);
+
+                if (ret instanceof Throwable)
+                    throw (Throwable) ret;
+
+                store.reference(ret);
+
+                write(reference, "NewObject " + store.getIdentifier(ret));
+
+            } else if (message.startsWith("NewStringUTF")) {
+                PluginDebug.debug("MESSAGE: ", message);
+                String[] args = message.split(" ");
+                int length = new Integer(args[1]);
+                byte[] byteArray = new byte[length];
+                String ret = null;
+                int i = 0;
+                int j = 2;
+                int c;
+                while (i < length) {
+                    c = Integer.parseInt(args[j++], 16);
+                    byteArray[i++] = (byte) c;
+                }
+
+                ret = new String(byteArray, "UTF-8");
+                PluginDebug.debug("NEWSTRINGUTF: ", ret);
+
+                store.reference(ret);
+                write(reference, "NewStringUTF " + store.getIdentifier(ret));
+            } else if (message.startsWith("NewString")) {
+                PluginDebug.debug("MESSAGE: ", message);
+                String[] args = message.split(" ");
+                Integer strlength = parseCall(args[1], null, Integer.class);
+                int bytelength = 2 * strlength;
+                byte[] byteArray = new byte[bytelength];
+                String ret = null;
+                for (int i = 0; i < strlength; i++) {
+                    int c = parseCall(args[2 + i], null, Integer.class);
+                    PluginDebug.debug("char ", i, " ", c);
+                    // Low.
+                    byteArray[2 * i] = (byte) (c & 0x0ff);
+                    // High.
+                    byteArray[2 * i + 1] = (byte) ((c >> 8) & 0x0ff);
+                }
+                ret = new String(byteArray, 0, bytelength, "UTF-16LE");
+                PluginDebug.debug("NEWSTRING: ", ret);
+
+                store.reference(ret);
+                write(reference, "NewString " + store.getIdentifier(ret));
+
+            } else if (message.startsWith("ExceptionOccurred")) {
+                PluginDebug.debug("EXCEPTION: ", throwable);
+                if (throwable != null)
+                    store.reference(throwable);
+                write(reference, "ExceptionOccurred "
+                                                + store.getIdentifier(throwable));
+            } else if (message.startsWith("ExceptionClear")) {
+                if (throwable != null && store.contains(throwable))
+                    store.unreference(store.getIdentifier(throwable));
+                throwable = null;
+                write(reference, "ExceptionClear");
+            } else if (message.startsWith("DeleteGlobalRef")) {
+                String[] args = message.split(" ");
+                Integer id = parseCall(args[1], null, Integer.class);
+                store.unreference(id);
+                write(reference, "DeleteGlobalRef");
+            } else if (message.startsWith("DeleteLocalRef")) {
+                String[] args = message.split(" ");
+                Integer id = parseCall(args[1], null, Integer.class);
+                store.unreference(id);
+                write(reference, "DeleteLocalRef");
+            } else if (message.startsWith("NewGlobalRef")) {
+                String[] args = message.split(" ");
+                Integer id = parseCall(args[1], null, Integer.class);
+                store.reference(store.getObject(id));
+                write(reference, "NewGlobalRef " + id);
+            } else if (message.startsWith("GetClassName")) {
+                String[] args = message.split(" ");
+                Integer objectID = parseCall(args[1], null, Integer.class);
+                Object o = store.getObject(objectID);
+                write(reference, "GetClassName " + o.getClass().getName());
+            } else if (message.startsWith("GetClassID")) {
+                String[] args = message.split(" ");
+                Integer objectID = parseCall(args[1], null, Integer.class);
+                store.reference(store.getObject(objectID).getClass());
+                write(reference, "GetClassID " + store.getIdentifier(store.getObject(objectID).getClass()));
+            }
+        } catch (Throwable t) {
+            t.printStackTrace();
+            String msg = t.getCause() != null ? t.getCause().getMessage() : t.getMessage();
+
+            // add an identifier string to let javaside know of the type of error
+            // check for cause as well, since the top level exception will be InvocationTargetException in most cases
+            if (t instanceof AccessControlException || t.getCause() instanceof AccessControlException) {
+                msg = "LiveConnectPermissionNeeded " + msg;
+            }
+
+            write(reference, " Error " + msg);
+
+            // ExceptionOccured is only called after Callmethod() by mozilla. So
+            // for exceptions that are not related to CallMethod, we need a way
+            // to log them. This is how we do it.. send an error message to the
+            // c++ side to let it know that something went wrong, and it will do
+            // the right thing to let mozilla know
+
+            // Store the cause as the actual exception. This is needed because
+            // the exception we get here will always be an
+            // "InvocationTargetException" due to the use of reflection above
+            if (message.startsWith("CallMethod") || message.startsWith("CallStaticMethod"))
+                throwable = t.getCause();
+        }
+
+    }
+
+    /**
+     * Checks if the calling script is allowed to access the specified class
+     *
+     * @param jsSrc The source of the script
+     * @param target The target class that the script is trying to access
+     * @param acc AccessControlContext for this execution
+     * @throws AccessControlException If the script has insufficient permissions
+     */
+    public void checkPermission(String jsSrc, Class target, AccessControlContext acc) throws AccessControlException {
+        // NPRuntime does not allow cross-site calling. We therefore always
+        // allow this, for the time being
+        return;
+    }
+
+    private void write(int reference, String message) {
+        PluginDebug.debug("appletviewer writing ", message);
+        streamhandler.write("context " + identifier + " reference " + reference
+                                + " " + message);
+    }
+
+    public void prePopulateLCClasses() {
+
+        int classID;
+
+        prepopulateClass("netscape/javascript/JSObject");
+        classID = prepopulateClass("netscape/javascript/JSException");
+        prepopulateMethod(classID, "<init>", "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)");
+        prepopulateMethod(classID, "<init>", "(ILjava/lang/Object;)");
+        prepopulateField(classID, "lineno");
+        prepopulateField(classID, "tokenIndex");
+        prepopulateField(classID, "source");
+        prepopulateField(classID, "filename");
+        prepopulateField(classID, "wrappedExceptionType");
+        prepopulateField(classID, "wrappedException");
+
+        classID = prepopulateClass("netscape/javascript/JSUtil");
+        prepopulateMethod(classID, "getStackTrace", "(Ljava/lang/Throwable;)");
+
+        prepopulateClass("java/lang/Object");
+        classID = prepopulateClass("java/lang/Class");
+        prepopulateMethod(classID, "getMethods", "()");
+        prepopulateMethod(classID, "getConstructors", "()");
+        prepopulateMethod(classID, "getFields", "()");
+        prepopulateMethod(classID, "getName", "()");
+        prepopulateMethod(classID, "isArray", "()");
+        prepopulateMethod(classID, "getComponentType", "()");
+        prepopulateMethod(classID, "getModifiers", "()");
+
+        classID = prepopulateClass("java/lang/reflect/Method");
+        prepopulateMethod(classID, "getName", "()");
+        prepopulateMethod(classID, "getParameterTypes", "()");
+        prepopulateMethod(classID, "getReturnType", "()");
+        prepopulateMethod(classID, "getModifiers", "()");
+
+        classID = prepopulateClass("java/lang/reflect/Constructor");
+        prepopulateMethod(classID, "getParameterTypes", "()");
+        prepopulateMethod(classID, "getModifiers", "()");
+
+        classID = prepopulateClass("java/lang/reflect/Field");
+        prepopulateMethod(classID, "getName", "()");
+        prepopulateMethod(classID, "getType", "()");
+        prepopulateMethod(classID, "getModifiers", "()");
+
+        classID = prepopulateClass("java/lang/reflect/Array");
+        prepopulateMethod(classID, "newInstance", "(Ljava/lang/Class;I)");
+
+        classID = prepopulateClass("java/lang/Throwable");
+        prepopulateMethod(classID, "toString", "()");
+        prepopulateMethod(classID, "getMessage", "()");
+
+        classID = prepopulateClass("java/lang/System");
+        prepopulateMethod(classID, "identityHashCode", "(Ljava/lang/Object;)");
+
+        classID = prepopulateClass("java/lang/Boolean");
+        prepopulateMethod(classID, "booleanValue", "()");
+        prepopulateMethod(classID, "<init>", "(Z)");
+
+        classID = prepopulateClass("java/lang/Double");
+        prepopulateMethod(classID, "doubleValue", "()");
+        prepopulateMethod(classID, "<init>", "(D)");
+
+        classID = prepopulateClass("java/lang/Void");
+        prepopulateField(classID, "TYPE");
+
+        prepopulateClass("java/lang/String");
+        prepopulateClass("java/applet/Applet");
+    }
+
+    private int prepopulateClass(String name) {
+        name = name.replace('/', '.');
+        ClassLoader cl = liveconnectLoader;
+        Class c = null;
+
+        try {
+            c = cl.loadClass(name);
+            store.reference(c);
+        } catch (ClassNotFoundException cnfe) {
+            // do nothing ... this should never happen
+            cnfe.printStackTrace();
+        }
+
+        return store.getIdentifier(c);
+    }
+
+    private int prepopulateMethod(int classID, String methodName, String signatureStr) {
+        Signature signature = parseCall(signatureStr, ((Class) store.getObject(classID)).getClassLoader(), Signature.class);
+        Object[] a = signature.getClassArray();
+
+        Class<?> c = (Class<?>) store.getObject(classID);
+        Method m = null;
+        Constructor cs = null;
+
+        try {
+            if (methodName.equals("<init>")
+                                        || methodName.equals("<clinit>")) {
+                cs = c.getConstructor(signature.getClassArray());
+                store.reference(cs);
+            } else {
+                m = c.getMethod(methodName, signature.getClassArray());
+                store.reference(m);
+            }
+        } catch (NoSuchMethodException e) {
+            // should never happen
+            e.printStackTrace();
+        }
+
+        return store.getIdentifier(m);
+    }
+
+    private int prepopulateField(int classID, String fieldName) {
+
+        Class<?> c = (Class<?>) store.getObject(classID);
+        Field f = null;
+        try {
+            f = c.getField(fieldName);
+        } catch (SecurityException e) {
+            // should never happen
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            // should never happen
+            e.printStackTrace();
+        }
+
+        store.reference(f);
+        return store.getIdentifier(f);
+    }
+
+    public void dumpStore() {
+        store.dump();
+    }
+
+    public Object getObject(int identifier) {
+        return store.getObject(identifier);
+    }
+
+    public int getIdentifier(Object o) {
+        return store.getIdentifier(o);
+    }
+
+    public void store(Object o) {
+        store.reference(o);
+    }
+
+    /**
+     * Returns a "closed" AccessControlContext i.e. no permissions to get out of sandbox.
+     */
+    public AccessControlContext getClosedAccessControlContext() {
+        // Deny everything
+        Permissions p = new Permissions();
+        ProtectionDomain pd = new ProtectionDomain(null, p);
+        return new AccessControlContext(new ProtectionDomain[] { pd });
+    }
+
+    public AccessControlContext getAccessControlContext(String[] nsPrivilegeList, String src) {
+
+        Permissions grantedPermissions = new Permissions();
+
+        for (int i = 0; i < nsPrivilegeList.length; i++) {
+            String privilege = nsPrivilegeList[i];
+
+            if (privilege.equals("UniversalBrowserRead")) {
+                BrowserReadPermission bp = new BrowserReadPermission();
+                grantedPermissions.add(bp);
+            } else if (privilege.equals("UniversalJavaPermission")) {
+                AllPermission ap = new AllPermission();
+                grantedPermissions.add(ap);
+            }
+        }
+
+        CodeSource cs = new CodeSource((URL) null, (java.security.cert.Certificate[]) null);
+
+        if (src != null && src.length() > 0) {
+            try {
+                cs = new CodeSource(new URL(src + "/"), (java.security.cert.Certificate[]) null);
+            } catch (MalformedURLException mfue) {
+                // do nothing
+            }
+
+            if (src.equals("[System]"))
+                grantedPermissions.add(new JSObjectCreatePermission());
+
+        } else {
+            JSObjectCreatePermission perm = new JSObjectCreatePermission();
+            grantedPermissions.add(perm);
+        }
+
+        ProtectionDomain pd = new ProtectionDomain(cs, grantedPermissions, null, null);
+
+        // Add to hashmap
+        return new AccessControlContext(new ProtectionDomain[] { pd });
+    }
+
+    // private static final == inline
+    private static final boolean isInt(Object o) {
+        boolean isInt = false;
+
+        try {
+            Integer.parseInt((String) o);
+            isInt = true;
+        } catch (Exception e) {
+            // don't care
+        }
+
+        return isInt;
+    }
+
+    class BrowserReadPermission extends BasicPermission {
+        public BrowserReadPermission() {
+            super("browserRead");
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	(revision 403)
@@ -0,0 +1,2128 @@
+/* PluginAppletViewer -- Handles embedding of the applet panel
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+/*
+  * Copyright 1995-2004 Sun Microsystems, Inc.  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.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */
+
+package sun.applet;
+
+import java.applet.Applet;
+import java.applet.AppletContext;
+import java.applet.AudioClip;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.SocketPermission;
+import java.net.URI;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.NetxPanel;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader;
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+import sun.misc.Ref;
+
+import com.sun.jndi.toolkit.url.UrlUtil;
+
+/**
+ * Lets us construct one using unix-style one shot behaviors
+ */
+
+class PluginAppletPanelFactory {
+
+    public AppletPanel createPanel(PluginStreamHandler streamhandler,
+                                    int identifier,
+                                    long handle, int x, int y,
+                                    final URL doc,
+                                    final Hashtable<String, String> atts) {
+        final NetxPanel panel = AccessController.doPrivileged(new PrivilegedAction<NetxPanel>() {
+            public NetxPanel run() {
+                NetxPanel panel = new NetxPanel(doc, atts, false);
+                NetxPanel.debug("Using NetX panel");
+                PluginDebug.debug(atts.toString());
+                return panel;
+            }
+        });
+
+        // create the frame.
+        PluginAppletViewer.framePanel(identifier, handle, panel);
+
+        panel.init();
+
+        // Start the applet
+        initEventQueue(panel);
+
+        // Wait for the panel to initialize
+        PluginAppletViewer.waitForAppletInit(panel);
+
+        Applet a = panel.getApplet();
+
+        // Still null?
+        if (a == null) {
+            streamhandler.write("instance " + identifier + " reference " + -1 + " fatalError: " + "Initialization timed out");
+            return null;
+        }
+
+        PluginDebug.debug("Applet ", a.getClass(), " initialized");
+        streamhandler.write("instance " + identifier + " reference 0 initialized");
+
+        /* AppletViewerPanel sometimes doesn't set size right initially. This 
+         * causes the parent frame to be the default (10x10) size.
+         *  
+         * Normally it goes unnoticed since browsers like Firefox make a resize 
+         * call after init. However some browsers (e.g. Midori) don't.
+         * 
+         * We therefore manually set the parent to the right size.
+         */
+        try {
+            SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    panel.getParent().setSize(Integer.valueOf(atts.get("width")), Integer.valueOf(atts.get("height")));
+                }
+            });
+        } catch (InvocationTargetException ite) {
+            // Not being able to resize is non-fatal
+            PluginDebug.debug("Unable to resize panel: ");
+            ite.printStackTrace();
+        } catch (InterruptedException ie) {
+            // Not being able to resize is non-fatal
+            PluginDebug.debug("Unable to resize panel: ");
+            ie.printStackTrace();
+        }
+
+        AppletSecurityContextManager.getSecurityContext(0).associateSrc(panel.getAppletClassLoader(), doc);
+        AppletSecurityContextManager.getSecurityContext(0).associateInstance(identifier, panel.getAppletClassLoader());
+
+        return panel;
+    }
+
+    public boolean isStandalone() {
+        return false;
+    }
+
+    /**
+     * Send the initial set of events to the appletviewer event queue.
+     * On start-up the current behaviour is to load the applet and call
+     * Applet.init() and Applet.start().
+     */
+    private void initEventQueue(AppletPanel panel) {
+        // appletviewer.send.event is an undocumented and unsupported system
+        // property which is used exclusively for testing purposes.
+        PrivilegedAction<String> pa = new PrivilegedAction<String>() {
+            public String run() {
+                return System.getProperty("appletviewer.send.event");
+            }
+        };
+        String eventList = AccessController.doPrivileged(pa);
+
+        if (eventList == null) {
+            // Add the standard events onto the event queue.
+            panel.sendEvent(AppletPanel.APPLET_LOAD);
+            panel.sendEvent(AppletPanel.APPLET_INIT);
+            panel.sendEvent(AppletPanel.APPLET_START);
+        } else {
+            // We're testing AppletViewer.  Force the specified set of events
+            // onto the event queue, wait for the events to be processed, and
+            // exit.
+
+            // The list of events that will be executed is provided as a
+            // ","-separated list.  No error-checking will be done on the list.
+            String[] events = eventList.split(",");
+
+            for (int i = 0; i < events.length; i++) {
+                PluginDebug.debug("Adding event to queue: ", events[i]);
+                if (events[i].equals("dispose"))
+                    panel.sendEvent(AppletPanel.APPLET_DISPOSE);
+                else if (events[i].equals("load"))
+                    panel.sendEvent(AppletPanel.APPLET_LOAD);
+                else if (events[i].equals("init"))
+                    panel.sendEvent(AppletPanel.APPLET_INIT);
+                else if (events[i].equals("start"))
+                    panel.sendEvent(AppletPanel.APPLET_START);
+                else if (events[i].equals("stop"))
+                    panel.sendEvent(AppletPanel.APPLET_STOP);
+                else if (events[i].equals("destroy"))
+                    panel.sendEvent(AppletPanel.APPLET_DESTROY);
+                else if (events[i].equals("quit"))
+                    panel.sendEvent(AppletPanel.APPLET_QUIT);
+                else if (events[i].equals("error"))
+                    panel.sendEvent(AppletPanel.APPLET_ERROR);
+                else
+                    // non-fatal error if we get an unrecognized event
+                    PluginDebug.debug("Unrecognized event name: ", events[i]);
+            }
+
+            while (!panel.emptyEventQueue())
+                ;
+        }
+    }
+}
+
+/*
+ */
+// FIXME: declare JSProxy implementation
+@SuppressWarnings("serial")
+public class PluginAppletViewer extends PluginAppletViewerBase
+        implements AppletContext, Printable {
+
+    /**
+     *  Enumerates the current status of an applet
+     *
+     *  PRE_INIT -> Parsing and initialization phase
+     *  INIT_COMPLETE -> Initialization complete, reframe pending
+     *  REFRAME_COMPLETE -> Reframe complete, applet is initialized and usable by the user
+     *  INACTIVE -> Browser has directed that the applet be destroyed (this state is non-overridable except by DESTROYED)
+     *  DESTROYED -> Applet has been destroyed
+     */
+    private static enum PAV_INIT_STATUS {
+        PRE_INIT, INIT_COMPLETE, REFRAME_COMPLETE, INACTIVE, DESTROYED
+    };
+
+    /**
+     * The panel in which the applet is being displayed.
+     */
+    private NetxPanel panel;
+    static final ReentrantLock panelLock = new ReentrantLock();
+    // CONDITION PREDICATE: panel.isAlive()
+    static final Condition panelLive = panelLock.newCondition();
+    private int identifier;
+
+    // Instance identifier -> PluginAppletViewer object.
+    private static ConcurrentMap<Integer, PluginAppletViewer> applets =
+            new ConcurrentHashMap<Integer, PluginAppletViewer>();
+    private static final ReentrantLock appletsLock = new ReentrantLock();
+    // CONDITION PREDICATE: !applets.containsKey(identifier)
+    private static final Condition appletAdded = appletsLock.newCondition();
+
+    private static PluginStreamHandler streamhandler;
+
+    private static PluginCallRequestFactory requestFactory;
+
+    private static ConcurrentMap<Integer, PAV_INIT_STATUS> status =
+            new ConcurrentHashMap<Integer, PAV_INIT_STATUS>();
+    private static final ReentrantLock statusLock = new ReentrantLock();
+    // CONDITION PREDICATE: !status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE)
+    private static final Condition initComplete = statusLock.newCondition();
+
+    private WindowListener windowEventListener = null;
+    private AppletEventListener appletEventListener = null;
+
+    public static final long APPLET_TIMEOUT = 180000000000L; // 180s in ns
+
+    private static final Object requestMutex = new Object();
+    private static long requestIdentityCounter = 0L;
+
+    private Image bufFrameImg;
+    private Graphics bufFrameImgGraphics;
+
+    /**
+     * Null constructor to allow instantiation via newInstance()
+     */
+    public PluginAppletViewer() {
+    }
+
+    public static void framePanel(int identifier, long handle, NetxPanel panel) {
+
+        PluginDebug.debug("Framing ", panel);
+
+        // SecurityManager MUST be set, and only privileged code may call reFrame()
+        System.getSecurityManager().checkPermission(new AllPermission());
+
+        PluginAppletViewer appletFrame = new PluginAppletViewer(handle, identifier, panel);
+
+        appletFrame.add("Center", panel);
+        appletFrame.pack();
+
+        appletFrame.appletEventListener = new AppletEventListener(appletFrame, appletFrame);
+        panel.addAppletListener(appletFrame.appletEventListener);
+
+        appletsLock.lock();
+        applets.put(identifier, appletFrame);
+        appletAdded.signalAll();
+        appletsLock.unlock();
+
+        PluginDebug.debug(panel, " framed");
+    }
+
+    /**
+     * Create new plugin appletviewer frame
+     */
+    private PluginAppletViewer(long handle, final int identifier,
+                               NetxPanel appletPanel) {
+
+        super(handle);
+        this.identifier = identifier;
+        this.panel = appletPanel;
+
+        synchronized(appletPanels) {
+            if (!appletPanels.contains(panel))
+                appletPanels.addElement(panel);
+        }
+
+        windowEventListener = new WindowAdapter() {
+
+            public void windowClosing(WindowEvent evt) {
+                destroyApplet(identifier);
+            }
+
+            public void windowIconified(WindowEvent evt) {
+                appletStop();
+            }
+
+            public void windowDeiconified(WindowEvent evt) {
+                appletStart();
+            }
+        };
+
+        addWindowListener(windowEventListener);
+
+    }
+
+    private static class AppletEventListener implements AppletListener {
+        final Frame frame;
+        final PluginAppletViewer appletViewer;
+
+        public AppletEventListener(Frame frame, PluginAppletViewer appletViewer) {
+            this.frame = frame;
+            this.appletViewer = appletViewer;
+        }
+
+        public void appletStateChanged(AppletEvent evt) {
+            AppletPanel src = (AppletPanel) evt.getSource();
+
+            panelLock.lock();
+            panelLive.signalAll();
+            panelLock.unlock();
+
+            switch (evt.getID()) {
+                case AppletPanel.APPLET_RESIZE: {
+                    if (src != null) {
+                        appletViewer.setSize(appletViewer.getPreferredSize());
+                        appletViewer.validate();
+                    }
+                    break;
+                }
+                case AppletPanel.APPLET_LOADING_COMPLETED: {
+                    Applet a = src.getApplet(); // sun.applet.AppletPanel
+
+                    // Fixed #4754451: Applet can have methods running on main
+                    // thread event queue.
+                    //
+                    // The cause of this bug is that the frame of the applet
+                    // is created in main thread group. Thus, when certain
+                    // AWT/Swing events are generated, the events will be
+                    // dispatched through the wrong event dispatch thread.
+                    //
+                    // To fix this, we rearrange the AppContext with the frame,
+                    // so the proper event queue will be looked up.
+                    //
+                    // Swing also maintains a Frame list for the AppContext,
+                    // so we will have to rearrange it as well.
+                    //
+                    if (a != null)
+                        AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a));
+                    else
+                        AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext());
+
+                    updateStatus(appletViewer.identifier, PAV_INIT_STATUS.INIT_COMPLETE);
+
+                    break;
+                }
+            }
+        }
+    }
+
+    public static void setStreamhandler(PluginStreamHandler sh) {
+        streamhandler = sh;
+    }
+
+    public static void setPluginCallRequestFactory(PluginCallRequestFactory rf) {
+        requestFactory = rf;
+    }
+
+    /**
+     * Handle an incoming message from the plugin.
+     */
+    public static void handleMessage(int identifier, int reference, String message) {
+
+        PluginDebug.debug("PAV handling: ", message);
+
+        try {
+            if (message.startsWith("handle")) {
+
+                // If there is a key for this status, it means it
+                // was either initialized before, or destroy has been
+                // processed. Stop moving further.
+                if (updateStatus(identifier, PAV_INIT_STATUS.PRE_INIT) != null)
+                    return;
+
+                // Extract the information from the message
+                String[] msgParts = new String[4];
+                for (int i = 0; i < 3; i++) {
+                    int spaceLocation = message.indexOf(' ');
+                    int nextSpaceLocation = message.indexOf(' ', spaceLocation + 1);
+                    msgParts[i] = message.substring(spaceLocation + 1, nextSpaceLocation);
+                    message = message.substring(nextSpaceLocation + 1);
+                }
+
+                long handle = Long.parseLong(msgParts[0]);
+                String width = msgParts[1];
+                String height = msgParts[2];
+
+                int spaceLocation = message.indexOf(' ', "tag".length() + 1);
+                String documentBase =
+                        UrlUtil.decode(message.substring("tag".length() + 1, spaceLocation));
+                String tag = message.substring(spaceLocation + 1);
+
+                PluginDebug.debug("Handle = ", handle, "\n",
+                                    "Width = ", width, "\n",
+                                    "Height = ", height, "\n",
+                                    "DocumentBase = ", documentBase, "\n",
+                                    "Tag = ", tag);
+
+                PluginAppletViewer.parse
+                                        (identifier, handle, width, height,
+                                                new StringReader(tag),
+                                                new URL(documentBase));
+
+                long maxTimeToSleep = APPLET_TIMEOUT;
+                appletsLock.lock();
+                try {
+                    while (!applets.containsKey(identifier) &&
+                            maxTimeToSleep > 0) { // Map is populated only by reFrame
+                        maxTimeToSleep -= waitTillTimeout(appletsLock, appletAdded,
+                                                          maxTimeToSleep);
+                    }
+                }
+                finally {
+                    appletsLock.unlock();
+                }
+
+                // If wait exceeded maxWait, we timed out. Throw an exception
+                if (maxTimeToSleep <= 0)
+                    throw new Exception("Applet initialization timeout");
+
+                // We should not try to destroy an applet during
+                // initialization. It may cause an inconsistent state,
+                // which would bad if it's a trusted applet that
+                // read/writes to files
+                waitForAppletInit(applets.get(identifier).panel);
+
+                // Should we proceed with reframing?
+                if (updateStatus(identifier, PAV_INIT_STATUS.REFRAME_COMPLETE).equals(PAV_INIT_STATUS.INACTIVE)) {
+                    destroyApplet(identifier);
+                    return;
+                }
+
+            } else if (message.startsWith("destroy")) {
+
+                // Set it inactive, and try to do cleanup is applicable
+                PAV_INIT_STATUS previousStatus = updateStatus(identifier, PAV_INIT_STATUS.INACTIVE);
+                PluginDebug.debug("Destroy status set for ", identifier);
+
+                if (previousStatus != null &&
+                         previousStatus.equals(PAV_INIT_STATUS.REFRAME_COMPLETE)) {
+                    destroyApplet(identifier);
+                }
+
+            } else {
+                PluginDebug.debug("Handling message: ", message, " instance ", identifier, " ", Thread.currentThread());
+
+                // Wait till initialization finishes
+                while (!applets.containsKey(identifier) &&
+                         (
+                           !status.containsKey(identifier) ||
+                            status.get(identifier).equals(PAV_INIT_STATUS.PRE_INIT)
+                         ))
+                    ;
+
+                // don't bother processing further for inactive applets
+                if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE))
+                    return;
+
+                applets.get(identifier).handleMessage(reference, message);
+            }
+        } catch (Exception e) {
+
+            e.printStackTrace();
+
+            // If an exception happened during pre-init, we need to update status
+            updateStatus(identifier, PAV_INIT_STATUS.INACTIVE);
+
+            throw new RuntimeException("Failed to handle message: " +
+                     message + " for instance " + identifier, e);
+        }
+    }
+
+    /**
+     * Sets the status unless an overriding status is set (e.g. if
+     * status is DESTROYED, it may not be overridden).
+     *
+     * @param identifier The identifier for which the status is to be set
+     * @param status The status to switch to
+     * @return The previous status
+     */
+    private static synchronized PAV_INIT_STATUS updateStatus(int identifier, PAV_INIT_STATUS newStatus) {
+
+        PAV_INIT_STATUS prev = status.get(identifier);
+
+        // If the status is set
+        if (status.containsKey(identifier)) {
+
+            // Nothing may override destroyed status
+            if (status.get(identifier).equals(PAV_INIT_STATUS.DESTROYED)) {
+                return prev;
+            }
+
+            // If status is inactive, only DESTROYED may override it
+            if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) {
+                if (!newStatus.equals(PAV_INIT_STATUS.DESTROYED)) {
+                    return prev;
+                }
+            }
+        }
+
+        // Else set to given status
+
+        statusLock.lock();
+        status.put(identifier, newStatus);
+        initComplete.signalAll();
+        statusLock.unlock();
+
+        return prev;
+    }
+
+    /**
+     * Destroys the given applet instance.
+     *
+     * This function may be called multiple times without problems.
+     * It does a synchronized check on the status and will only
+     * attempt to destroy the applet if not previously destroyed.
+     *
+     * @param identifier The instance which is to be destroyed
+     */
+
+    private static synchronized void destroyApplet(int identifier) {
+
+        PluginDebug.debug("DestroyApplet called for ", identifier);
+
+        PAV_INIT_STATUS prev = updateStatus(identifier, PAV_INIT_STATUS.DESTROYED);
+
+        // If already destroyed, return
+        if (prev.equals(PAV_INIT_STATUS.DESTROYED)) {
+            PluginDebug.debug(identifier, " already destroyed. Returning.");
+            return;
+        }
+
+        PluginDebug.debug("Attempting to destroy frame ", identifier);
+
+        // Try to dispose the panel right away
+        final PluginAppletViewer pav = applets.get(identifier);
+        if (pav != null) {
+            pav.dispose();
+
+            // If panel is already disposed, return
+            if (pav.panel.applet == null) {
+                PluginDebug.debug(identifier, " panel inactive. Returning.");
+                return;
+            }
+
+            PluginDebug.debug("Attempting to destroy panel ", identifier);
+
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    pav.appletClose();
+                }
+            });
+        }
+
+        PluginDebug.debug(identifier, " destroyed");
+    }
+
+    /**
+     * Function to block until applet initialization is complete.
+     *
+     * This function will return if the wait is longer than {@link #APPLET_TIMEOUT}
+     *
+     * @param panel the instance to wait for.
+     */
+    public static void waitForAppletInit(NetxPanel panel) {
+
+        // Wait till initialization finishes
+        long maxTimeToSleep = APPLET_TIMEOUT;
+
+        panelLock.lock();
+        try {
+            while (panel.getApplet() == null &&
+                    panel.isAlive() &&
+                    maxTimeToSleep > 0) {
+                PluginDebug.debug("Waiting for applet panel ", panel, " to initialize...");
+                maxTimeToSleep -= waitTillTimeout(panelLock, panelLive, maxTimeToSleep);
+            }
+        }
+        finally {
+            panelLock.unlock();
+        }
+
+        PluginDebug.debug("Applet panel ", panel, " initialized");
+    }
+
+    public void handleMessage(int reference, String message) {
+        if (message.startsWith("width")) {
+
+            // Wait for panel to come alive
+            long maxTimeToSleep = APPLET_TIMEOUT;
+            statusLock.lock();
+            try {
+                while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) &&
+                        maxTimeToSleep > 0) {
+                    maxTimeToSleep -= waitTillTimeout(statusLock, initComplete,
+                                                      maxTimeToSleep);
+                }
+            }
+            finally {
+                statusLock.unlock();
+            }
+
+            // 0 => width, 1=> width_value, 2 => height, 3=> height_value
+            String[] dimMsg = message.split(" ");
+
+            final int height = Integer.parseInt(dimMsg[3]);
+            final int width = Integer.parseInt(dimMsg[1]);
+
+            panel.updateSizeInAtts(height, width);
+
+            try {
+                SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+
+                        setSize(width, height);
+
+                        // There is a rather odd drawing bug whereby resizing
+                        // the panel makes no difference on initial call
+                        // because the panel thinks that it is already the
+                        // right size. Validation has no effect there either.
+                        // So we work around by setting size to 1, validating,
+                        // and then setting to the right size and validating
+                        // again. This is not very efficient, and there is
+                        // probably a better way -- but resizing happens
+                        // quite infrequently, so for now this is how we do it
+
+                        panel.setSize(1, 1);
+                        panel.validate();
+
+                        panel.setSize(width, height);
+                        panel.validate();
+
+                        panel.applet.resize(width, height);
+                        panel.applet.validate();
+                    }
+                });
+            } catch (InterruptedException e) {
+                // do nothing
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                // do nothing
+                e.printStackTrace();
+            }
+
+        } else if (message.startsWith("GetJavaObject")) {
+
+            // FIXME: how do we determine what security context this
+            // object should belong to?
+            Object o;
+
+            // First, wait for panel to instantiate
+            // Next, wait for panel to come alive
+            long maxTimeToSleep = APPLET_TIMEOUT;
+            panelLock.lock();
+            try {
+                while (panel == null || !panel.isAlive())
+                    maxTimeToSleep -= waitTillTimeout(panelLock, panelLive,
+                                                      maxTimeToSleep);
+            }
+            finally {
+                panelLock.unlock();
+            }
+
+            // Wait for the panel to initialize
+            // (happens in a separate thread)
+            waitForAppletInit(panel);
+
+            PluginDebug.debug(panel, " -- ", panel.getApplet(), " -- ", panel.isAlive());
+
+            // Still null?
+            if (panel.getApplet() == null) {
+                streamhandler.write("instance " + identifier + " reference " + -1 + " fatalError: " + "Initialization timed out");
+                return;
+            }
+
+            o = panel.getApplet();
+            PluginDebug.debug("Looking for object ", o, " panel is ", panel);
+            AppletSecurityContextManager.getSecurityContext(0).store(o);
+            PluginDebug.debug("WRITING 1: ", "context 0 reference ", reference, " GetJavaObject "
+                                 , AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o));
+            streamhandler.write("context 0 reference " + reference + " GetJavaObject "
+                              + AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o));
+            PluginDebug.debug("WRITING 1 DONE");
+        }
+    }
+
+    /*
+     * Methods for java.applet.AppletContext
+     */
+
+    private static Map<URL, AudioClip> audioClips = new HashMap<URL, AudioClip>();
+
+    /**
+     * Get an audio clip.
+     */
+    public AudioClip getAudioClip(URL url) {
+        checkConnect(url);
+        synchronized (audioClips) {
+            AudioClip clip = audioClips.get(url);
+            if (clip == null) {
+                audioClips.put(url, clip = new AppletAudioClip(url));
+            }
+            return clip;
+        }
+    }
+
+    private static Map<URL, AppletImageRef> imageRefs = new HashMap<URL, AppletImageRef>();
+
+    /**
+     * Get an image.
+     */
+    public Image getImage(URL url) {
+        return getCachedImage(url);
+    }
+
+    private Image getCachedImage(URL url) {
+        return (Image) getCachedImageRef(url).get();
+    }
+
+    /**
+     * Get an image ref.
+     */
+    private synchronized Ref getCachedImageRef(URL url) {
+        PluginDebug.debug("getCachedImageRef() searching for ", url);
+
+        try {
+
+            String originalURL = url.toString();
+            String codeBase = panel.getCodeBase().toString();
+
+            if (originalURL.startsWith(codeBase)) {
+
+                PluginDebug.debug("getCachedImageRef() got URL = ", url);
+                PluginDebug.debug("getCachedImageRef() plugin codebase = ", codeBase);
+
+                String resourceName = originalURL.substring(codeBase.length());
+                JNLPClassLoader loader = (JNLPClassLoader) panel.getAppletClassLoader();
+
+                URL localURL = null;
+                if (loader.resourceAvailableLocally(resourceName))
+                    url = loader.getResource(resourceName);
+
+                url = localURL != null ? localURL : url;
+            }
+
+            PluginDebug.debug("getCachedImageRef() getting img from URL = ", url);
+
+            synchronized (imageRefs) {
+                AppletImageRef ref = imageRefs.get(url);
+                if (ref == null) {
+                    ref = new AppletImageRef(url);
+                    imageRefs.put(url, ref);
+                }
+                return ref;
+            }
+        } catch (Exception e) {
+            System.err.println("Error occurred when trying to fetch image:");
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * Flush the image cache.
+     */
+    static void flushImageCache() {
+        imageRefs.clear();
+    }
+
+    private static Vector<NetxPanel> appletPanels = new Vector<NetxPanel>();
+
+    /**
+     * Get an applet by name.
+     */
+    public Applet getApplet(String name) {
+        name = name.toLowerCase();
+        SocketPermission panelSp =
+                new SocketPermission(panel.getCodeBase().getHost(), "connect");
+        synchronized(appletPanels) {
+            for (Enumeration<NetxPanel> e = appletPanels.elements(); e.hasMoreElements();) {
+                AppletPanel p = e.nextElement();
+                String param = p.getParameter("name");
+                if (param != null) {
+                    param = param.toLowerCase();
+                }
+                if (name.equals(param) &&
+                        p.getDocumentBase().equals(panel.getDocumentBase())) {
+
+                    SocketPermission sp =
+                        new SocketPermission(p.getCodeBase().getHost(), "connect");
+
+                    if (panelSp.implies(sp)) {
+                        return p.applet;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return an enumeration of all the accessible
+     * applets on this page.
+     */
+    public Enumeration<Applet> getApplets() {
+        Vector<Applet> v = new Vector<Applet>();
+        SocketPermission panelSp =
+                new SocketPermission(panel.getCodeBase().getHost(), "connect");
+
+        synchronized(appletPanels) {
+            for (Enumeration<NetxPanel> e = appletPanels.elements(); e.hasMoreElements();) {
+                AppletPanel p = e.nextElement();
+                if (p.getDocumentBase().equals(panel.getDocumentBase())) {
+
+                    SocketPermission sp =
+                        new SocketPermission(p.getCodeBase().getHost(), "connect");
+                    if (panelSp.implies(sp)) {
+                        v.addElement(p.applet);
+                    }
+                }
+            }
+        }
+        return v.elements();
+    }
+
+    /**
+     * Ignore.
+     */
+    public void showDocument(URL url) {
+        PluginDebug.debug("Showing document...");
+        showDocument(url, "_self");
+    }
+
+    /**
+     * Ignore.
+     */
+    public void showDocument(URL url, String target) {
+        try {
+            Long reference = getRequestIdentifier();
+            write("reference " + reference +  " LoadURL " + UrlUtil.encode(url.toString(), "UTF-8") + " " + target);
+        } catch (IOException exception) {
+            // Deliberately ignore IOException.  showDocument may be
+            // called from threads other than the main thread after
+            // streamhandler.pluginOutputStream has been closed.
+        }
+    }
+
+    /**
+     * Show status.
+     */
+    public void showStatus(String status) {
+        try {
+            // FIXME: change to postCallRequest
+            // For statuses, we cannot have a newline
+            status = status.replace("\n", " ");
+            write("status " + status);
+        } catch (IOException exception) {
+            // Deliberately ignore IOException.  showStatus may be
+            // called from threads other than the main thread after
+            // streamhandler.pluginOutputStream has been closed.
+        }
+    }
+
+    /**
+     * Returns an incremental number (unique identifier) for a message.
+     * If identifier hits Long.MAX_VALUE it loops back starting at 0.
+     *
+     *  @return A unique Long identifier for the request
+     */
+    private static long getRequestIdentifier() {
+        synchronized(requestMutex) {
+            if (requestIdentityCounter == Long.MAX_VALUE) {
+                requestIdentityCounter = 0L;
+            }
+
+            return requestIdentityCounter++;
+        }
+    }
+
+    public long getWindow() {
+        PluginDebug.debug("STARTING getWindow");
+        Long reference = getRequestIdentifier();
+
+        PluginCallRequest request = requestFactory.getPluginCallRequest("window",
+                "instance " + identifier + " reference " +
+                        +reference + " " + "GetWindow", reference);
+
+        PluginDebug.debug("STARTING postCallRequest");
+        streamhandler.postCallRequest(request);
+        PluginDebug.debug("STARTING postCallRequest done");
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait request 2");
+                while ((Long) request.getObject() == 0)
+                    request.wait();
+                PluginDebug.debug("wait request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                     e);
+        }
+
+        PluginDebug.debug("STARTING getWindow DONE");
+        return (Long) request.getObject();
+    }
+
+    // FIXME: make private, access via reflection.
+    public static Object getMember(long internal, String name) {
+        AppletSecurityContextManager.getSecurityContext(0).store(name);
+        int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("member",
+                "instance " + 0 + " reference " + reference + " GetMember " +
+                        internal + " " + nameID, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait getMEM request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait getMEM request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait getMEM request 3 GOT: ", request.getObject().getClass());
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" getMember DONE");
+        return request.getObject();
+    }
+
+    public static void setMember(long internal, String name, Object value) {
+        System.err.println("Setting to class " + value.getClass() + ":" + value.getClass().isPrimitive());
+        AppletSecurityContextManager.getSecurityContext(0).store(name);
+        int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
+        Long reference = getRequestIdentifier();
+
+        // work on a copy of value, as we don't want to be manipulating
+        // complex objects
+        String valueToSetTo;
+        if (value instanceof java.lang.Byte ||
+                value instanceof java.lang.Character ||
+                value instanceof java.lang.Short ||
+                value instanceof java.lang.Integer ||
+                value instanceof java.lang.Long ||
+                value instanceof java.lang.Float ||
+                value instanceof java.lang.Double ||
+                value instanceof java.lang.Boolean) {
+
+            valueToSetTo = "literalreturn " + value.toString();
+
+            // Character -> Str results in str value.. we need int value as
+            // per specs.
+            if (value instanceof java.lang.Character) {
+                valueToSetTo = "literalreturn " + (int) ((java.lang.Character) value).charValue();
+            } else if (value instanceof Float ||
+                        value instanceof Double) {
+                valueToSetTo = "literalreturn " + String.format("%308.308e", value);
+            }
+
+        } else {
+            AppletSecurityContextManager.getSecurityContext(0).store(value);
+            valueToSetTo = Integer.toString(AppletSecurityContextManager.getSecurityContext(0).getIdentifier(value));
+        }
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("void",
+                "instance " + 0 + " reference " + reference + " SetMember " +
+                        internal + " " + nameID + " " + valueToSetTo, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait setMem request: ", request.getMessage());
+            PluginDebug.debug("wait setMem request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait setMem request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait setMem request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" setMember DONE");
+    }
+
+    // FIXME: handle long index as well.
+    public static void setSlot(long internal, int index, Object value) {
+        AppletSecurityContextManager.getSecurityContext(0).store(value);
+        Long reference = getRequestIdentifier();
+
+        // work on a copy of value, as we don't want to be manipulating
+        // complex objects
+        String valueToSetTo;
+        if (value instanceof java.lang.Byte ||
+                value instanceof java.lang.Character ||
+                value instanceof java.lang.Short ||
+                value instanceof java.lang.Integer ||
+                value instanceof java.lang.Long ||
+                value instanceof java.lang.Float ||
+                value instanceof java.lang.Double ||
+                value instanceof java.lang.Boolean) {
+
+            valueToSetTo = "literalreturn " + value.toString();
+
+            // Character -> Str results in str value.. we need int value as
+            // per specs.
+            if (value instanceof java.lang.Character) {
+                valueToSetTo = "literalreturn " + (int) ((java.lang.Character) value).charValue();
+            } else if (value instanceof Float ||
+                        value instanceof Double) {
+                valueToSetTo = "literalreturn " + String.format("%308.308e", value);
+            }
+
+        } else {
+            AppletSecurityContextManager.getSecurityContext(0).store(value);
+            valueToSetTo = Integer.toString(AppletSecurityContextManager.getSecurityContext(0).getIdentifier(value));
+        }
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("void",
+                "instance " + 0 + " reference " + reference + " SetSlot " +
+                        internal + " " + index + " " + valueToSetTo, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait setSlot request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait setSlot request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait setSlot request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" setSlot DONE");
+    }
+
+    public static Object getSlot(long internal, int index) {
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("member",
+                "instance " + 0 + " reference " + reference + " GetSlot " +
+                        internal + " " + index, reference);
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait getSlot request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait getSlot request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait getSlot request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" getSlot DONE");
+        return request.getObject();
+    }
+
+    public static Object eval(long internal, String s) {
+        AppletSecurityContextManager.getSecurityContext(0).store(s);
+        int stringID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(s);
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        // FIXME: rename GetMemberPluginCallRequest ObjectPluginCallRequest.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("member",
+                "instance " + 0 + " reference " + reference + " Eval " +
+                        internal + " " + stringID, reference);
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait eval request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait eval request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait eval request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" getSlot DONE");
+        return request.getObject();
+    }
+
+    public static void removeMember(long internal, String name) {
+        AppletSecurityContextManager.getSecurityContext(0).store(name);
+        int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("void",
+                "instance " + 0 + " reference " + reference + " RemoveMember " +
+                        internal + " " + nameID, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait removeMember request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait removeMember request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait removeMember request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" RemoveMember DONE");
+    }
+
+    public static Object call(long internal, String name, Object args[]) {
+        // FIXME: when is this removed from the object store?
+        // FIXME: reference should return the ID.
+        // FIXME: convenience method for this long line.
+        AppletSecurityContextManager.getSecurityContext(0).store(name);
+        int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
+        Long reference = getRequestIdentifier();
+
+        String argIDs = "";
+        for (Object arg : args) {
+            AppletSecurityContextManager.getSecurityContext(0).store(arg);
+            argIDs += AppletSecurityContextManager.getSecurityContext(0).getIdentifier(arg) + " ";
+        }
+        argIDs = argIDs.trim();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("member",
+                "instance " + 0 + " reference " + reference + " Call " +
+                        internal + " " + nameID + " " + argIDs, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait call request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait call request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait call request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" Call DONE");
+        return request.getObject();
+    }
+
+    public static Object requestPluginCookieInfo(URI uri) {
+
+        PluginCallRequest request;
+        Long reference = getRequestIdentifier();
+
+        try {
+            String encodedURI = UrlUtil.encode(uri.toString(), "UTF-8");
+            request = requestFactory.getPluginCallRequest("cookieinfo",
+                    "plugin PluginCookieInfo " + "reference " + reference +
+                            " " + encodedURI, reference);
+
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        PluginMessageConsumer.registerPriorityWait(reference);
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait cookieinfo request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait cookieinfo request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait cookieinfo request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for cookieinfo request.",
+                                        e);
+        }
+        PluginDebug.debug(" Cookieinfo DONE");
+        return request.getObject();
+    }
+
+    public static Object requestPluginProxyInfo(URI uri) {
+
+        String requestURI = null;
+        Long reference = getRequestIdentifier();
+
+        try {
+
+            // there is no easy way to get SOCKS proxy info. So, we tell mozilla that we want proxy for
+            // an HTTP uri in case of non http/ftp protocols. If we get back a SOCKS proxy, we can
+            // use that, if we get back an http proxy, we fallback to DIRECT connect
+
+            String scheme = uri.getScheme();
+            String port = uri.getPort() != -1 ? ":" + uri.getPort() : "";
+            if (!uri.getScheme().startsWith("http") && !uri.getScheme().equals("ftp"))
+                scheme = "http";
+
+            requestURI = UrlUtil.encode(scheme + "://" + uri.getHost() + port + "/" + uri.getPath(), "UTF-8");
+        } catch (Exception e) {
+            PluginDebug.debug("Cannot construct URL from ", uri.toString(), " ... falling back to DIRECT proxy");
+            e.printStackTrace();
+            return null;
+        }
+
+        PluginCallRequest request = requestFactory.getPluginCallRequest("proxyinfo",
+                "plugin PluginProxyInfo reference " + reference + " " +
+                        requestURI, reference);
+
+        PluginMessageConsumer.registerPriorityWait(reference);
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait call request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait call request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait call request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" Call DONE");
+        return request.getObject();
+    }
+
+    public static void JavaScriptFinalize(long internal) {
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("void",
+                "instance " + 0 + " reference " + reference + " Finalize " +
+                        internal, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait finalize request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait finalize request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait finalize request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" finalize DONE");
+    }
+
+    public static String javascriptToString(long internal) {
+        Long reference = getRequestIdentifier();
+
+        // Prefix with dummy instance for convenience.
+        PluginCallRequest request = requestFactory.getPluginCallRequest("member",
+                "instance " + 0 + " reference " + reference + " ToString " +
+                        internal, reference);
+
+        streamhandler.postCallRequest(request);
+        streamhandler.write(request.getMessage());
+        try {
+            PluginDebug.debug("wait ToString request 1");
+            synchronized (request) {
+                PluginDebug.debug("wait ToString request 2");
+                while (request.isDone() == false)
+                    request.wait();
+                PluginDebug.debug("wait ToString request 3");
+            }
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+        }
+        PluginDebug.debug(" ToString DONE");
+        return (String) request.getObject();
+    }
+
+    // FIXME: make this private and access it from JSObject using
+    // reflection.
+    private void write(String message) throws IOException {
+        PluginDebug.debug("WRITING 2: ", "instance ", identifier, " " + message);
+        streamhandler.write("instance " + identifier + " " + message);
+        PluginDebug.debug("WRITING 2 DONE");
+    }
+
+    public void setStream(String key, InputStream stream) throws IOException {
+        // We do nothing.
+    }
+
+    @Override
+    public InputStream getStream(String key) {
+        // We do nothing.
+        return null;
+    }
+
+    @Override
+    public Iterator<String> getStreamKeys() {
+        // We do nothing.
+        return null;
+    }
+
+    /**
+     * Decodes the string (converts html escapes into proper characters)
+     *
+     * @param toDecode The string to decode
+     * @return The decoded string
+     */
+    public static String decodeString(String toDecode) {
+
+        toDecode = toDecode.replace("&gt;", ">");
+        toDecode = toDecode.replace("&lt;", "<");
+        toDecode = toDecode.replace("&amp;", "&");
+        toDecode = toDecode.replace("&#10;", "\n");
+        toDecode = toDecode.replace("&#13;", "\r");
+        toDecode = toDecode.replace("&quot;", "\"");
+
+        return toDecode;
+    }
+
+    /**
+     * System parameters.
+     */
+    static Hashtable<String, String> systemParam = new Hashtable<String, String>();
+
+    static {
+        systemParam.put("codebase", "codebase");
+        systemParam.put("code", "code");
+        systemParam.put("alt", "alt");
+        systemParam.put("width", "width");
+        systemParam.put("height", "height");
+        systemParam.put("align", "align");
+        systemParam.put("vspace", "vspace");
+        systemParam.put("hspace", "hspace");
+    }
+
+    /**
+     * Print the HTML tag.
+     */
+    public static void printTag(PrintStream out, Hashtable<String, String> atts) {
+        out.print("<applet");
+
+        String v = atts.get("codebase");
+        if (v != null) {
+            out.print(" codebase=\"" + v + "\"");
+        }
+
+        v = atts.get("code");
+        if (v == null) {
+            v = "applet.class";
+        }
+        out.print(" code=\"" + v + "\"");
+        v = atts.get("width");
+        if (v == null) {
+            v = "150";
+        }
+        out.print(" width=" + v);
+
+        v = atts.get("height");
+        if (v == null) {
+            v = "100";
+        }
+        out.print(" height=" + v);
+
+        v = atts.get("name");
+        if (v != null) {
+            out.print(" name=\"" + v + "\"");
+        }
+        out.println(">");
+
+        // A very slow sorting algorithm
+        int len = atts.size();
+        String params[] = new String[len];
+        len = 0;
+        for (Enumeration<String> e = atts.keys(); e.hasMoreElements();) {
+            String param = e.nextElement();
+            int i = 0;
+            for (; i < len; i++) {
+                if (params[i].compareTo(param) >= 0) {
+                    break;
+                }
+            }
+            System.arraycopy(params, i, params, i + 1, len - i);
+            params[i] = param;
+            len++;
+        }
+
+        for (int i = 0; i < len; i++) {
+            String param = params[i];
+            if (systemParam.get(param) == null) {
+                out.println("<param name=" + param +
+                        " value=\"" + atts.get(param) + "\">");
+            }
+        }
+        out.println("</applet>");
+    }
+
+    /**
+     * Make sure the atrributes are uptodate.
+     */
+    public void updateAtts() {
+        Dimension d = panel.getSize();
+        Insets in = panel.getInsets();
+        panel.atts.put("width",
+                       Integer.valueOf(d.width - (in.left + in.right)).toString());
+        panel.atts.put("height",
+                       Integer.valueOf(d.height - (in.top + in.bottom)).toString());
+    }
+
+    /**
+     * Restart the applet.
+     */
+    void appletRestart() {
+        panel.sendEvent(AppletPanel.APPLET_STOP);
+        panel.sendEvent(AppletPanel.APPLET_DESTROY);
+        panel.sendEvent(AppletPanel.APPLET_INIT);
+        panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    /**
+     * Reload the applet.
+     */
+    void appletReload() {
+        panel.sendEvent(AppletPanel.APPLET_STOP);
+        panel.sendEvent(AppletPanel.APPLET_DESTROY);
+        panel.sendEvent(AppletPanel.APPLET_DISPOSE);
+
+        /**
+         * Fixed #4501142: Classlaoder sharing policy doesn't
+         * take "archive" into account. This will be overridden
+         * by Java Plug-in.         [stanleyh]
+         */
+        AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey());
+
+        /*
+         * Make sure we don't have two threads running through the event queue
+         * at the same time.
+         */
+        try {
+            ((AppletViewerPanel)panel).joinAppletThread();
+            ((AppletViewerPanel)panel).release();
+        } catch (InterruptedException e) {
+            return; // abort the reload
+        }
+
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                ((AppletViewerPanel)panel).createAppletThread();
+                return null;
+            }
+        });
+
+        panel.sendEvent(AppletPanel.APPLET_LOAD);
+        panel.sendEvent(AppletPanel.APPLET_INIT);
+        panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    public int print(Graphics graphics, PageFormat pf, int pageIndex) {
+        return Printable.NO_SUCH_PAGE;
+    }
+
+    /**
+     * Start the applet.
+     */
+    void appletStart() {
+        panel.sendEvent(AppletPanel.APPLET_START);
+    }
+
+    /**
+     * Stop the applet.
+     */
+    void appletStop() {
+        panel.sendEvent(AppletPanel.APPLET_STOP);
+    }
+
+    /**
+     * Shutdown a viewer.
+     * Stop, Destroy, Dispose and Quit a viewer
+     */
+    private void appletShutdown(AppletPanel p) {
+        p.sendEvent(AppletPanel.APPLET_STOP);
+        p.sendEvent(AppletPanel.APPLET_DESTROY);
+        p.sendEvent(AppletPanel.APPLET_DISPOSE);
+        p.sendEvent(AppletPanel.APPLET_QUIT);
+    }
+
+    /**
+     * Close this viewer.
+     * Stop, Destroy, Dispose and Quit an AppletView, then
+     * reclaim resources and exit the program if this is
+     * the last applet.
+     */
+    void appletClose() {
+
+        // The caller thread is event dispatch thread, so
+        // spawn a new thread to avoid blocking the event queue
+        // when calling appletShutdown.
+        //
+        final AppletPanel p = panel;
+
+        new Thread(new Runnable() {
+            @SuppressWarnings("deprecation")
+            public void run() {
+                ClassLoader cl = p.applet.getClass().getClassLoader();
+
+                // Since we want to deal with JNLPClassLoader, extract it if this
+                // is a codebase loader
+                if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+                    cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+                ThreadGroup tg = ((JNLPClassLoader) cl).getApplication().getThreadGroup();
+
+                appletShutdown(p);
+                appletPanels.removeElement(p);
+
+                try {
+                    SwingUtilities.invokeAndWait(new Runnable() {
+                        public void run() {
+                            dispose();
+                        }
+                    });
+                } catch (Exception e) { // ignore, we are just disposing it
+                }
+
+                if (countApplets() == 0) {
+                    appletSystemExit();
+                }
+
+                updateStatus(identifier, PAV_INIT_STATUS.DESTROYED);
+            }
+        }).start();
+    }
+
+    /**
+     * Exit the program.
+     * Exit from the program (if not stand alone) - do no clean-up
+     */
+    private void appletSystemExit() {
+        // Do nothing. Exit is handled by another
+        // block of code, called when _all_ applets are gone
+    }
+
+    /**
+     * How many applets are running?
+     */
+
+    public static int countApplets() {
+        return appletPanels.size();
+    }
+
+    /**
+     * Scan spaces.
+     */
+    public static void skipSpace(int[] c, Reader in) throws IOException {
+        while ((c[0] >= 0) &&
+                ((c[0] == ' ') || (c[0] == '\t') || (c[0] == '\n') || (c[0] == '\r'))) {
+            c[0] = in.read();
+        }
+    }
+
+    /**
+     * Scan identifier
+     */
+    public static String scanIdentifier(int[] c, Reader in) throws IOException {
+        StringBuilder buf = new StringBuilder();
+
+        if (c[0] == '!') {
+            // Technically, we should be scanning for '!--' but we are reading
+            // from a stream, and there is no way to peek ahead. That said,
+            // a ! at this point can only mean comment here afaik, so we
+            // should be okay
+            skipComment(c, in);
+            return "";
+        }
+
+        while (true) {
+            if (((c[0] >= 'a') && (c[0] <= 'z')) ||
+                    ((c[0] >= 'A') && (c[0] <= 'Z')) ||
+                    ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_')) {
+                buf.append((char) c[0]);
+                c[0] = in.read();
+            } else {
+                return buf.toString();
+            }
+        }
+    }
+
+    public static void skipComment(int[] c, Reader in) throws IOException {
+        StringBuilder buf = new StringBuilder();
+        boolean commentHeaderPassed = false;
+        c[0] = in.read();
+        buf.append((char) c[0]);
+
+        while (true) {
+            if (c[0] == '-' && (c[0] = in.read()) == '-') {
+                buf.append((char) c[0]);
+                if (commentHeaderPassed) {
+                    // -- encountered ... is > next?
+                    if ((c[0] = in.read()) == '>') {
+                        buf.append((char) c[0]);
+
+                        PluginDebug.debug("Comment skipped: ", buf.toString());
+
+                        // comment skipped.
+                        return;
+                    }
+                } else {
+                    // first -- is part of <!-- ... , just mark that we have passed it
+                    commentHeaderPassed = true;
+                }
+
+            } else if (commentHeaderPassed == false) {
+                buf.append((char) c[0]);
+                PluginDebug.debug("Warning: Attempted to skip comment, but this tag does not appear to be a comment: ", buf.toString());
+                return;
+            }
+
+            c[0] = in.read();
+            buf.append((char) c[0]);
+        }
+    }
+
+    /**
+     * Scan tag
+     */
+    public static Hashtable<String, String> scanTag(int[] c, Reader in) throws IOException {
+        Hashtable<String, String> atts = new Hashtable<String, String>();
+        skipSpace(c, in);
+        while (c[0] >= 0 && c[0] != '>') {
+            String att = decodeString(scanIdentifier(c, in));
+            String val = "";
+            skipSpace(c, in);
+            if (c[0] == '=') {
+                int quote = -1;
+                c[0] = in.read();
+                skipSpace(c, in);
+                if ((c[0] == '\'') || (c[0] == '\"')) {
+                    quote = c[0];
+                    c[0] = in.read();
+                }
+                StringBuilder buf = new StringBuilder();
+                while ((c[0] > 0) &&
+                        (((quote < 0) && (c[0] != ' ') && (c[0] != '\t') &&
+                                (c[0] != '\n') && (c[0] != '\r') && (c[0] != '>'))
+                         || ((quote >= 0) && (c[0] != quote)))) {
+                    buf.append((char) c[0]);
+                    c[0] = in.read();
+                }
+                if (c[0] == quote) {
+                    c[0] = in.read();
+                }
+                skipSpace(c, in);
+                val = decodeString(buf.toString());
+            }
+
+            PluginDebug.debug("PUT ", att, " = '", val, "'");
+            atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
+
+            while (true) {
+                if ((c[0] == '>') || (c[0] < 0) ||
+                        ((c[0] >= 'a') && (c[0] <= 'z')) ||
+                        ((c[0] >= 'A') && (c[0] <= 'Z')) ||
+                        ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_'))
+                    break;
+                c[0] = in.read();
+            }
+            //skipSpace(in);
+        }
+        return atts;
+    }
+
+    // private static final == inline
+    private static final boolean isInt(Object o) {
+        boolean isInt = false;
+        try {
+            Integer.parseInt((String) o);
+            isInt = true;
+        } catch (Exception e) {
+            // don't care
+        }
+
+        return isInt;
+    }
+
+    /* values used for placement of AppletViewer's frames */
+    private static int x = 0;
+    private static int y = 0;
+    private static final int XDELTA = 30;
+    private static final int YDELTA = XDELTA;
+
+    static String encoding = null;
+
+    /**
+     * Scan an html file for <applet> tags
+     */
+    public static void parse(int identifier, long handle, String width, String height, Reader in, URL url, String enc)
+            throws IOException {
+        encoding = enc;
+        parse(identifier, handle, width, height, in, url, System.out, new PluginAppletPanelFactory());
+    }
+
+    public static void parse(int identifier, long handle, String width, String height, Reader in, URL url)
+            throws PrivilegedActionException {
+
+        final int fIdentifier = identifier;
+        final long fHandle = handle;
+        final String fWidth = width;
+        final String fHeight = height;
+        final Reader fIn = in;
+        final URL fUrl = url;
+        AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+            public Void run() throws IOException {
+                parse(fIdentifier, fHandle, fWidth, fHeight, fIn, fUrl,
+                        System.out, new PluginAppletPanelFactory());
+                return null;
+            }
+        });
+    }
+
+    @SuppressWarnings("unused")
+    public static void parse(int identifier, long handle, String width,
+                 String height, Reader in, URL url,
+                              PrintStream statusMsgStream,
+                              PluginAppletPanelFactory factory)
+            throws IOException {
+        boolean isObjectTag = false;
+        boolean objectTagAlreadyParsed = false;
+
+        // The current character
+        // FIXME: This is an evil hack to force pass-by-reference.. the
+        // parsing code needs to be rewritten from scratch to prevent such
+        //a need
+        int[] c = new int[1];
+
+        // warning messages
+        String requiresNameWarning = amh.getMessage("parse.warning.requiresname");
+        String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
+        String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
+        String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
+        String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
+        String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
+        String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
+        String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
+        String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
+        String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
+        String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
+        String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
+
+        java.net.URLConnection conn = url.openConnection();
+        /* The original URL may have been redirected - this
+         * sets it to whatever URL/codebase we ended up getting
+         */
+        url = conn.getURL();
+
+        int ydisp = 1;
+        Hashtable<String, String> atts = null;
+
+        while (true) {
+            c[0] = in.read();
+            if (c[0] == -1)
+                break;
+
+            if (c[0] == '<') {
+                c[0] = in.read();
+                if (c[0] == '/') {
+                    c[0] = in.read();
+                    String nm = scanIdentifier(c, in);
+                    if (nm.equalsIgnoreCase("applet") ||
+                             nm.equalsIgnoreCase("object") ||
+                             nm.equalsIgnoreCase("embed")) {
+
+                        // We can't test for a code tag until </OBJECT>
+                        // because it is a parameter, not an attribute.
+                        if (isObjectTag) {
+                            if (atts.get("code") == null && atts.get("object") == null) {
+                                statusMsgStream.println(objectRequiresCodeWarning);
+                                atts = null;
+                            }
+                        }
+
+                        if (atts != null) {
+                            // XXX 5/18 In general this code just simply
+                            // shouldn't be part of parsing.  It's presence
+                            // causes things to be a little too much of a
+                            // hack.
+
+                            // Let user know we are starting up
+                            streamhandler.write("instance " + identifier + " status " + amh.getMessage("status.start"));
+                            factory.createPanel(streamhandler, identifier, handle, x, y, url, atts);
+
+                            x += XDELTA;
+                            y += YDELTA;
+                            // make sure we don't go too far!
+                            Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+                            if ((x > d.width - 300) || (y > d.height - 300)) {
+                                x = 0;
+                                y = 2 * ydisp * YDELTA;
+                                ydisp++;
+                            }
+                        }
+                        atts = null;
+                        isObjectTag = false;
+                    }
+                } else {
+                    String nm = scanIdentifier(c, in);
+                    if (nm.equalsIgnoreCase("param")) {
+                        Hashtable<String, String> t = scanTag(c, in);
+                        String att = t.get("name");
+
+                        if (atts.containsKey(att))
+                            continue;
+
+                        if (att == null) {
+                            statusMsgStream.println(requiresNameWarning);
+                        } else {
+                            String val = t.get("value");
+                            if (val == null) {
+                                statusMsgStream.println(requiresNameWarning);
+                            } else {
+                                PluginDebug.debug("PUT ", att, " = ", val);
+                                atts.put(att.toLowerCase(), val);
+                            }
+                        }
+                    } else if (nm.equalsIgnoreCase("applet")) {
+                        atts = scanTag(c, in);
+
+                        // If there is a classid and no code tag present, transform it to code tag
+                        if (atts.get("code") == null && atts.get("classid") != null
+                                && !(atts.get("classid")).startsWith("clsid:")) {
+                            atts.put("code", atts.get("classid"));
+                        }
+
+                        // remove java: from code tag
+                        if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
+                            atts.put("code", (atts.get("code")).substring(5));
+                        }
+
+                        if (atts.get("code") == null && atts.get("object") == null) {
+                            statusMsgStream.println(appletRequiresCodeWarning);
+                            atts = null;
+                        }
+
+                        if (atts.get("width") == null || !isInt(atts.get("width"))) {
+                            atts.put("width", width);
+                        }
+
+                        if (atts.get("height") == null || !isInt(atts.get("height"))) {
+                            atts.put("height", height);
+                        }
+                    } else if (nm.equalsIgnoreCase("object")) {
+                        isObjectTag = true;
+
+                        // Once code is set, additional nested objects are ignored
+                        if (!objectTagAlreadyParsed) {
+                            objectTagAlreadyParsed = true;
+                            atts = scanTag(c, in);
+                        }
+
+                        // If there is a classid and no code tag present, transform it to code tag
+                        if (atts.get("code") == null && atts.get("classid") != null
+                                && !(atts.get("classid")).startsWith("clsid:")) {
+                            atts.put("code", atts.get("classid"));
+                        }
+
+                        // remove java: from code tag
+                        if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
+                            atts.put("code", (atts.get("code")).substring(5));
+                        }
+
+                        // java_* aliases override older names:
+                        // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-ie
+                        if (atts.get("java_code") != null) {
+                            atts.put("code", (atts.get("java_code")));
+                        }
+
+                        if (atts.containsKey("code")) {
+                            objectTagAlreadyParsed = true;
+                        }
+
+                        if (atts.get("java_codebase") != null) {
+                            atts.put("codebase", (atts.get("java_codebase")));
+                        }
+
+                        if (atts.get("java_archive") != null) {
+                            atts.put("archive", (atts.get("java_archive")));
+                        }
+
+                        if (atts.get("java_object") != null) {
+                            atts.put("object", (atts.get("java_object")));
+                        }
+
+                        if (atts.get("java_type") != null) {
+                            atts.put("type", (atts.get("java_type")));
+                        }
+
+                        if (atts.get("width") == null || !isInt(atts.get("width"))) {
+                            atts.put("width", width);
+                        }
+
+                        if (atts.get("height") == null || !isInt(atts.get("height"))) {
+                            atts.put("height", height);
+                        }
+                    } else if (nm.equalsIgnoreCase("embed")) {
+                        atts = scanTag(c, in);
+
+                        // If there is a classid and no code tag present, transform it to code tag
+                        if (atts.get("code") == null && atts.get("classid") != null
+                                && !(atts.get("classid")).startsWith("clsid:")) {
+                            atts.put("code", atts.get("classid"));
+                        }
+
+                        // remove java: from code tag
+                        if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
+                            atts.put("code", (atts.get("code")).substring(5));
+                        }
+
+                        // java_* aliases override older names:
+                        // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
+                        if (atts.get("java_code") != null) {
+                            atts.put("code", (atts.get("java_code")));
+                        }
+
+                        if (atts.get("java_codebase") != null) {
+                            atts.put("codebase", (atts.get("java_codebase")));
+                        }
+
+                        if (atts.get("java_archive") != null) {
+                            atts.put("archive", (atts.get("java_archive")));
+                        }
+
+                        if (atts.get("java_object") != null) {
+                            atts.put("object", (atts.get("java_object")));
+                        }
+
+                        if (atts.get("java_type") != null) {
+                            atts.put("type", (atts.get("java_type")));
+                        }
+
+                        if (atts.get("code") == null && atts.get("object") == null) {
+                            statusMsgStream.println(embedRequiresCodeWarning);
+                            atts = null;
+                        }
+
+                        if (atts.get("width") == null || !isInt(atts.get("width"))) {
+                            atts.put("width", width);
+                        }
+
+                        if (atts.get("height") == null || !isInt(atts.get("height"))) {
+                            atts.put("height", height);
+                        }
+
+                    }
+                }
+            }
+        }
+        in.close();
+    }
+
+    private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");
+
+    private static void checkConnect(URL url) {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            try {
+                java.security.Permission perm =
+                        url.openConnection().getPermission();
+                if (perm != null)
+                    security.checkPermission(perm);
+                else
+                    security.checkConnect(url.getHost(), url.getPort());
+            } catch (java.io.IOException ioe) {
+                security.checkConnect(url.getHost(), url.getPort());
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * This method calls paint directly, rather than via super.update() since
+     * the parent class's update() just does a couple of checks (both of
+     * which are accounted for) and then calls paint anyway.
+     */
+    public void update(Graphics g) {
+
+        // If the image or the graphics don't exist, create new ones
+        if (bufFrameImg == null || bufFrameImgGraphics == null) {
+            bufFrameImg = createImage(getWidth(), getHeight());
+            bufFrameImgGraphics = bufFrameImg.getGraphics();
+        }
+
+        // Paint off-screen
+        paint(bufFrameImgGraphics);
+
+        // Draw the painted image
+        g.drawImage(bufFrameImg, 0, 0, this);
+    }
+
+    /**
+     * Waits on a given condition queue until timeout.
+     *
+     * <b>This function assumes that the monitor lock has already been
+     * acquired by the caller.</b>
+     *
+     * If the given lock is null, this function returns immediately.
+     *
+     * @param lock the lock that must be held when this method is called.
+     * @param cond the condition queue on which to wait for notifications.
+     * @param timeout The maximum time to wait (nanoseconds)
+     * @return Approximate time spent sleeping (not guaranteed to be perfect)
+     */
+    public static long waitTillTimeout(ReentrantLock lock, Condition cond,
+                                       long timeout) {
+
+        // Can't wait on null. Return 0 indicating no wait happened.
+        if (lock == null)
+            return 0;
+
+        assert lock.isHeldByCurrentThread();
+
+        // Record when we started sleeping
+        long sleepStart = 0L;
+
+        try {
+            sleepStart = System.nanoTime();
+            cond.await(timeout, TimeUnit.NANOSECONDS);
+        } catch (InterruptedException ie) {} // Discarded, time to return
+
+        // Return the difference
+        return System.nanoTime() - sleepStart;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequest.java	(revision 403)
@@ -0,0 +1,86 @@
+/* PluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+// FIXME: for each type of request extend a new (anonymous?)
+// PluginCallRequest.
+public abstract class PluginCallRequest {
+    private String message;
+    private Long reference;
+    private PluginCallRequest next;
+    private boolean done = false;
+
+    public PluginCallRequest(String message, Long reference) {
+        this.message = message;
+        this.reference = reference;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public boolean isDone() {
+        return this.done;
+    }
+
+    public boolean setDone(boolean done) {
+        return this.done = done;
+    }
+
+    public void setNext(PluginCallRequest next) {
+        this.next = next;
+    }
+
+    public PluginCallRequest getNext() {
+        return this.next;
+    }
+
+    /**
+     * Returns whether the given message is serviceable by this object
+     * 
+     * @param message The message to service
+     * @return boolean indicating if message is serviceable
+     */
+    public boolean serviceable(String message) {
+        return message.contains("reference " + reference);
+    }
+
+    public abstract void parseReturn(String message);
+
+    public abstract Object getObject();
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequestFactory.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequestFactory.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCallRequestFactory.java	(revision 403)
@@ -0,0 +1,59 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class PluginCallRequestFactory {
+
+    public PluginCallRequest getPluginCallRequest(String id, String message, Long reference) {
+
+        if (id == "member") {
+            return new GetMemberPluginCallRequest(message, reference);
+        } else if (id == "void") {
+            return new VoidPluginCallRequest(message, reference);
+        } else if (id == "window") {
+            return new GetWindowPluginCallRequest(message, reference);
+        } else if (id == "proxyinfo") {
+            return new PluginProxyInfoRequest(message, reference);
+        } else if (id == "cookieinfo") {
+            return new PluginCookieInfoRequest(message, reference);
+        } else {
+            throw new RuntimeException("Unknown plugin call request type requested from factory");
+        }
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginClassLoader.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginClassLoader.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginClassLoader.java	(revision 403)
@@ -0,0 +1,50 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class PluginClassLoader extends ClassLoader {
+
+    public PluginClassLoader() {
+        super();
+    }
+
+    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        return super.loadClass(name, resolve);
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java	(revision 403)
@@ -0,0 +1,77 @@
+/* PluginCookieInfoRequest -- Object representing a request for cookie information from the browser
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+/**
+ * This class represents a request object for cookie information for a given URI
+ */
+
+public class PluginCookieInfoRequest extends PluginCallRequest {
+
+    String cookieString = new String();
+
+    public PluginCookieInfoRequest(String message, Long reference) {
+        super(message, reference);
+    }
+
+    public void parseReturn(String cookieInfo) {
+
+        // try to parse the proxy information. If things go wrong, do nothing .. 
+        // this will keep internal = null which forces a direct connection
+
+        PluginDebug.debug("PluginCookieInfoRequest GOT: ", cookieInfo);
+
+        // skip 'plugin' marker
+        cookieInfo = cookieInfo.substring(cookieInfo.indexOf(' ') + 1);
+
+        // skip 'PluginCookieInfo' tag
+        cookieInfo = cookieInfo.substring(cookieInfo.indexOf(' ') + 1);
+
+        // skip 'reference' tag
+        cookieInfo = cookieInfo.substring(cookieInfo.indexOf(' ') + 1);
+
+        // skip reference # and get the rest
+        cookieString = cookieInfo.substring(cookieInfo.indexOf(' ') + 1);
+
+        setDone(true);
+    }
+
+    public String getObject() {
+        return this.cookieString;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieManager.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieManager.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginCookieManager.java	(revision 403)
@@ -0,0 +1,87 @@
+/* PluginCookieManager -- Cookie manager for the plugin
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.io.IOException;
+import java.net.CookieManager;
+import java.net.HttpCookie;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class PluginCookieManager extends CookieManager {
+    public Map<String, List<String>> get(URI uri,
+            Map<String, List<String>> requestHeaders) throws IOException {
+        // pre-condition check
+        if (uri == null || requestHeaders == null) {
+            throw new IllegalArgumentException("Argument is null");
+        }
+
+        Map<String, List<String>> cookieMap = new java.util.HashMap<String, List<String>>();
+
+        String cookies = (String) PluginAppletViewer
+                .requestPluginCookieInfo(uri);
+        List<String> cookieHeader = new java.util.ArrayList<String>();
+
+        if (cookies != null && cookies.length() > 0)
+            cookieHeader.add(cookies);
+
+        // Add anything else that mozilla didn't add
+        for (HttpCookie cookie : getCookieStore().get(uri)) {
+            // apply path-matches rule (RFC 2965 sec. 3.3.4)
+            if (pathMatches(uri.getPath(), cookie.getPath())) {
+                cookieHeader.add(cookie.toString());
+            }
+        }
+
+        cookieMap.put("Cookie", cookieHeader);
+        return Collections.unmodifiableMap(cookieMap);
+    }
+
+    private boolean pathMatches(String path, String pathToMatchWith) {
+        if (path == pathToMatchWith)
+            return true;
+        if (path == null || pathToMatchWith == null)
+            return false;
+        if (path.startsWith(pathToMatchWith))
+            return true;
+
+        return false;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginDebug.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginDebug.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginDebug.java	(revision 403)
@@ -0,0 +1,56 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class PluginDebug {
+
+    static final boolean DEBUG = System.getenv().containsKey("ICEDTEAPLUGIN_DEBUG");
+
+    public static void debug(Object... messageChunks) {
+        if (DEBUG) {
+            if (messageChunks == null) {
+                messageChunks = new Object[] {null};
+            }
+            StringBuilder b = new StringBuilder();
+            for (Object chunk : messageChunks) {
+                b.append(chunk);
+            }
+            System.err.println(b.toString());
+        }
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginException.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginException.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginException.java	(revision 403)
@@ -0,0 +1,51 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class PluginException extends Exception {
+
+    public PluginException(PluginStreamHandler sh, int instance, int reference, Throwable t) {
+        t.printStackTrace();
+        this.setStackTrace(t.getStackTrace());
+
+        AppletSecurityContextManager.dumpStore(0);
+
+        String message = "instance " + instance + " reference " + reference + " Error " + t.getMessage();
+        sh.write(message);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMain.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMain.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMain.java	(revision 403)
@@ -0,0 +1,191 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+/*
+ * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.applet;
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.CookieHandler;
+import java.net.CookieManager;
+import java.net.ProxySelector;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.JNLPAuthenticator;
+
+/**
+ * The main entry point into PluginAppletViewer.
+ */
+public class PluginMain extends PluginMainBase {
+    // the files where stdout/stderr are sent to
+    public static final String PLUGIN_STDERR_FILE = "java.stderr";
+    public static final String PLUGIN_STDOUT_FILE = "java.stdout";
+
+    // This is used in init().  Getting rid of this is desirable but depends
+    // on whether the property that uses it is necessary/standard.
+    private static final String theVersion = System.getProperty("java.version");
+
+    /**
+     * The main entry point into AppletViewer.
+     */
+    public static void main(String args[])
+            throws IOException {
+        if (!checkArgs(args)) {
+            System.exit(1);
+        }
+
+        try {
+            PluginStreamHandler streamHandler = connect(args);
+            boolean redirectStreams = System.getenv().containsKey("ICEDTEAPLUGIN_DEBUG");
+
+            // must be called before JNLPRuntime.initialize()
+            JNLPRuntime.setRedirectStreams(redirectStreams);
+
+            PluginAppletSecurityContext sc = new PluginAppletSecurityContext(0);
+            sc.prePopulateLCClasses();
+            PluginAppletSecurityContext.setStreamhandler(streamHandler);
+            AppletSecurityContextManager.addContext(0, sc);
+
+            PluginAppletViewer.setStreamhandler(streamHandler);
+            PluginAppletViewer.setPluginCallRequestFactory(new PluginCallRequestFactory());
+
+            init();
+
+            // Streams set. Start processing.
+            streamHandler.startProcessing();
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.err.println("Something very bad happened. I don't know what to do, so I am going to exit :(");
+            System.exit(1);
+        }
+    }
+
+    private PluginMain() {
+        // The PluginMain constructor should never, EVER, be called
+    }
+
+    private static void init() {
+        Properties avProps = new Properties();
+
+        // ADD OTHER RANDOM PROPERTIES
+        // XXX 5/18 need to revisit why these are here, is there some
+        // standard for what is available?
+
+        // Standard browser properties
+        avProps.put("browser", "sun.applet.AppletViewer");
+        avProps.put("browser.version", "1.06");
+        avProps.put("browser.vendor", "Sun Microsystems Inc.");
+        avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion);
+
+        // Define which packages can be extended by applets
+        // XXX 5/19 probably not needed, not checked in AppletSecurity
+        avProps.put("package.restrict.definition.java", "true");
+        avProps.put("package.restrict.definition.sun", "true");
+
+        // Define which properties can be read by applets.
+        // A property named by "key" can be read only when its twin
+        // property "key.applet" is true.  The following ten properties
+        // are open by default.  Any other property can be explicitly
+        // opened up by the browser user by calling appletviewer with
+        // -J-Dkey.applet=true
+        avProps.put("java.version.applet", "true");
+        avProps.put("java.vendor.applet", "true");
+        avProps.put("java.vendor.url.applet", "true");
+        avProps.put("java.class.version.applet", "true");
+        avProps.put("os.name.applet", "true");
+        avProps.put("os.version.applet", "true");
+        avProps.put("os.arch.applet", "true");
+        avProps.put("file.separator.applet", "true");
+        avProps.put("path.separator.applet", "true");
+        avProps.put("line.separator.applet", "true");
+
+        avProps.put("javaplugin.nodotversion", "160_17");
+        avProps.put("javaplugin.version", "1.6.0_17");
+        avProps.put("javaplugin.vm.options", "");
+
+        // Read in the System properties.  If something is going to be
+        // over-written, warn about it.
+        Properties sysProps = System.getProperties();
+        for (Enumeration<?> e = sysProps.propertyNames(); e.hasMoreElements();) {
+            String key = (String) e.nextElement();
+            String val = sysProps.getProperty(key);
+            avProps.setProperty(key, val);
+        }
+
+        // INSTALL THE PROPERTY LIST
+        System.setProperties(avProps);
+
+        // plug in a custom authenticator and proxy selector
+        boolean installAuthenticator = Boolean.valueOf(JNLPRuntime.getConfiguration()
+                        .getProperty(DeploymentConfiguration.KEY_SECURITY_INSTALL_AUTHENTICATOR));
+        if (installAuthenticator) {
+            Authenticator.setDefault(new JNLPAuthenticator());
+        }
+        // override the proxy selector set by JNLPRuntime
+        ProxySelector.setDefault(new PluginProxySelector());
+
+        CookieManager ckManager = new PluginCookieManager();
+        CookieHandler.setDefault(ckManager);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java	(revision 403)
@@ -0,0 +1,240 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+class PluginMessageConsumer {
+
+    private static final int MAX_PARALLEL_INITS = 1;
+
+    // Each initialization requires 5 responses (tag, handle, width, proxy, cookie) 
+    // before the message stack unlocks/collapses. This works out well because we 
+    // want to allow upto 5 parallel tasks anyway
+    private static final int MAX_WORKERS = MAX_PARALLEL_INITS * 4;
+    private static final int PRIORITY_WORKERS = MAX_PARALLEL_INITS * 2;
+
+    private static LinkedList<String> priorityWaitQueue = new LinkedList<String>();
+
+    private LinkedList<String> readQueue = new LinkedList<String>();
+    private ArrayList<PluginMessageHandlerWorker> workers = new ArrayList<PluginMessageHandlerWorker>();
+    private PluginStreamHandler streamHandler;
+    private ConsumerThread consumerThread = new ConsumerThread();
+
+    public PluginMessageConsumer(PluginStreamHandler streamHandler) {
+        this.streamHandler = streamHandler;
+        this.consumerThread.start();
+    }
+
+    /** 
+     * Registers a reference to wait for. Responses to registered priority 
+     * references get handled by priority worker if normal workers are busy.
+     *
+     * @param reference The reference to give priority to
+     */
+    public static void registerPriorityWait(Long reference) {
+        PluginDebug.debug("Registering priority for reference ", reference);
+        registerPriorityWait("reference " + reference.toString());
+    }
+
+    /** 
+     * Registers a string to wait for.
+     *
+     * @param searchString the string to look for in a response
+     */
+    private static void registerPriorityWait(String searchString) {
+        PluginDebug.debug("Registering priority for string ", searchString);
+        synchronized (priorityWaitQueue) {
+            if (!priorityWaitQueue.contains(searchString)) {
+                priorityWaitQueue.add(searchString);
+            }
+        }
+    }
+
+    /** 
+     * Unregisters a priority string to wait for.
+     *
+     * @param searchString The string to unregister from the priority list
+     */
+    private static void unRegisterPriorityWait(String searchString) {
+        synchronized (priorityWaitQueue) {
+            priorityWaitQueue.remove(searchString);
+        }
+    }
+
+    private static String getPriorityStrIfPriority(String message) {
+
+        // Destroy messages are permanently high priority
+        if (message.endsWith("destroy")) {
+            return "destroy";
+        }
+
+        synchronized (priorityWaitQueue) {
+            for (String priorityStr : priorityWaitQueue) {
+                if (message.indexOf(priorityStr) > 0) {
+                    return priorityStr; 
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void notifyWorkerIsFree(PluginMessageHandlerWorker worker) {
+        consumerThread.interrupt();
+    }
+
+    public void queue(String message) {
+        synchronized (readQueue) {
+            readQueue.addLast(message);
+        }
+
+        // Wake that lazy consumer thread
+        consumerThread.interrupt();
+    }
+
+    protected class ConsumerThread extends Thread {
+
+        /**
+         * Scans the readQueue for priority messages and brings them to the front
+         */
+        private void bringPriorityMessagesToFront() {
+            synchronized (readQueue) {
+
+                // iterate through the list
+                for (int i = 0; i < readQueue.size(); i++) {
+
+                    // remove element at i to inspect it
+                    String message = readQueue.remove(i);
+
+                    // if element at i is a priority msg, bring it forward
+                    if (getPriorityStrIfPriority(message) != null) {
+                        readQueue.addFirst(message);
+                    } else { // else keep it where it was
+                        readQueue.add(i, message);
+                    }
+
+                    // by the end the queue size is the same, so the 
+                    // position indicator (i) is still valid
+                }
+            }
+        }
+
+        public void run() {
+
+            while (true) {
+
+                String message = null;
+
+                synchronized (readQueue) {
+                    message = readQueue.poll();
+                }
+
+                if (message != null) {
+
+                    String priorityStr = getPriorityStrIfPriority(message);
+                    boolean isPriorityResponse = (priorityStr != null);
+
+                    //PluginDebug.debug("Message " + message + " (priority=" + isPriorityResponse + ") ready to be processed. Looking for free worker...");
+                    final PluginMessageHandlerWorker worker = getFreeWorker(isPriorityResponse);
+
+                    if (worker == null) {
+                        synchronized (readQueue) {
+                            readQueue.addFirst(message);
+                        }
+
+                        // re-scan to see if any priority message came in
+                        bringPriorityMessagesToFront();
+
+                        continue; // re-loop to try next msg
+                    }
+
+                    if (isPriorityResponse) {
+                        unRegisterPriorityWait(priorityStr);
+                    }
+
+                    worker.setmessage(message);
+                    worker.interrupt();
+
+                } else {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException ie) {
+                    }
+                }
+            }
+        }
+    }
+
+    private PluginMessageHandlerWorker getFreeWorker(boolean prioritized) {
+
+        for (PluginMessageHandlerWorker worker : workers) {
+            if (worker.isFree(prioritized)) {
+                PluginDebug.debug("Found free worker (", worker.isPriority(), ") with id ", worker.getWorkerId());
+                // mark it busy before returning
+                worker.busy();
+                return worker;
+            }
+        }
+
+        // If we have less than MAX_WORKERS, create a new worker
+        if (workers.size() <= MAX_WORKERS) {
+            PluginMessageHandlerWorker worker = null;
+
+            if (workers.size() < (MAX_WORKERS - PRIORITY_WORKERS)) {
+                PluginDebug.debug("Cannot find free worker, creating worker ", workers.size());
+                worker = new PluginMessageHandlerWorker(this, streamHandler, workers.size(), false);
+            } else if (prioritized) {
+                PluginDebug.debug("Cannot find free worker, creating priority worker ", workers.size());
+                worker = new PluginMessageHandlerWorker(this, streamHandler, workers.size(), true);
+            } else {
+                return null;
+            }
+
+            worker.start();
+            worker.busy();
+            workers.add(worker);
+            return worker;
+
+        }
+
+        // No workers available. Better luck next time! 
+        return null;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java	(revision 403)
@@ -0,0 +1,141 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+class PluginMessageHandlerWorker extends Thread {
+
+    private boolean free = true;
+    private final boolean isPriorityWorker;
+    private final int id;
+    private String message;
+    private PluginStreamHandler streamHandler;
+    private PluginMessageConsumer consumer;
+
+    public PluginMessageHandlerWorker(
+                PluginMessageConsumer consumer,
+                PluginStreamHandler streamHandler, int id,
+                boolean isPriorityWorker) {
+
+        this.id = id;
+        this.streamHandler = streamHandler;
+        this.isPriorityWorker = isPriorityWorker;
+        this.consumer = consumer;
+
+        PluginDebug.debug("Worker ", this.id, " (priority=", isPriorityWorker, ") created.");
+    }
+
+    public void setmessage(String message) {
+        this.message = message;
+    }
+
+    public void run() {
+        while (true) {
+
+            if (message != null) {
+
+                PluginDebug.debug("Consumer (priority=", isPriorityWorker, ") thread ", id, " consuming ", message);
+
+                // ideally, whoever returns this object should mark it
+                // busy first, but just in case..
+                busy();
+
+                try {
+                    streamHandler.handleMessage(message);
+                } catch (PluginException pe) {
+                    /*
+                       catch the exception and DO NOTHING. The plugin should take over after 
+                       this error and let the user know. We don't quit because otherwise the 
+                       exception will spread to the rest of the applets which is a no-no
+                     */
+                }
+
+                this.message = null;
+
+                PluginDebug.debug("Consumption (priority=", isPriorityWorker, ") completed by consumer thread ", id);
+
+                // mark ourselves free again
+                free();
+
+            } else {
+
+                // Sleep when there is nothing to do
+                try {
+                    Thread.sleep(Integer.MAX_VALUE);
+                    PluginDebug.debug("Consumer thread ", id, " sleeping...");
+                } catch (InterruptedException ie) {
+                    PluginDebug.debug("Consumer thread ", id, " woken...");
+                    // nothing.. someone woke us up, see if there 
+                    // is work to do
+                }
+            }
+        }
+    }
+
+    public int getWorkerId() {
+        return id;
+    }
+
+    public void busy() {
+        synchronized (this) {
+            this.free = false;
+        }
+    }
+
+    public void free() {
+        synchronized (this) {
+            this.free = true;
+
+            // Signal the consumer that we are done in case it was waiting
+            consumer.notifyWorkerIsFree(this);
+        }
+    }
+
+    public boolean isPriority() {
+        return isPriorityWorker;
+    }
+
+    public boolean isFree(boolean prioritized) {
+        synchronized (this) {
+            return free && (prioritized == isPriorityWorker);
+        }
+    }
+
+    public String toString() {
+        return "Worker #" + this.id + "/IsPriority=" + this.isPriorityWorker + "/IsFree=" + this.free + "/Message=" + message;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginObjectStore.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginObjectStore.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginObjectStore.java	(revision 403)
@@ -0,0 +1,143 @@
+/* PluginObjectStore -- manage identifier-to-object mapping
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.util.HashMap;
+import java.util.Map;
+
+// Enums are the best way to implement singletons:
+// Bloch, Joshua. Effective Java, 2nd Edition. Item 3, Chapter 2. ISBN: 0-321-35668-3.
+enum PluginObjectStore {
+    INSTANCE;
+
+    private HashMap<Integer, Object> objects = new HashMap<Integer, Object>();
+    private HashMap<Integer, Integer> counts = new HashMap<Integer, Integer>();
+    private HashMap<Object, Integer> identifiers = new HashMap<Object, Integer>();
+    private final Object lock = new Object();
+
+    private boolean wrapped = false;
+    private int nextUniqueIdentifier = 1;
+
+    public static PluginObjectStore getInstance() {
+        return INSTANCE;
+    }
+
+    public Object getObject(Integer identifier) {
+        synchronized(lock) {
+            return objects.get(identifier);
+        }
+    }
+
+    public Integer getIdentifier(Object object) {
+        synchronized(lock) {
+            if (object == null)
+                return 0;
+            return identifiers.get(object);
+        }
+    }
+
+    public boolean contains(Object object) {
+        synchronized(lock) {
+            if (object == null)
+                return identifiers.containsKey(object);
+
+            return false;
+        }
+    }
+
+    public boolean contains(int identifier) {
+        synchronized(lock) {
+            return objects.containsKey(identifier);
+        }
+    }
+
+    private boolean checkNeg() {
+        if (nextUniqueIdentifier < 1) {
+            wrapped = true;
+            nextUniqueIdentifier = 1;
+        }
+        return wrapped;
+    }
+
+    private int getNextID() {
+        while (checkNeg() && objects.containsKey(nextUniqueIdentifier))
+            nextUniqueIdentifier++;
+        return nextUniqueIdentifier++;
+    }
+
+    public void reference(Object object) {
+        synchronized(lock) {
+            Integer identifier = identifiers.get(object);
+            if (identifier == null) {
+                int next = getNextID();
+                objects.put(next, object);
+                counts.put(next, 1);
+                identifiers.put(object, next);
+            } else {
+                counts.put(identifier, counts.get(identifier) + 1);
+            }
+        }
+    }
+
+    public void unreference(int identifier) {
+        synchronized(lock) {
+            Integer currentCount = counts.get(identifier);
+            if (currentCount == null) {
+                return;
+            }
+            if (currentCount == 1) {
+                Object object = objects.get(identifier);
+                objects.remove(identifier);
+                counts.remove(identifier);
+                identifiers.remove(object);
+            } else {
+                counts.put(identifier, currentCount - 1);
+            }
+        }
+    }
+
+    public void dump() {
+        synchronized(lock) {
+            if (PluginDebug.DEBUG) {
+                for (Map.Entry<Integer, Object> e : objects.entrySet()) {
+                    PluginDebug.debug(e.getKey(), "::", e.getValue());
+                }
+            }
+        }
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java	(revision 403)
@@ -0,0 +1,80 @@
+/* PluginProxyInfoRequest -- Object representing a request for proxy information from the browser
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.net.URI;
+
+/**
+ * This class represents a request object for proxy information for a given URI
+ */
+
+public class PluginProxyInfoRequest extends PluginCallRequest {
+
+    URI internal = null;
+
+    public PluginProxyInfoRequest(String message, Long reference) {
+        super(message, reference);
+    }
+
+    public void parseReturn(String proxyInfo) {
+
+        // try to parse the proxy information. If things go wrong, do nothing .. 
+        // this will keep internal = null which forces a direct connection
+
+        PluginDebug.debug("PluginProxyInfoRequest GOT: ", proxyInfo);
+        String[] messageComponents = proxyInfo.split(" ");
+
+        try {
+            String protocol = messageComponents[4].equals("PROXY") ? "http" : "socks";
+            String host = messageComponents[5].split(":")[0];
+            int port = Integer.parseInt(messageComponents[5].split(":")[1]);
+
+            internal = new URI(protocol, null, host, port, null, null, null);
+        } catch (ArrayIndexOutOfBoundsException aioobe) {
+            // Nothing.. this is expected if there is no proxy
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        setDone(true);
+    }
+
+    public URI getObject() {
+        return this.internal;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxySelector.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxySelector.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginProxySelector.java	(revision 403)
@@ -0,0 +1,131 @@
+/* PluginProxySelector -- proxy selector for all connections from applets and the plugin
+   Copyright (C) 2009  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.jnlp.runtime.JNLPProxySelector;
+import net.sourceforge.jnlp.util.TimedHashMap;
+
+/**
+ * Proxy selector implementation for plugin network functions.
+ *
+ * This class fetches proxy information from the web browser and
+ * uses that information in the context of all network connection
+ * (plugin specific and applet connections) as applicable
+ *
+ */
+
+public class PluginProxySelector extends JNLPProxySelector {
+
+    private TimedHashMap<String, Proxy> proxyCache = new TimedHashMap<String, Proxy>();
+
+    /**
+     * Selects the appropriate proxy (or DIRECT connection method) for the given URI
+     *
+     * @param uri The URI being accessed
+     * @return A list of Proxy objects that are usable for this URI
+     */
+    @Override
+    protected List<Proxy> getFromBrowser(URI uri) {
+
+        List<Proxy> proxyList = new ArrayList<Proxy>();
+
+        // check cache first
+        Proxy cachedProxy = checkCache(uri);
+        if (cachedProxy != null) {
+            proxyList.add(cachedProxy);
+            return proxyList;
+        }
+
+        // Nothing usable in cache. Fetch info from browser
+        Proxy proxy = Proxy.NO_PROXY;
+        Object o = PluginAppletViewer.requestPluginProxyInfo(uri);
+
+        // If the browser returned anything, try to parse it. If anything in the try block fails, the fallback is direct connection
+        try {
+            if (o != null) {
+                PluginDebug.debug("Proxy URI = ", o);
+                URI proxyURI = (URI) o;
+
+                // If origin uri is http/ftp, we're good. If origin uri is not that, the proxy _must_ be socks, else we fallback to direct
+                if (uri.getScheme().startsWith("http") || uri.getScheme().equals("ftp") || proxyURI.getScheme().startsWith("socks")) {
+
+                    Proxy.Type type = proxyURI.getScheme().equals("http") ? Proxy.Type.HTTP : Proxy.Type.SOCKS;
+                    InetSocketAddress socketAddr = new InetSocketAddress(proxyURI.getHost(), proxyURI.getPort());
+
+                    proxy = new Proxy(type, socketAddr);
+
+                    String uriKey = uri.getScheme() + "://" + uri.getHost();
+                    proxyCache.put(uriKey, proxy);
+                } else {
+                    PluginDebug.debug("Proxy ", proxyURI, " cannot be used for ", uri, ". Falling back to DIRECT");
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        proxyList.add(proxy);
+
+        PluginDebug.debug("Proxy for ", uri.toString(), " is ", proxy);
+
+        return proxyList;
+    }
+
+    /**
+     * Checks to see if proxy information is already cached.
+     *
+     * @param uri The URI to check
+     * @return The cached Proxy. null if there is no suitable cached proxy.
+     */
+    private Proxy checkCache(URI uri) {
+
+        String uriKey = uri.getScheme() + "://" + uri.getHost();
+        if (proxyCache.get(uriKey) != null) {
+            return proxyCache.get(uriKey);
+        }
+
+        return null;
+    }
+
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginStreamHandler.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginStreamHandler.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/PluginStreamHandler.java	(revision 403)
@@ -0,0 +1,396 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.nio.charset.Charset;
+
+import javax.swing.SwingUtilities;
+
+public class PluginStreamHandler {
+
+    private BufferedReader pluginInputReader;
+    private BufferedWriter pluginOutputWriter;
+
+    private RequestQueue queue = new RequestQueue();
+
+    private JavaConsole console = new JavaConsole();
+
+    private PluginMessageConsumer consumer;
+    private Boolean shuttingDown = false;
+
+
+    public PluginStreamHandler(InputStream inputstream, OutputStream outputstream)
+            throws MalformedURLException, IOException {
+
+        PluginDebug.debug("Current context CL=", Thread.currentThread().getContextClassLoader());
+
+        PluginDebug.debug("Creating consumer...");
+        consumer = new PluginMessageConsumer(this);
+
+        // Set up input and output pipes.  Use UTF-8 encoding.
+        pluginInputReader =
+                new BufferedReader(new InputStreamReader(inputstream,
+                        Charset.forName("UTF-8")));
+        pluginOutputWriter =
+                new BufferedWriter(new OutputStreamWriter
+                        (outputstream, Charset.forName("UTF-8")));
+    }
+
+    public void startProcessing() {
+
+        Thread listenerThread = new Thread() {
+
+            public void run() {
+
+                while (true) {
+
+                    PluginDebug.debug("Waiting for data...");
+
+                    String s = read();
+
+                    if (s != null) {
+                        consumer.queue(s);
+                    } else {
+                        try {
+                            // Close input/output channels to plugin.
+                            pluginInputReader.close();
+                            pluginOutputWriter.close();
+                        } catch (IOException exception) {
+                            // Deliberately ignore IOException caused by broken
+                            // pipe since plugin may have already detached.
+                        }
+                        AppletSecurityContextManager.dumpStore(0);
+                        PluginDebug.debug("APPLETVIEWER: exiting appletviewer");
+                        System.exit(0);
+                    }
+                }
+            }
+        };
+
+        listenerThread.start();
+    }
+
+    /**
+     * Given a string, reads the first two (space separated) tokens.
+     *
+     * @param message The string to read
+     * @param start The position to start reading at
+     * @param array The array into which the first two tokens are placed
+     * @return Position where the next token starts
+     */
+    private int readPair(String message, int start, String[] array) {
+        
+        int end = start;
+        array[0] = null;
+        array[1] = null;
+
+        if (message.length() > start) {
+            int firstSpace = message.indexOf(' ', start);
+            if (firstSpace == -1) {
+                array[0] = message.substring(start);
+                end = message.length();
+            } else {
+                array[0] = message.substring(start, firstSpace);
+                if (message.length() > firstSpace + 1) {
+                    int secondSpace = message.indexOf(' ', firstSpace + 1);
+                    if (secondSpace == -1) {
+                        array[1] = message.substring(firstSpace + 1);
+                        end = message.length();
+                    } else {
+                        array[1] = message.substring(firstSpace + 1, secondSpace);
+                        end = secondSpace + 1;
+                    }
+                }
+            }
+        }
+
+        PluginDebug.debug("readPair: '", array[0], "' - '", array[1], "' ", end);
+        return end;
+    }
+
+    public void handleMessage(String message) throws PluginException {
+
+        int reference = -1;
+        String src = null;
+        String[] privileges = null;
+        String rest = "";
+        String[] msgComponents = new String[2];
+        int pos = 0;
+        int oldPos = 0;
+
+        pos = readPair(message, oldPos, msgComponents);
+        if (msgComponents[0] == null || msgComponents[1] == null) {
+            return;
+        }
+
+        if (msgComponents[0].startsWith("plugin")) {
+            handlePluginMessage(message);
+            return;
+        }
+
+        // type and identifier are guaranteed to be there
+        String type = msgComponents[0];
+        final int identifier = Integer.parseInt(msgComponents[1]);
+
+        // reference, src and privileges are optional components, 
+        // and are guaranteed to be in that order, if they occur
+        oldPos = pos;
+        pos = readPair(message, oldPos, msgComponents);
+
+        // is there a reference ?
+        if ("reference".equals(msgComponents[0])) {
+            reference = Integer.parseInt(msgComponents[1]);
+            oldPos = pos;
+            pos = readPair(message, oldPos, msgComponents);
+        }
+
+        // is there a src?
+        if ("src".equals(msgComponents[0])) {
+            src = msgComponents[1];
+            oldPos = pos;
+            pos = readPair(message, oldPos, msgComponents);
+        }
+
+        // is there a privileges?
+        if ("privileges".equals(msgComponents[0])) {
+            String privs = msgComponents[1];
+            privileges = privs.split(",");
+            oldPos = pos;
+        }
+
+        // rest
+        if (message.length() > oldPos) {
+            rest = message.substring(oldPos);
+        }
+
+        try {
+
+            PluginDebug.debug("Breakdown -- type: ", type, " identifier: ", identifier, " reference: ", reference, " src: ", src, " privileges: ", privileges, " rest: \"", rest, "\"");
+
+            if (rest.contains("JavaScriptGetWindow")
+                    || rest.contains("JavaScriptGetMember")
+                    || rest.contains("JavaScriptSetMember")
+                    || rest.contains("JavaScriptGetSlot")
+                    || rest.contains("JavaScriptSetSlot")
+                    || rest.contains("JavaScriptEval")
+                    || rest.contains("JavaScriptRemoveMember")
+                    || rest.contains("JavaScriptCall")
+                    || rest.contains("JavaScriptFinalize")
+                    || rest.contains("JavaScriptToString")) {
+
+                finishCallRequest("reference " + reference + " " + rest);
+                return;
+            }
+
+            final int freference = reference;
+            final String frest = rest;
+
+            if (type.equals("instance")) {
+                PluginAppletViewer.handleMessage(identifier, freference, frest);
+            } else if (type.equals("context")) {
+                PluginDebug.debug("Sending to PASC: ", identifier, "/", reference, " and ", rest);
+                AppletSecurityContextManager.handleMessage(identifier, reference, src, privileges, rest);
+            }
+        } catch (Exception e) {
+            throw new PluginException(this, identifier, reference, e);
+        }
+    }
+
+    private void handlePluginMessage(String message) {
+        if (message.equals("plugin showconsole")) {
+            showConsole();
+        } else if (message.equals("plugin hideconsole")) {
+            hideConsole();
+        } else {
+            // else this is something that was specifically requested
+            finishCallRequest(message);
+        }
+    }
+
+    public void postCallRequest(PluginCallRequest request) {
+        synchronized (queue) {
+            queue.post(request);
+        }
+    }
+
+    private void finishCallRequest(String message) {
+        PluginDebug.debug("DISPATCHCALLREQUESTS 1");
+        synchronized (queue) {
+            PluginDebug.debug("DISPATCHCALLREQUESTS 2");
+            PluginCallRequest request = queue.pop();
+
+            // make sure we give the message to the right request 
+            // in the queue.. for the love of God, MAKE SURE!
+
+            // first let's be efficient.. if there was only one 
+            // request in queue, we're already set
+            if (queue.size() != 0) {
+
+                int size = queue.size();
+                int count = 0;
+
+                while (!request.serviceable(message)) {
+
+                    PluginDebug.debug(request, " cannot service ", message);
+
+                    // something is very wrong.. we have a message to 
+                    // process, but no one to service it
+                    if (count >= size) {
+                        throw new RuntimeException("Unable to find processor for message " + message);
+                    }
+
+                    // post request at the end of the queue
+                    queue.post(request);
+
+                    // Look at the next request
+                    request = queue.pop();
+
+                    count++;
+                }
+
+            }
+
+            PluginDebug.debug("DISPATCHCALLREQUESTS 3");
+            if (request != null) {
+                PluginDebug.debug("DISPATCHCALLREQUESTS 5");
+                synchronized (request) {
+                    request.parseReturn(message);
+                    request.notifyAll();
+                }
+                PluginDebug.debug("DISPATCHCALLREQUESTS 6");
+                PluginDebug.debug("DISPATCHCALLREQUESTS 7");
+            }
+        }
+        PluginDebug.debug("DISPATCHCALLREQUESTS 8");
+    }
+
+    /**
+     * Read string from plugin.
+     *
+     * @return the read string
+     *
+     * @exception IOException if an error occurs
+     */
+    private String read() {
+        String message = null;
+
+        try {
+            message = pluginInputReader.readLine();
+            PluginDebug.debug("  PIPE: appletviewer read: ", message);
+
+            if (message == null || message.equals("shutdown")) {
+                synchronized (shuttingDown) {
+                    shuttingDown = true;
+                }
+                try {
+                    // Close input/output channels to plugin.
+                    pluginInputReader.close();
+                    pluginOutputWriter.close();
+                } catch (IOException exception) {
+                    // Deliberately ignore IOException caused by broken
+                    // pipe since plugin may have already detached.
+                }
+                AppletSecurityContextManager.dumpStore(0);
+                PluginDebug.debug("APPLETVIEWER: exiting appletviewer");
+                System.exit(0);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return message;
+    }
+
+    /**
+     * Write string to plugin.
+     * 
+     * @param message the message to write
+     *
+     * @exception IOException if an error occurs
+     */
+    public void write(String message) {
+
+        PluginDebug.debug("  PIPE: appletviewer wrote: ", message);
+        synchronized (pluginOutputWriter) {
+            try {
+                pluginOutputWriter.write(message + "\n", 0, message.length());
+                pluginOutputWriter.write(0);
+                pluginOutputWriter.flush();
+            } catch (IOException e) {
+                // if we are shutting down, ignore write failures as 
+                // pipe may have closed
+                synchronized (shuttingDown) {
+                    if (!shuttingDown) {
+                        e.printStackTrace();
+                    }
+                }
+
+                // either ways, if the pipe is broken, there is nothing 
+                // we can do anymore. Don't hang around.
+                PluginDebug.debug("Unable to write to PIPE. APPLETVIEWER exiting");
+                System.exit(1);
+            }
+        }
+
+        return;
+    }
+
+    private void showConsole() {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                console.showConsole();
+            }
+        });
+    }
+
+    private void hideConsole() {
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                console.hideConsole();
+            }
+        });
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/RequestQueue.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/RequestQueue.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/RequestQueue.java	(revision 403)
@@ -0,0 +1,75 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class RequestQueue {
+    PluginCallRequest head = null;
+    PluginCallRequest tail = null;
+    private int size = 0;
+
+    public void post(PluginCallRequest request) {
+        PluginDebug.debug("Securitymanager=", System.getSecurityManager());
+        if (head == null) {
+            head = tail = request;
+            tail.setNext(null);
+        } else {
+            tail.setNext(request);
+            tail = request;
+            tail.setNext(null);
+        }
+
+        size++;
+    }
+
+    public PluginCallRequest pop() {
+        if (head == null)
+            return null;
+
+        PluginCallRequest ret = head;
+        head = head.getNext();
+        ret.setNext(null);
+
+        size--;
+
+        return ret;
+    }
+
+    public int size() {
+        return size;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/TestEnv.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/TestEnv.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/TestEnv.java	(revision 403)
@@ -0,0 +1,171 @@
+/* TestEnv -- test JavaScript-to-Java calls
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class TestEnv {
+    public static int intField = 103;
+    public int intInstanceField = 7822;
+    public String stringField = "hello";
+    // z <musical G clef> <chinese water>
+    public String complexStringField = "z\uD834\uDD1E\u6C34";
+
+    public static void TestIt() {
+        PluginDebug.debug("TestIt");
+    }
+
+    public static void TestItBool(boolean arg) {
+        PluginDebug.debug("TestItBool: " + arg);
+    }
+
+    public static void TestItByte(byte arg) {
+        PluginDebug.debug("TestItByte: " + arg);
+    }
+
+    public static void TestItChar(char arg) {
+        PluginDebug.debug("TestItChar: " + arg);
+    }
+
+    public static void TestItShort(short arg) {
+        PluginDebug.debug("TestItShort: " + arg);
+    }
+
+    public static void TestItInt(int arg) {
+        PluginDebug.debug("TestItInt: " + arg);
+    }
+
+    public static void TestItLong(long arg) {
+        PluginDebug.debug("TestItLong: " + arg);
+    }
+
+    public static void TestItFloat(float arg) {
+        PluginDebug.debug("TestItFloat: " + arg);
+    }
+
+    public static void TestItDouble(double arg) {
+        PluginDebug.debug("TestItDouble: " + arg);
+    }
+
+    public static void TestItObject(TestEnv arg) {
+        PluginDebug.debug("TestItObject: " + arg);
+    }
+
+    public static void TestItObjectString(String arg) {
+        PluginDebug.debug("TestItObjectString: " + arg);
+    }
+
+    public static void TestItIntArray(int[] arg) {
+        PluginDebug.debug("TestItIntArray: " + arg);
+        for (int i = 0; i < arg.length; i++)
+            PluginDebug.debug("ELEMENT: " + i + " " + arg[i]);
+    }
+
+    public static void TestItObjectArray(String[] arg) {
+        PluginDebug.debug("TestItObjectArray: " + arg);
+        for (int i = 0; i < arg.length; i++)
+            PluginDebug.debug("ELEMENT: " + i + " " + arg[i]);
+    }
+
+    public static void TestItObjectArrayMulti(String[][] arg) {
+        PluginDebug.debug("TestItObjectArrayMulti: " + arg);
+        for (int i = 0; i < arg.length; i++)
+            for (int j = 0; j < arg[i].length; j++)
+                PluginDebug.debug("ELEMENT: " + i + " " + j + " " + arg[i][j]);
+    }
+
+    public static boolean TestItBoolReturnTrue() {
+        return true;
+    }
+
+    public static boolean TestItBoolReturnFalse() {
+        return false;
+    }
+
+    public static byte TestItByteReturn() {
+        return (byte) 0xfe;
+    }
+
+    public static char TestItCharReturn() {
+        return 'K';
+    }
+
+    public static char TestItCharUnicodeReturn() {
+        return '\u6C34';
+    }
+
+    public static short TestItShortReturn() {
+        return 23;
+    }
+
+    public static int TestItIntReturn() {
+        return 3445;
+    }
+
+    public static long TestItLongReturn() {
+        return 3242883;
+    }
+
+    public static float TestItFloatReturn() {
+        return 9.21E4f;
+    }
+
+    public static double TestItDoubleReturn() {
+        return 8.33E88;
+    }
+
+    public static Object TestItObjectReturn() {
+        return new String("Thomas");
+    }
+
+    public static int[] TestItIntArrayReturn() {
+        return new int[] { 6, 7, 8 };
+    }
+
+    public static String[] TestItObjectArrayReturn() {
+        return new String[] { "Thomas", "Brigitte" };
+    }
+
+    public static String[][] TestItObjectArrayMultiReturn() {
+        return new String[][] { { "Thomas", "Brigitte" },
+                                { "Lindsay", "Michael" } };
+    }
+
+    public int TestItIntInstance(int arg) {
+        PluginDebug.debug("TestItIntInstance: " + this + " " + arg);
+        return 899;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java	(revision 403)
@@ -0,0 +1,53 @@
+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+public class VoidPluginCallRequest extends PluginCallRequest {
+    public VoidPluginCallRequest(String message, Long reference) {
+        super(message, reference);
+        PluginDebug.debug("VoidPluginCall ", message);
+    }
+
+    public void parseReturn(String message) {
+        setDone(true);
+    }
+
+    public Object getObject() {
+        return null;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.cc	(revision 403)
@@ -0,0 +1,138 @@
+/* OS_OS2.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#define INCL_DOS
+#define INCL_PM
+#define INCL_ERRORS
+#include <os2.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "OS_OS2.h"
+#include "OS_OS2_WinOS2.h"
+
+const char *icedtea_web_data_dir()
+{
+    const char *home = getenv("ICEDTEA_WEB_DATA");
+    if (!home)
+    {
+#if !defined(ICEDTEA_WEB_DATA_DIR)
+        // deduce the path from this DLL's name
+        static char buf[CCHMAXPATH] = {0};
+        if (buf[0] == 0)
+        {
+            BOOL ok = FALSE;
+            HMODULE hmod;
+            ULONG objNum, offset;
+            APIRET rc;
+            rc = DosQueryModFromEIP(&hmod, &objNum, sizeof(buf), buf, &offset,
+                                    (ULONG)&icedtea_web_data_dir);
+            if (rc == NO_ERROR)
+            {
+                rc = DosQueryModuleName(hmod, sizeof(buf), buf);
+                if (rc == NO_ERROR)
+                {
+                    // truncate the extension to get the data dir
+                    char *end = strrchr(buf, '.');
+                    if (end)
+                    {
+                        *end = '\0';
+                        ok = TRUE;
+                    }
+                }
+            }
+            if (!ok)
+                strcpy(buf, ".");
+        }
+        home = buf;
+#else
+        home = ICEDTEA_WEB_DATA_DIR;
+#endif
+    }
+    return home;
+}
+
+const char *icedtea_web_jre_dir()
+{
+    const char *jre = getenv("ICEDTEA_WEB_JRE");
+    if (!jre)
+    {
+#if !defined(ICEDTEA_WEB_JRE_DIR)
+        // deduce the path from JAVA.EXE found in PATH
+        static char buf[CCHMAXPATH] = {0};
+        if (buf[0] == 0)
+        {
+            BOOL ok = FALSE;
+            APIRET rc;
+            rc = DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT |
+                               SEARCH_CUR_DIRECTORY,
+                               "PATH", "JAVA.EXE", buf, sizeof(buf));
+            if (rc == NO_ERROR)
+            {
+                char *end = strrchr(buf, '\\');
+                if (end)
+                {
+                    *end = '\0';
+                    ok = TRUE;
+                    // truncate \bin if present
+                    end = strrchr(buf, '\\');
+                    if (end && stricmp(end + 1, "bin") == 0)
+                        *end = '\0';
+                }
+            }
+            if (!ok)
+                strcpy(buf, ".");
+        }
+        jre = buf;
+#else
+        jre = ICEDTEA_WEB_JRE_DIR;
+#endif
+    }
+    return jre;
+}
+
+bool init_os()
+{
+    return init_os_winos2();
+}
+
+void done_os()
+{
+    done_os_winos2();
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2.h	(revision 403)
@@ -0,0 +1,50 @@
+/* OS_OS2.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __OS_OS2_H__
+#define __OS_OS2_H__
+
+const char *icedtea_web_data_dir();
+const char *icedtea_web_jre_dir();
+
+bool init_os();
+void done_os();
+
+void *wrap_window_handle (void *handle);
+
+#endif // __OS_OS2_H__
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.cc
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.cc	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.cc	(revision 403)
@@ -0,0 +1,79 @@
+/* OS_OS2_WinOS2.cc
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include <windows.h>
+
+#include <winuser32.h> // CreateFakeWindowEx and friends
+
+#include "IcedTeaPluginUtils.h"
+
+static ATOM WrapperClass;
+
+LRESULT WIN32API WrapperWndProc (HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+    return DefWindowProc (hwnd, msg, mp1, mp2);
+}
+
+bool init_os_winos2()
+{
+    WNDCLASSA WndClass;
+    memset (&WndClass, 0, sizeof(WndClass));
+    WndClass.lpfnWndProc = WrapperWndProc;
+    WndClass.lpszClassName = "WC_ICEDTEANP_WRAPPER";
+    WndClass.cbWndExtra = 0;
+    WrapperClass = RegisterClass (&WndClass);
+    if (!WrapperClass)
+    {
+        PLUGIN_DEBUG ("RegisterClass failed.\n");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+void done_os_winos2()
+{
+    if (!UnregisterClass ("WC_ICEDTEANP_WRAPPER", 0));
+        PLUGIN_DEBUG ("UnregisterClass failed.\n");
+}
+
+void *wrap_window_handle (void *handle)
+{
+    HWND hwnd = CreateFakeWindowEx ((HWND) handle, WrapperClass);
+    return (void *) hwnd;
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.h
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.h	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/OS_OS2_WinOS2.h	(revision 403)
@@ -0,0 +1,45 @@
+/* OS_OS2_WinOS2.h
+
+   Copyright (C) 2009, 2010  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+#ifndef __OS_OS2_WINOS2_H__
+#define __OS_OS2_WINOS2_H__
+
+bool init_os_winos2();
+void done_os_winos2();
+
+#endif // __OS_OS2_WINOS2_H__
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginAppletViewerBase.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginAppletViewerBase.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginAppletViewerBase.java	(revision 403)
@@ -0,0 +1,50 @@
+/* PluginAppletViewerBase -- OS/2 version
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import sun.awt.windows.WEmbeddedFrame;
+
+class PluginAppletViewerBase extends WEmbeddedFrame {
+
+    PluginAppletViewerBase() {
+    }
+
+    PluginAppletViewerBase(long handle) {
+        super(handle);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginMainBase.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginMainBase.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/os2/java/sun/applet/PluginMainBase.java	(revision 403)
@@ -0,0 +1,77 @@
+/* PluginMainBase -- OS/2 version
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+class PluginMainBase {
+
+    private static int inPipe = -1;
+    private static int outPipe = -1;
+
+    static boolean checkArgs(String args[]) {
+        if (args.length == 2) {
+            inPipe = Integer.valueOf(args[0]).intValue();
+            outPipe = Integer.valueOf(args[1]).intValue();
+            if (inPipe >= 0 && outPipe >= 0)
+                return true;
+        }
+        System.err.println("Invalid pipe descriptors provided. Refusing to proceed.");
+        return false;
+    }
+
+    static PluginStreamHandler connect(String args[]) {
+        PluginStreamHandler streamHandler = null;
+        sun.misc.JavaIOFileDescriptorAccess fdAccess = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
+        FileDescriptor inPipeFD = new FileDescriptor();
+        fdAccess.set(inPipeFD, inPipe);
+        FileDescriptor outPipeFD = new FileDescriptor();
+        fdAccess.set(outPipeFD, outPipe);
+        try {
+            streamHandler = new PluginStreamHandler(new FileInputStream(inPipeFD), new FileOutputStream(outPipeFD));
+            PluginDebug.debug("Streams initialized");
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+        return streamHandler;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginAppletViewerBase.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginAppletViewerBase.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginAppletViewerBase.java	(revision 403)
@@ -0,0 +1,50 @@
+/* PluginAppletViewerBase -- Linux version
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import sun.awt.X11.XEmbeddedFrame;
+
+class PluginAppletViewerBase extends XEmbeddedFrame {
+
+    PluginAppletViewerBase() {
+    }
+
+    PluginAppletViewerBase(long handle) {
+        super(handle, true);
+    }
+}
Index: /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginMainBase.java
===================================================================
--- /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginMainBase.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/icedteanp/x11/java/sun/applet/PluginMainBase.java	(revision 403)
@@ -0,0 +1,67 @@
+/* PluginMainBase -- Linux version
+   Copyright (C) 2008  Red Hat
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.applet;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+class PluginMainBase {
+
+    static boolean checkArgs(String args[]) {
+        if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) {
+            System.err.println("Invalid pipe names provided. Refusing to proceed.");
+            return false;
+        }
+        return true;
+    }
+
+    static PluginStreamHandler connect(String args[]) {
+        String inPipe = args[0];
+        String outPipe = args[1];
+        PluginStreamHandler streamHandler = null;
+        try {
+            streamHandler = new PluginStreamHandler(new FileInputStream(inPipe), new FileOutputStream(outPipe));
+            PluginDebug.debug("Streams initialized");
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+        return streamHandler;
+    }
+}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/DummyObject.java
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/DummyObject.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/DummyObject.java	(revision 403)
@@ -0,0 +1,15 @@
+public class DummyObject {
+     private String str;
+     
+     public DummyObject(String s) {
+        this.str = s;
+     }
+     
+     public void setStr(String s) {
+        this.str = s;
+     }
+     
+     public String toString() {
+        return str;
+     }
+}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper1.java
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper1.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper1.java	(revision 403)
@@ -0,0 +1,1 @@
+public class OverloadTestHelper1 {}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper2.java
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper2.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper2.java	(revision 403)
@@ -0,0 +1,1 @@
+public class OverloadTestHelper2 extends OverloadTestHelper1 {}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper3.java
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper3.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/OverloadTestHelper3.java	(revision 403)
@@ -0,0 +1,1 @@
+public class OverloadTestHelper3 extends  OverloadTestHelper2 {}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/PluginTest.java
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/PluginTest.java	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/PluginTest.java	(revision 403)
@@ -0,0 +1,710 @@
+import javax.swing.JApplet;
+import java.awt.Graphics;
+import java.awt.*;
+import java.applet.*;
+import java.awt.event.*;
+import netscape.javascript.JSObject;
+import java.lang.reflect.Array;
+
+public class PluginTest extends JApplet {
+
+    public int i = 42;
+    public double d = 42.42;
+    public float f = 42.1F;
+    public long l = 4294967296L;
+    public boolean b = true;
+    public char c = '\u2323';
+    public byte by = 43;
+    public String rs = "I'm a string!";
+    public String ss = "ð ãÂ£$Ç£â¬ð";
+    public Object n = null;
+    public int[] ia = new int[5];
+
+    public Integer I = 24;
+    public Double D = 24.24;
+    public Float F = 24.124F;
+    public Long L = 6927694924L;
+    public Boolean B = false;
+    public Character C = '\u1526';
+    public Byte By = 34;
+    public Double[] Da1 = new Double[10];
+    public Double[] Da2 = null;
+
+    public char[] ca = new char[3];
+    public Character[] Ca = new Character[3];
+
+    public void setUpForGMTests() {
+        i = 42;
+        d = 42.42;
+        f = 42.1F;
+        l = 4294967296L;
+        b = true;
+        c = '\u2323';
+        by = 43;
+        rs = "I'm a string!";
+        ss = "ð ãÂ£$Ç£â¬ð";
+        n = null;
+
+        I = 24;
+        D = 24.24;
+        F = 24.124F;
+        L = 6927694924L;
+        B = false;
+        C = '\u1526';
+        By = 34;
+
+        ia[4] = 1024;
+        Da1[9] = D;
+    }
+
+    public void setUpForSMTests() {
+        i = 0;
+        d = 0.0;
+        f = 0F;
+        l = 0L;
+        b = false;
+        c = 'A';
+        by = 0;
+        rs = "";
+        ss = "";
+        n = new String("non-null object");
+
+        I = 0;
+        D = 0.0;
+        F = 0F;
+        L = 0L;
+        B = false;
+        C = 'A';
+        By = null;
+
+        ia[4] = 0;
+        Da1[9] = D;
+    }
+
+    /*
+     *****************************************
+     * JS -> Java Parameter conversion tests *
+     *****************************************
+    */
+    public void setUpForReturnTests() {
+        i = 41;
+        d = 41.41;
+        f = 41.411F;
+        l = 4294967297L;
+        b = true;
+        c = '\u2329';
+        by = 44;
+        rs = "I'm a string too!";
+        ss = "ð ãÂ£$Ç£â¬ð";
+        n = null;
+
+        I = 14;
+        D = 14.14;
+        F = 14.114F;
+        L = 6927694925L;
+        B = false;
+        C = '\u2417';
+        By = 46;
+    }
+
+    /*
+     **************************************
+     * JS -> Java invocation return tests *
+     **************************************
+    */
+
+    public int intReturnTest() { return i; }
+
+    public double doubleReturnTest() { return d; }
+
+    public float floatReturnTest() { return f; }
+
+    public long longReturnTest() { return l; }
+
+    public boolean booleanReturnTest() { return b; }
+
+    public char charReturnTest() { return c; }
+
+    public byte byteReturnTest() { return by; }
+    
+    public char[] charArrayReturnTest() { 
+        ca[0] = '\u2410';
+        ca[1] = '\u2411';
+        ca[2] = '\u2412';
+        return ca; 
+    }
+
+    public String regularStringReturnTest() { return rs; }
+
+    public String specialStringReturnTest() { return ss; }
+
+    public void voidReturnTest() { }
+
+    public Object nullReturnTest() { return null; }
+
+    public Integer IntegerReturnTest() { return I; }
+
+    public Double DoubleReturnTest() { return D; }
+    public void DoubleSetTest(double set) { D = set; }
+
+    public Float FloatReturnTest() { return F; }
+
+    public Long LongReturnTest() { return L; }
+
+    public Boolean BooleanReturnTest() { return B; }
+
+    public Character CharacterReturnTest() { return C; }
+
+    public Byte ByteReturnTest() { return By; }
+
+    public Character[] CharacterArrayReturnTest() { 
+        Ca[0] = '\u2350';
+        Ca[1] = '\u2351';
+        Ca[2] = '\u2352';
+        return Ca; 
+    }
+
+    /*
+     **************************************
+     * JS -> Java parameter passing tests *
+     **************************************
+    */
+
+    public void setUpForParameterTests() {
+        i = 41;
+        d = 41.41;
+        f = 41.411F;
+        l = 4294967297L;
+        b = true;
+        c = '\u2329';
+        by = 44;
+        rs = "I'm a string too!";
+        ss = "ð ãÂ£$Ç£â¬ð";
+        n = null;
+
+        I = 14;
+        D = 14.14;
+        F = 14.114F;
+        L = 6927694925L;
+        B = false;
+        C = '\u2417';
+        By = 46;
+    }
+
+    public String functioniParamTest(int i) {
+       String ret = Integer.toString(i);
+       return ret;
+    }
+
+    public String functiondParamTest(double d) {
+        String ret = Double.toString(d);
+        return ret;
+     }
+
+    public String functionfParamTest(float f) {
+        String ret = Float.toString(f);
+        return ret;
+     }
+
+    public String functionlParamTest(long l) {
+        String ret = Long.toString(l);
+        return ret;
+    }
+    
+    public String functionbParamTest(boolean b) {
+        String ret = Boolean.toString(b);
+        return ret;
+     }
+    
+    public String functioncParamTest(char c) {
+        String ret = Character.toString(c);
+        return ret;
+     }
+    
+    public String functionbyParamTest(byte b) {
+        String ret = Byte.toString(b);
+        return ret;
+     }
+    
+     public String functioncaParamTest(char[] ca) {
+    
+        String ret = "";
+        ret += ca[0];
+        for (int i=1 ; i < ca.length; i++) {
+            ret += ":" + ca[i];
+        }
+
+        return ret;
+    }
+    
+    public String functionsiaParamTest(String[] s) {
+    
+        String ret = s[0];
+        for (int i=1 ; i < s.length; i++) {
+            ret += ":" + s[i];
+        }
+
+        return ret;
+    }
+
+    public String functionsParamTest(String s) {
+        return s + ":" + s.getClass().getName();
+    }
+    
+    public String functionIParamTest(Integer p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionDParamTest(Double p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionFParamTest(Float p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionLParamTest(Long p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionBParamTest(Boolean p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionCParamTest(Character p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionBParamTest(Byte p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functionCaParamTest(Character p) {
+        String ret = p.toString() + ":" + p.getClass().getName();
+        return ret;
+    }
+    
+    public String functioncomplexaParamTest(DummyObject[] ca) {
+        String ret = ca[0].toString();
+        for (int i=1 ; i < ca.length; i++) {
+            ret += ":" + ca[i].toString();
+        }
+
+        return ret;
+    }
+
+    /*
+     ***********************************************
+     * JS -> Java overload resolution plugin tests *
+     ***********************************************
+    */
+
+    /* Numeric type to the analogous Java primitive type */
+    
+    public String foo_num_to_num(int p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":int"; }
+    
+    // int -> int is lower than:
+    // int to double
+    public String foo_num_to_num(long p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":long"; }
+    // int to String
+    public String foo_num_to_num(String p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+
+    /* Null to any non-primitive type */
+    public String foo_null_to_nonprim(Integer p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":Integer"; }
+    
+    // Null to non-prim is better than:
+    // null -> prim (not allowed)
+    public String foo_null_to_nonprim(int p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":int"; }
+
+
+    /* JSObject to JSObject */
+    public String foo_jso_to_jso(JSObject p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":JSObject"; }
+
+    // JSO -> JSO is better than:
+    // JSO -> String
+    public String foo_jso_to_jso(String p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    // JSO -> Java array
+    public String foo_jso_to_jso(String[] p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    // JSO -> Superclass (Object)
+    public String foo_jso_to_jso(Object p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+
+    /* Class type to Class type where the types are equal */
+    public String foo_ct_to_ct(OverloadTestHelper2 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+    // CT -> CT is better than:
+    // CT -> Superclass
+    public String foo_ct_to_ct(OverloadTestHelper1 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    // CT->Subclass
+    public String foo_ct_to_ct(OverloadTestHelper3 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+
+
+    /* Numeric type to a different primitive type */
+    public String foo_multiprim(double p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":double"; }
+    
+    // Num -> Diff. prim. is better than:
+    // Better than anything else.. using string as a dummy
+    public String foo_multiprim(String p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+
+
+    /* String to numeric */
+    public String foo_strnum(double p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":double"; }
+    
+    // Str -> Num is better than:
+    // Anything else .. using OverloadTestHelper1 as a dummy
+    public String foo_strnum(OverloadTestHelper1 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+
+    /* Class type to superclass type (with subclass passed) */
+    public String foo_ct_to_sc(OverloadTestHelper1 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":OverloadTestHelper1"; }
+
+    // CT -> Superclass is better than CT to String
+    public String foo_ct_to_sc(String p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+    
+
+    /* Any Java value to String */
+    public String foo_jv_to_str(String p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+    // JV -> Str is better than anything else allowed
+    public String foo_jv_to_str(JSObject p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+    
+    
+    /* JSO to Array (lower cost) */
+    public String foo_jso_to_array(int[] p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":int[]"; }
+
+    // JSO to array is better than:
+    // something not possible
+    public String foo_jso_to_array(Integer p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+    
+    
+    /****** Not allowed resolutions *******/
+    
+    /* null to primitive */
+    public String foo_null_to_prim(int p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":int"; }
+
+    /* JSObject to something else */
+    public String foo_jso_to_somethingelse(OverloadTestHelper1 p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+    /* Any other conversion not described ... e.g. sending non-array to array */
+    public String foo_unsupported(Object[] p) { return (new Throwable()).getStackTrace()[0].getMethodName() + ":" + p.getClass().getName(); }
+
+    /*
+     ******************************
+     * JS -> Java type conversion *
+     ******************************
+    */
+
+    public byte byte_type = 0;
+    public char char_type = 'A';
+    public short short_type = 0;
+    public int int_type = 0;
+    public long long_type = 0L;
+    public float float_type = 0F;
+    public double double_type = 0.0;
+    public boolean boolean_type = false;
+    
+    public byte[] byte_array = null;
+    public char[] char_array = null;
+    public short[] short_array = null;
+    public int[] int_array = null;
+    public long[] long_array = null;
+    public float[] float_array = null;
+    public double[] double_array = null;
+    public char[][] char_array_array = null;
+
+    public Byte Byte_type = null;    
+    public Character Character_type = 'A';
+    public Short Short_type = 0;
+    public Integer Integer_type = 0;
+    public Long Long_type = 0L;
+    public Float Float_type = 0F;
+    public Double Double_type = 0.0;
+    public String String_type = "";
+    public Boolean Boolean_type = false;
+    public JSObject JSObject_type = null;
+
+    public Byte[] Byte_array = null;    
+    public Character[] Character_array = null;
+    public Short[] Short_array = null;
+    public Integer[] Integer_array = null;
+    public Long[] Long_array = null;
+    public Float[] Float_array = null;
+    public Double[] Double_array = null;
+    public String[] String_array = null;
+    public String[][] String_array_array = null;
+
+    public Object Object_type = null;
+
+    public String getArrayAsStr(Object array) {
+        int size = Array.getLength(array);
+        
+        String ret = "";
+        for (int i=0; i < size; i++) {
+            ret += Array.get(array, i) == null ? "null" : Array.get(array, i).toString();
+            ret += ",";
+        }
+
+        if (ret.length() > 0) {
+            ret = ret.substring(0, ret.length()-1);
+        }
+        
+        return ret;
+    }
+
+    /*
+    **************************
+    **************************
+    * Begin Java -> JS tests *
+    **************************
+    **************************
+    */
+
+    public DummyObject dummyObject = new DummyObject("DummyObject1");
+    public Object value;
+    private JSObject window;
+
+    /*
+    *************************
+    * Java -> JS read tests *
+    *************************
+    */
+
+    public boolean jjsReadIntTest() {
+        value = new Integer(window.getMember("intvar").toString());
+        return ((Integer) value).equals(1);
+    }
+
+    public boolean jjsReadDoubleTest() {
+        value = new Double(window.getMember("doublevar").toString());
+        return ((Double) value).equals(1.1);
+    }
+
+    public boolean jjsReadBooleanTest() {
+        value = new Boolean(window.getMember("boolvar").toString());
+        return ((Boolean) value).equals(true);
+    }
+
+    public boolean jjsReadStringTest() {
+        value = window.getMember("stringvar").toString();
+        return ((String) value).equals("stringvar");
+    }
+
+    public boolean jjsReadObjectTest() {
+        value = window.getMember("objectvar").toString();
+        return value.equals("DummyObject1");
+    }
+    
+    public boolean jjsRead1DArrayTest() {
+        value = ((JSObject) window.getMember("arrayvar")).getSlot(1);
+        return value.toString().equals("100");
+    }
+
+    public boolean jjsRead2DArrayTest() {
+        value = ((JSObject) ((JSObject) window.getMember("arrayvar2")).getSlot(1)).getSlot(2);
+        return value.toString().equals("200");
+    }
+
+    /*
+    **************************
+    * Java -> JS write tests *
+    **************************
+    */
+
+    public void jjsSetIntTest() {
+        window.setMember("setvar", (int) 1);
+    }
+
+    public void jjsSetIntegerTest() {
+        window.setMember("setvar", new Integer(2));
+    }
+
+    public void jjsSetdoubleTest() {
+        window.setMember("setvar", (double) 2.1);
+    }
+
+    public void jjsSetDoubleTest() {
+        window.setMember("setvar", new Double(2.2));
+    }
+
+    public void jjsSetfloatTest() {
+        window.setMember("setvar", (float) 2.3);
+    }
+
+    public void jjsSetFloatTest() {
+        window.setMember("setvar", new Float(2.4));
+    }
+
+    public void jjsSetshortTest() {
+        window.setMember("setvar", (short) 3);
+    }
+
+    public void jjsSetShortTest() {
+        window.setMember("setvar", new Short((short) 4));
+    }
+
+    public void jjsSetlongTest() {
+        window.setMember("setvar", (long) 4294967296L);
+    }
+
+    public void jjsSetLongTest() {
+        window.setMember("setvar", new Long(4294967297L));
+    }
+
+    public void jjsSetbyteTest() {
+        window.setMember("setvar", (byte) 5);
+    }
+
+    public void jjsSetByteTest() {
+        window.setMember("setvar", new Byte((byte) 6));
+    }
+
+    public void jjsSetcharTest() {
+        window.setMember("setvar", (char) '\u2323');
+    }
+
+    public void jjsSetCharacterTest() {
+        window.setMember("setvar", new Character('\u2324'));
+    }
+
+    public void jjsSetbooleanTest() {
+        window.setMember("setvar", (boolean) true);
+    }
+
+    public void jjsSetBooleanTest() {
+        window.setMember("setvar", new Boolean(false));
+    }
+
+    public void jjsSetStringTest() {
+        window.setMember("setvar", "ð ãÂ£$Ç£â¬ð");
+    }
+
+    public void jjsSetObjectTest() {
+        dummyObject = new DummyObject("DummyObject2");
+        window.setMember("setvar", dummyObject);
+    }
+    
+    public void jjsSet1DArrayTest() {
+        ((JSObject) window.getMember("setvar")).setSlot(1, 100);
+    }
+
+    public void jjsSet2DArrayTest() {
+        ((JSObject) ((JSObject) window.getMember("setvar")).getSlot(1)).setSlot(2, 200);
+    }
+
+    /*
+    ****************************************
+    * Java -> JS call parameter conversion *
+    ****************************************
+    */
+
+    public String jjsCallParamTest(String type) {
+
+        Object ret = new Object();
+        
+        int i = 1;
+        double d = 1.1;
+        float f = 1.2F;
+        long l = 4294967296L;
+        short s = 2;
+        byte b = 3;
+        char c = '\u2323';
+        boolean bl = true;
+        Integer I = 4;
+        Double D = 4.1;
+        Float F = 4.2F;
+        Long L = 4294967297L;
+        Short S = 5;
+        Byte B = 6;
+        Boolean Bl = false;
+        Character C = '\u2324';
+        String str = "ð ãÂ£$Ç£â¬ð";
+        Object o = new DummyObject("d1");
+        
+        String  callParamTestFuncName = "JJSParameterTypeCallTest";
+        
+        if (type.equals("int"))
+            ret = window.call(callParamTestFuncName, new Object[]{i});
+        else if (type.equals("double"))
+            ret = window.call(callParamTestFuncName, new Object[]{d});
+        else if (type.equals("float"))
+            ret = window.call(callParamTestFuncName, new Object[]{f});
+        else if (type.equals("long"))
+            ret = window.call(callParamTestFuncName, new Object[]{l});
+        else if (type.equals("short"))
+            ret = window.call(callParamTestFuncName, new Object[]{s});
+        else if (type.equals("byte"))
+            ret = window.call(callParamTestFuncName, new Object[]{b});
+        else if (type.equals("char"))
+            ret = window.call(callParamTestFuncName, new Object[]{c});
+        else if (type.equals("boolean"))
+            ret = window.call(callParamTestFuncName, new Object[]{bl});
+        else if (type.equals("java.lang.Integer"))
+            ret = window.call(callParamTestFuncName, new Object[]{I});
+        else if (type.equals("java.lang.Double"))
+            ret = window.call(callParamTestFuncName, new Object[]{D});
+        else if (type.equals("java.lang.Float"))
+            ret = window.call(callParamTestFuncName, new Object[]{F});
+        else if (type.equals("java.lang.Long"))
+            ret = window.call(callParamTestFuncName, new Object[]{L});
+        else if (type.equals("java.lang.Short"))
+            ret = window.call(callParamTestFuncName, new Object[]{S});
+        else if (type.equals("java.lang.Byte"))
+            ret = window.call(callParamTestFuncName, new Object[]{B});
+        else if (type.equals("java.lang.Boolean"))
+            ret = window.call(callParamTestFuncName, new Object[]{Bl});
+        else if (type.equals("java.lang.Character"))
+            ret = window.call(callParamTestFuncName, new Object[]{C});
+        else if (type.equals("java.lang.String"))
+            ret = window.call(callParamTestFuncName, new Object[]{str});
+        else if (type.equals("PluginTest.Packages.DummyObject"))
+            ret = window.call(callParamTestFuncName, new Object[]{o});
+        else
+            ret = "Unknown param type: " + type;
+
+        return ret.toString();
+    }
+    
+    /*
+    *******************************************
+    * Java -> JS invocation return type tests *
+    *******************************************
+    */
+
+    public String jjsReturnTypeTest(String type) {
+    
+        String  returnTypeTestFuncName = "JJSReturnTypeCallTest";
+        Object ret = window.call(returnTypeTestFuncName, new Object[]{type});
+
+        return ret.toString();        
+    }
+
+
+    /*
+    ***********************************
+    * Java -> JS invocation eval test *
+    ***********************************
+    */
+
+    public String jjsEvalTest(String str) {
+        return window.eval(str).toString();
+    }
+
+    public void init() {
+        window = JSObject.getWindow(this);
+        //JSObject.getWindow(this).call("appletLoaded", new Object[]{});
+    }
+
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/build
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/build	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/build	(revision 403)
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# change to dir with tests
+cd `dirname $0`
+
+JAVAC=javac
+JAR=jar
+
+if [ ! -z $JAVA_HOME ]; then
+    JAVAC=$JAVA_HOME/bin/javac
+    JAVAC=$JAVA_HOME/bin/jar
+fi
+
+$JAVAC PluginTest.java DummyObject.java OverloadTestHelper*java
+$JAR cf PluginTest.jar PluginTest.class DummyObject.class OverloadTestHelper*class
+rm -f *class
+
+echo "Done. Now launch \"firefox file://`pwd`/index.html\""
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/common.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/common.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/common.js	(revision 403)
@@ -0,0 +1,219 @@
+/*
+ * Commonly used functions
+ */
+
+        var cell, cellText; // reused
+
+        function updateTotals() {
+            document.getElementById("totals").innerHTML =  "<table class=\"results\" width=\"100%\"><tr><th>Total tests run </th><th> Passed </th><th> Failed </th><th> Errors </th></tr>" +
+                                                           "<tr><td>" + (passed+failed+errored) + " </td><td> " + passed + "  </td><td> " + failed + " </td><td> " + errored + " </td></tr>";
+        }
+
+        function pass(row) {
+            cell = document.createElement("td");
+            cell.setAttribute("style","color:green;text-align:center;font-weight: bold");
+            cellText = document.createTextNode("passed");
+            cell.appendChild(cellText);
+            row.appendChild(cell);
+
+            passed++;
+            updateTotals();
+        }
+
+        function fail(row, reason) {
+            cell = document.createElement("td");
+            cell.setAttribute("style","color:red;text-align:center;font-weight: bold");
+            if (reason)
+                cellText = document.createTextNode(reason);
+            else
+                cellText = document.createTextNode("failed");
+            cell.appendChild(cellText);
+            row.appendChild(cell);
+
+            failed++;
+            updateTotals();
+        }
+
+        function error(type, expected, e, row) {
+
+            cell = document.createElement("td");
+            cell.setAttribute("style","color:red;text-align:center;font-weight: bold");
+            cell.setAttribute("colspan","5");
+            cellText = document.createTextNode("An error occurred when running this test: " +  e);
+            cell.appendChild(cellText);
+            row.appendChild(cell);
+
+            errored++;
+            updateTotals();
+        }
+
+        function check(actual, expected, expectedtype, row) {
+           if (actual == expected) {
+                if (typeof(actual) == expectedtype) {
+                    pass(row);
+                 } else {
+                     fail(row, "Type mismatch: " + typeof(actual) + " != " + expectedtype);
+                 }
+            } else {
+                     fail(row, "Failed: " + actual + " [" + typeof(actual) + "] != " + expected + " [" + typeof(expected) + "]");
+            }
+        }
+
+        function doTest() {
+        
+            passed = 0;
+            failed = 0;
+            errored = 0;
+            document.getElementById("results").innerHTML = "";
+            updateTotals();
+       
+            try {
+                if (document.getElementById("testForm").jsjget.checked == 1)
+                    getMemberTests();
+                    
+                if (document.getElementById("testForm").jsjset.checked == 1)
+                    setMemberTests();
+
+                if (document.getElementById("testForm").jsjfp.checked == 1)
+                    fpCallTests();
+
+                if (document.getElementById("testForm").jsjfrt.checked == 1)
+                    rtCallTests();
+                    
+                if (document.getElementById("testForm").jsjfr.checked == 1)
+                    frCallTests();
+                    
+                if (document.getElementById("testForm").jsjtc.checked == 1)
+                    typeCastingTests();   
+                    
+                if (document.getElementById("testForm").jjsget.checked == 1)
+                    jjsGetMemberTests();
+                    
+                if (document.getElementById("testForm").jjsset.checked == 1)
+                    jjsSetMemberTests();
+                    
+                if (document.getElementById("testForm").jjcparam.checked == 1)
+                    jjsCallParameterTests();
+                    
+                if (document.getElementById("testForm").jjcrt.checked == 1)
+                    jjsCallReturnTypeTests();
+
+                if (document.getElementById("testForm").jjeval.checked == 1)
+                    jjsEvalTests();
+            } catch (e) {
+                document.getElementById("results").innerHTML += "<font color=\"red\">ERROR:<BR>" + e;
+            }
+        }
+        
+        function testAll() {
+            document.getElementById("testForm").jsjget.checked = 1;
+            document.getElementById("testForm").jsjset.checked = 1;
+            document.getElementById("testForm").jsjfp.checked = 1;
+            document.getElementById("testForm").jsjfrt.checked = 1;
+            document.getElementById("testForm").jsjfr.checked = 1;
+            document.getElementById("testForm").jsjtc.checked = 1;
+            document.getElementById("testForm").jjsget.checked = 1;
+            document.getElementById("testForm").jjsset.checked = 1;
+            document.getElementById("testForm").jjcparam.checked = 1;
+            document.getElementById("testForm").jjcrt.checked = 1;
+            document.getElementById("testForm").jjeval.checked = 1;
+
+            doTest();
+        }
+
+
+var intvar;
+var doublevar;
+var boolvar;
+var stringvar;
+var objectvar;
+var arrayvar;
+var arrayvar2;
+var setvar;
+
+function initVars() {
+    intvar = 1;
+    doublevar = 1.1;
+    boolvar = true;
+    stringvar = "stringvar";
+    objectvar = new PluginTest.Packages.DummyObject("DummyObject1");
+    arrayvar = new Array();
+    arrayvar[1] = 100;
+
+    arrayvar2 = new Array();
+    arrayvar2[1] = new Array();
+    arrayvar2[1][2] = 200;
+}
+
+function createResultTable(tbl, tblBody, columnNames) {
+    tbl.setAttribute("border", "5");
+    tbl.setAttribute("width", "100%");
+    tbl.setAttribute("class", "results");
+    row = document.createElement("tr");
+
+    for (var i=0; i < columnNames.length; i++) {
+        cell = document.createElement("th");
+        cellText = document.createTextNode(columnNames[i]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+    }
+
+    tblBody.appendChild(row);
+    tbl.appendChild(tblBody);
+    document.getElementById("results").appendChild(tbl);
+}
+
+function addResult() {
+
+    var row = arguments[arguments.length-1];
+
+    // Different length arguments imply different width distributions
+
+    if (arguments.length == 4) {
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","25%");
+        cellText = document.createTextNode(arguments[0]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","20%");
+        cellText = document.createTextNode(arguments[1]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","40%");
+        cellText = document.createTextNode(arguments[2]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+    }  else if (arguments.length == 5) {
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","25%");
+        cellText = document.createTextNode(arguments[0]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","20%");
+        cellText = document.createTextNode(arguments[1]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","20%");
+        cellText = document.createTextNode(arguments[2]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+        cell = document.createElement("td");
+        cell.setAttribute("width","20%");
+        cellText = document.createTextNode(arguments[3]);
+        cell.appendChild(cellText);
+        row.appendChild(cell);
+
+    }
+}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/index.html
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/index.html	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/index.html	(revision 403)
@@ -0,0 +1,91 @@
+<HTML>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<HEAD>
+
+    <style type="text/css">
+        table.results {
+            background-color: white;
+            border-collapse: collapse;
+            border-color: black black black black;
+            border-spacing: 0px;
+            border-style: outset outset outset outset;
+            border-width: 0px 0px 0px 0px;
+        }
+
+        table.results th {
+            background-color: white;
+            border-style: inset inset inset inset;
+            border-color: gray gray gray gray;
+            border-width: 1px 1px 1px 1px;
+            padding: 1px 1px 1px 1px;
+        }
+
+        table.results td {
+            background-color: white;
+            border-color: gray gray gray gray;
+            border-style: inset inset inset inset;
+            border-width: 1px 1px 1px 1px;
+            padding: 2px 2px 2px 2px;
+        }
+
+    </style>
+
+    <!-- Load all tests scripts -->
+    <script language="JavaScript" src="common.js"></script>
+    <script language="JavaScript" src="jsj_get_tests.js"></script>
+    <script language="JavaScript" src="jsj_set_tests.js"></script>
+    <script language="JavaScript" src="jsj_func_rettype_tests.js"></script>
+    <script language="JavaScript" src="jsj_func_parameters_tests.js"></script>
+    <script language="JavaScript" src="jsj_func_overload_tests.js"></script>
+    <script language="JavaScript" src="jsj_type_conversion_tests.js"></script>    
+    <script language="JavaScript" src="jjs_tests.js"></script>
+    <script language="JavaScript" src="jjs_get_tests.js"></script>
+    <script language="JavaScript" src="jjs_set_tests.js"></script>
+    <script language="JavaScript" src="jjs_func_rettype_tests.js"></script>
+    <script language="JavaScript" src="jjs_func_parameters_tests.js"></script>
+    <script language="JavaScript" src="jjs_eval_test.js"></script>
+
+</HEAD>
+
+<BODY>
+
+<!-- Test selection/launch input -->
+<form id="testForm">
+    <table STYLE="width:100%; float:static">
+        <tr>
+            <td>
+                <input type=checkbox name="jsjget"><tt>JS -> Java read tests</tt><BR>
+                <input type=checkbox name="jsjset"><tt>JS -> Java set tests</tt><BR>
+                <input type=checkbox name="jsjfp"><tt>JS -> Java function parameter conversion tests</tt><BR>
+                <input type=checkbox name="jsjfrt"><tt>JS -> Java function return type tests</tt><BR>
+                <input type=checkbox name="jsjfr"><tt>JS -> Java function resolution tests</tt><BR>
+            </td>
+            <td>
+                <input type=checkbox name="jsjtc"><tt>JS -> Java type conversion tests</tt><BR>
+                <input type=checkbox name="jjsget"><tt>Java -> JS read tests</tt><BR>
+                <input type=checkbox name="jjsset"><tt>Java -> JS set tests</tt><BR>
+                <input type=checkbox name="jjcparam"><tt>Java -> JS function parameter conversion tests</tt><BR>
+                <input type=checkbox name="jjcrt"><tt>Java -> JS function return type tests</tt><BR>
+                <input type=checkbox name="jjeval"><tt>Java -> JS eval test</tt><BR>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <input type=button id="run_selected" value="Run selected tests" onclick="doTest();">
+                <input type=button id= "run_all" value="Run all tests" onclick="testAll();">
+            </td>
+        </tr>
+    </table>
+</form>
+
+<!-- Results -->
+<DIV ID="RESULTS">
+    <DIV ID="totals" STYLE="width:100%; float:static"></DIV>
+    <DIV ID="results" STYLE="width:100%; float:static"></DIV>
+</DIV>
+
+<APPLET CODE="PluginTest.class" ARCHIVE="PluginTest.jar" NAME="PluginTest" WIDTH="0" HEIGHT=0 MAYSCRIPT></APPLET><BR>
+
+</BODY>
+</HTML>
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_eval_test.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_eval_test.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_eval_test.js	(revision 403)
@@ -0,0 +1,57 @@
+/******************************************************
+ * Tests for parameter conversion between Java and JS *
+ ******************************************************/
+
+
+function jjsEvalTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>Java -> JS Eval Test:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Evaluating";
+    columnNames[1] = "Expected result";
+    columnNames[2] = "Result";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        evalstr = "document.location";
+        expectedvalue = eval(evalstr);
+        actualValue = PluginTest.jjsEvalTest(evalstr);
+        addResult(evalstr, expectedvalue, actualValue, row);
+        check(actualValue, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        evalstr = "1+1";
+        expectedvalue = eval(evalstr);
+        actualValue = PluginTest.jjsEvalTest(evalstr);
+        addResult(evalstr, expectedvalue, actualValue, row);
+        check(actualValue, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        evalstr = "typeof(true)";
+        expectedvalue = eval(evalstr);
+        actualValue = PluginTest.jjsEvalTest(evalstr);
+        addResult(evalstr, expectedvalue, actualValue, row);
+        check(actualValue, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_parameters_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_parameters_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_parameters_tests.js	(revision 403)
@@ -0,0 +1,107 @@
+/******************************************************
+ * Tests for parameter conversion between Java and JS *
+ ******************************************************/
+
+function JJSParameterTypeCallTest(type_parameter) {
+    return type_parameter + ":" + typeof(type_parameter);
+}
+
+function runSingleJjsCallParameterTest(type, control_arg, row) {
+    try {
+        expectedvalue = JJSParameterTypeCallTest(control_arg);
+        actualvalue = PluginTest.jjsCallParamTest(type);
+        addResult(type, expectedvalue, actualvalue, row);
+        check(actualvalue, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+}
+
+function jjsCallParameterTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>Java -> JS Call tests (Parameter Type):</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Parameter Type (Java side)";
+    columnNames[1] = "Expecting Java to receive";
+    columnNames[2] = "Java Received";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("int", 1, row);
+    tblBody.appendChild(row);
+
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("double", 1.1, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("float", 1.2000000476837158, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("long", 4294967296, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("short", 2, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("byte", 3, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("char", 8995, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("boolean", true, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Integer", 4, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Double", 4.1, row);
+    tblBody.appendChild(row);
+
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Float", 4.199999809265137, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Long", 4294967297, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Short", 5, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Byte", 6, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Boolean", false, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.Character", 8996, row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("java.lang.String", "ð ãÂ£$Ç£â¬ð", row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJjsCallParameterTest("PluginTest.Packages.DummyObject", (new PluginTest.Packages.DummyObject("d1")), row);
+    tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_rettype_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_rettype_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_func_rettype_tests.js	(revision 403)
@@ -0,0 +1,61 @@
+/******************************************************
+ * Tests for parameter conversion between Java and JS *
+ ******************************************************/
+
+function JJSReturnTypeCallTest(type) {
+
+    if (type == "Number")
+        return 1;
+
+    if (type == "Boolean")        
+        return false;
+
+    if (type == "String")
+        return "ð ãÂ£$Ç£â¬ð";
+
+    if (type == "Object")
+        return window;
+}
+
+function runSingleJJSReturnTypeTest(type, row) {
+    try {
+        expectedvalue = JJSReturnTypeCallTest(type);
+        actualvalue = PluginTest.jjsReturnTypeTest(type);
+        addResult(type, expectedvalue, actualvalue, row);
+        check(actualvalue, expectedvalue + "", "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+}
+
+function jjsCallReturnTypeTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>Java -> JS Call tests (Return Type):</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Parameter Type (Java side)";
+    columnNames[1] = "Expected return value";
+    columnNames[2] = "Actual return value";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    row = document.createElement("tr");
+    runSingleJJSReturnTypeTest("Number", row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJJSReturnTypeTest("Boolean", row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJJSReturnTypeTest("String", row);
+    tblBody.appendChild(row);
+    
+    row = document.createElement("tr");
+    runSingleJJSReturnTypeTest("Object", row);
+    tblBody.appendChild(row);
+}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_get_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_get_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_get_tests.js	(revision 403)
@@ -0,0 +1,114 @@
+/*****************************************
+ * Tests for reading JS values from Java *
+ *****************************************/
+
+function jjsGetMemberTests() {
+
+    initVars();
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java get tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Member Type";
+    columnNames[1] = "Expected Value";
+    columnNames[2] = "Actual value";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        type = "int";
+        expectedvalue = intvar;
+        tpassed = PluginTest.jjsReadIntTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "double";
+        expectedvalue = doublevar;
+        tpassed = PluginTest.jjsReadDoubleTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "boolean";
+        expectedvalue = boolvar;
+        tpassed = PluginTest.jjsReadBooleanTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "string";
+        expectedvalue = stringvar;
+        tpassed = PluginTest.jjsReadStringTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "object";
+        expectedvalue = objectvar;
+        tpassed = PluginTest.jjsReadObjectTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "1D Array";
+        expectedvalue = 100;
+        tpassed = PluginTest.jjsRead1DArrayTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "2D Array";
+        expectedvalue = 200;
+        tpassed = PluginTest.jjsRead2DArrayTest();
+        actualValue = PluginTest.value;
+        addResult(type, expectedvalue, PluginTest.value, row);
+        check(tpassed, true, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); return;
+
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_set_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_set_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jjs_set_tests.js	(revision 403)
@@ -0,0 +1,314 @@
+/*****************************************
+ * Tests for setting JS values from Java *
+ *****************************************/
+
+function jjsSetMemberTests() {
+
+    initVars();
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java set tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Java Member Type";
+    columnNames[1] = "Old Value";
+    columnNames[2] = "Expected value";
+    columnNames[3] = "Actual Value";
+    columnNames[4] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        type = "int";
+        oldvalue = setvar;
+        PluginTest.jjsSetIntTest();
+        expectedvalue = 1;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Integer";
+        oldvalue = setvar;
+        PluginTest.jjsSetIntegerTest();
+        expectedvalue = 2;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "double";
+        oldvalue = setvar;
+        PluginTest.jjsSetdoubleTest();
+        expectedvalue = 2.1;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Double";
+        oldvalue = setvar;
+        PluginTest.jjsSetDoubleTest();
+        expectedvalue = 2.2;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "float";
+        oldvalue = setvar;
+        PluginTest.jjsSetfloatTest();
+        expectedvalue = 2.299999952316284 ;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Float";
+        oldvalue = setvar;
+        PluginTest.jjsSetFloatTest();
+        expectedvalue = 2.4000000953674316;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "long";
+        oldvalue = setvar;
+        PluginTest.jjsSetlongTest();
+        expectedvalue = 4294967296;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Long";
+        oldvalue = setvar;
+        PluginTest.jjsSetLongTest();
+        expectedvalue = 4294967297;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "short";
+        oldvalue = setvar;
+        PluginTest.jjsSetshortTest();
+        expectedvalue = 3;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Short";
+        oldvalue = setvar;
+        PluginTest.jjsSetShortTest();
+        expectedvalue = 4;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "byte";
+        oldvalue = setvar;
+        PluginTest.jjsSetbyteTest();
+        expectedvalue = 5;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Byte";
+        oldvalue = setvar;
+        PluginTest.jjsSetByteTest();
+        expectedvalue = 6;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "char";
+        oldvalue = setvar;
+        PluginTest.jjsSetcharTest();
+        expectedvalue = 8995;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Character";
+        oldvalue = setvar;
+        PluginTest.jjsSetCharacterTest();
+        expectedvalue = 8996;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "boolean";
+        oldvalue = setvar;
+        PluginTest.jjsSetbooleanTest();
+        expectedvalue = true;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row); 
+    
+    
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.Boolean";
+        oldvalue = setvar;
+        PluginTest.jjsSetBooleanTest();
+        expectedvalue = false;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "boolean", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "java.lang.String";
+        oldvalue = setvar;
+        PluginTest.jjsSetStringTest();
+        expectedvalue = "ð ãÂ£$Ç£â¬ð";
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "(Complex java object)";
+        oldvalue = setvar;
+        PluginTest.jjsSetObjectTest();
+        expectedvalue = PluginTest.dummyObject;
+        addResult(type, oldvalue, expectedvalue, setvar, row);
+        check(setvar, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "1D Array";
+	setvar = new Array();
+        oldvalue = setvar[1];
+        PluginTest.jjsSet1DArrayTest();
+        expectedvalue = 100;
+        addResult(type, oldvalue, expectedvalue, setvar[1], row);
+        check(setvar[1], expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "2D Array";
+	setvar = new Array();
+	setvar[1] = new Array();
+        oldvalue = setvar[1][2];
+        PluginTest.jjsSet2DArrayTest();
+        expectedvalue = 200;
+        addResult(type, oldvalue, expectedvalue, setvar[1][2], row);
+        check(setvar[1][2], expectedvalue, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+}
+
+function java_to_js_call_test_info (type, expectedreply, functionreply, row) {
+
+    cell = document.createElement("td");
+    cell.setAttribute("width","25%");
+    cellText = document.createTextNode(type);
+    cell.appendChild(cellText);
+    row.appendChild(cell);
+
+    cell = document.createElement("td");
+    cell.setAttribute("width","20%");
+    cellText = document.createTextNode(expectedreply);
+    cell.appendChild(cellText);
+    row.appendChild(cell);
+    
+    cell = document.createElement("td");
+    cell.setAttribute("width","20%");
+    cellText = document.createTextNode(functionreply);
+    cell.appendChild(cellText);
+    row.appendChild(cell);
+
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_overload_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_overload_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_overload_tests.js	(revision 403)
@@ -0,0 +1,181 @@
+ /**************************************************************
+  * Tests for overloaded function resolution when calling Java *
+   * functions from JS                                         *
+  **************************************************************/
+
+function frCallTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java Call tests [Overload and casting]:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Available functions";
+    columnNames[1] = "Expected reply";
+    columnNames[2] = "Reply";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        fname = "foo_null_to_nonprim";
+        available = fname + " [(Integer), (int)]";
+        expectedreply = fname + ":Integer";
+        reply = PluginTest.foo_null_to_nonprim(null);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":Integer", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_jso_to_jso";
+        available = fname + " [(JSObject), (String), (String[]), (Object)]";
+        expectedreply = fname + ":JSObject";
+        reply = PluginTest.foo_jso_to_jso(window);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":JSObject", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_ct_to_ct";
+        available = fname + " [(OverloadTestHelper1), (OverloadTestHelper2), (OverloadTestHelper3)]";
+        expectedreply = fname + ":OverloadTestHelper2";
+        reply = PluginTest.foo_ct_to_ct(new PluginTest.Packages.OverloadTestHelper2());
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":OverloadTestHelper2", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_multiprim";
+        available = fname + " [(double), (String)]";
+        expectedreply = fname + ":double";
+        reply = PluginTest.foo_multiprim(1.1);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":double", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_multiprim";
+        available = fname + " [(double), (String)]";
+        expectedreply = fname + ":double";
+        reply = PluginTest.foo_multiprim(1.1);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":double", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_strnum";
+        available = fname + " [(double), (OverloadTestHelper1)]";
+        expectedreply = fname + ":double";
+        reply = PluginTest.foo_strnum(1.1);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":double", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_ct_to_sc";
+        available = fname + " [(OverloadTestHelper1), (String)]";
+        expectedreply = fname + ":double";
+        reply = PluginTest.foo_ct_to_sc(new PluginTest.Packages.OverloadTestHelper2());
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":OverloadTestHelper1", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_jv_to_str";
+        available = fname + " [(String), (JSObject)]";
+        expectedreply = fname + ":String";
+        reply = PluginTest.foo_jv_to_str(new PluginTest.Packages.OverloadTestHelper1());
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":java.lang.String", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        fname = "foo_jso_to_array";
+        available = fname + " [(int[]), (Integer), (Integer[])]";
+        expectedreply = fname + ":int[]";
+        arr = new Array();
+        arr[0] = 10;
+        reply = PluginTest.foo_jso_to_array(arr);
+        addResult(available, expectedreply, reply, row);
+        check(fname + ":int[]", reply, "string", row);
+    } catch (e) {
+        error(null, null, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    // Tests where exceptions are expected
+    fname = "foo_null_to_prim";
+    available = fname + " [(int)] -- Not allowed";
+    
+    try {
+        row = document.createElement("tr");
+        expectedreply = null;
+        reply = PluginTest.foo_null_to_prim(null);
+        fail(row, "An exception was expected. Instead, got reply: " + reply);
+    } catch (e) {
+        addResult(available, "[An exception]", e.toString(), row);
+        pass(row);
+    }
+    tblBody.appendChild(row);
+    fname = "foo_jso_to_somethingelse";
+    available = fname + " [(OverloadTestHelper1)] -- Not allowed";
+    
+    try {
+        row = document.createElement("tr");
+        expectedreply = null;
+        reply = PluginTest.foo_jso_to_somethingelse(window);
+        fail(row, "An exception was expected. Instead, got reply: " + reply);
+    } catch (e) {
+        addResult(available, "[An exception]", e.toString(), row);
+        pass(row);
+    }
+    tblBody.appendChild(row);
+    fname = "foo_unsupported";
+    available = fname + " [(Object[] p)] -- Not allowed";
+    try {
+      row = document.createElement("tr");
+      expectedreply = null;
+      reply = PluginTest.foo_unsupported(25);
+       fail(row, "An exception was expected. Instead, got reply: " + reply);
+    } catch (e) {
+       addResult(available, "[An exception]", e.toString(), row);
+       pass(row);
+    }
+
+    tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_parameters_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_parameters_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_parameters_tests.js	(revision 403)
@@ -0,0 +1,216 @@
+ /********************************************************************
+  * Tests for function parameter coversion when calling Java from JS *
+  ********************************************************************/
+
+function fpCallTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java Call tests [Parameter type]:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Parameter type";
+    columnNames[1] = "Sending";
+    columnNames[2] = "Expected reply";
+    columnNames[3] = "Reply";
+    columnNames[4] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    PluginTest.setUpForReturnTests();
+
+     try {
+         row = document.createElement("tr");
+         type = "int";
+         send = 1;
+         reply = PluginTest.functioniParamTest(send);
+         addResult(type, send, send, reply, row);
+         check(send, reply, "number", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "double";
+         send = 1.1;
+         reply = PluginTest.functiondParamTest(send);
+         addResult(type, send, send, reply, row);
+         check(send, reply, "number", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+    try {
+         row = document.createElement("tr");
+         type = "float";
+         send = 1.11;
+         reply = PluginTest.functionfParamTest(send);
+         addResult(type, send, send, reply, row);
+         check(send, reply, "number", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "long";
+         send = 4294967300;
+         reply = PluginTest.functionlParamTest(send);
+         addResult(type, send, send, reply, row);
+         check(send, reply, "number", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+
+     try {
+         row = document.createElement("tr");
+         type = "boolean";
+         send = true;
+         reply = PluginTest.functionbParamTest(send);
+         addResult(type, send, send, reply, row);
+         check("true", reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "char";
+         send = 75;
+         reply = PluginTest.functioncParamTest(send);
+         addResult(type, send, "K", reply, row);
+         check("K", reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+
+     try {
+         row = document.createElement("tr");
+         type = "byte";
+         send = 76;
+         reply = PluginTest.functionbyParamTest(send);
+         addResult(type, send, send, reply, row);
+         check(send, reply, "number", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);       
+     
+     try {
+         row = document.createElement("tr");
+         type = "char[] (simple primitive)";
+         arr = new Array();
+         arr[0] = 80;
+         arr[1] = 81;
+         reply = PluginTest.functioncaParamTest(arr);
+         addResult(type, "[80,81]", "P:Q", reply, row);
+         check(reply, "P:Q", "string", row);
+     } catch (e) {
+         error(type, "P:Q", e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "String";
+         send = "$ãÂ£â¬ðð Ç£";
+         expectedreply = "$ãÂ£â¬ðð Ç£:java.lang.String";
+         reply = PluginTest.functionsParamTest(send);
+         addResult(type, send, expectedreply, reply, row);
+         check(expectedreply, reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "Integer";
+         send = "32";
+         expectedreply = send+":java.lang.Integer";
+         reply = PluginTest.functionIParamTest(send);
+         addResult(type, send, expectedreply, reply, row);
+         check(expectedreply, reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "Double";
+         send = 32.0;
+         expectedreply = "32.0:java.lang.Double";
+         reply = PluginTest.functionDParamTest(send);
+         addResult(type, send, expectedreply, reply, row);
+         check(expectedreply, reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);             
+     
+     try {
+         row = document.createElement("tr");
+         type = "Float";
+         send = 32.01;
+         expectedreply = send+":java.lang.Float";
+         reply = PluginTest.functionFParamTest(send);
+         addResult(type, send, expectedreply, reply, row);
+         check(expectedreply, reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);
+
+     try {
+         row = document.createElement("tr");
+         type = "Long";
+         send = 4294967301;
+         expectedreply = send+":java.lang.Long";
+         reply = PluginTest.functionLParamTest(send);
+         addResult(type, send, expectedreply, reply, row);
+         check(expectedreply, reply, "string", row);
+     } catch (e) {
+         error(type, send, e, row);
+     }
+     tblBody.appendChild(row);   
+     
+     
+     try {
+         row = document.createElement("tr");
+         type = "String/Int [] (mixed)";
+         arr = new Array();
+         arr[0] = "s1";
+         arr[1] = 42;
+         reply = PluginTest.functionsiaParamTest(arr);
+         addResult(type, "[s1,42]", "s1:42", reply, row);
+         check(reply, "s1:42", "string", row);
+     } catch (e) {
+         error(type, "s1:42", e, row);
+     }
+     tblBody.appendChild(row);
+     
+     try {
+         row = document.createElement("tr");
+         type = "DummyObject[] (complex)";
+         arr = new Array();
+         arr[0] = new PluginTest.Packages.DummyObject("DummyObject1");
+         arr[1] = new PluginTest.Packages.DummyObject("DummyObject2");
+         reply = PluginTest.functioncomplexaParamTest(arr);
+         addResult(type, "[DummyObject1,DummyObjec2]", "DummyObject1:DummyObject2", reply, row);
+         check(reply, "DummyObject1:DummyObject2", "string", row);
+     } catch (e) {
+         error(type, "DummyObject1:DummyObject2", e, row);
+     }
+
+     tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_rettype_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_rettype_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_func_rettype_tests.js	(revision 403)
@@ -0,0 +1,262 @@
+/***********************************************************************
+ * Tests to process various return types from Java side function calls *
+ ***********************************************************************/
+
+function rtCallTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java Call tests [Return Type]:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Function return type";
+    columnNames[1] = "Expected Value";
+    columnNames[2] = "Actual Value";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    PluginTest.setUpForParameterTests();
+
+    try {
+        row = document.createElement("tr");
+        type = "int";
+        expectedvalue = 41;
+        addResult(type, expectedvalue, PluginTest.intReturnTest(), row);
+        check(PluginTest.intReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "double";
+        expectedvalue = 41.41;
+        addResult(type, expectedvalue, PluginTest.doubleReturnTest(), row);
+        check(PluginTest.doubleReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "float";
+        expectedvalue = 41.4109992980957;
+        addResult(type, expectedvalue, PluginTest.floatReturnTest(), row);
+        check(PluginTest.floatReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "long";
+        expectedvalue = 4294967297;
+        addResult(type, expectedvalue, PluginTest.longReturnTest(), row);
+        check(PluginTest.longReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "boolean";
+        expectedvalue = true;
+        addResult(type, expectedvalue, PluginTest.booleanReturnTest(), row);
+        check(PluginTest.booleanReturnTest(), expectedvalue, "boolean", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "char";
+        expectedvalue = 9001;
+        addResult(type, expectedvalue, PluginTest.charReturnTest(), row);
+        check(PluginTest.charReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "byte";
+        expectedvalue = 44;
+        addResult(type, expectedvalue, PluginTest.byteReturnTest(), row);
+        check(PluginTest.byteReturnTest(), expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "char[] (direct element access)";
+        expectedvalue = 9234;
+        addResult(type, expectedvalue, PluginTest.charArrayReturnTest()[2], row);
+        check(PluginTest.charArrayReturnTest()[2], expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Regular char string";
+        expectedvalue = "I'm a string too!";
+        addResult(type, expectedvalue, PluginTest.regularStringReturnTest(), row);
+        check(PluginTest.regularStringReturnTest(), expectedvalue, "string", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Special char string";
+        expectedvalue = "ð ãÂ£$Ç£â¬ð";
+        addResult(type, expectedvalue, PluginTest.specialStringReturnTest(), row);
+        check(PluginTest.specialStringReturnTest(), expectedvalue, "string", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "void";
+        expectedvalue = null;
+        addResult(type, "undefined", PluginTest.voidReturnTest(), row);
+        check(PluginTest.voidReturnTest(), expectedvalue, "undefined", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "null";
+        expectedvalue = null;
+        addResult(type, expectedvalue, PluginTest.nullReturnTest(), row);
+        check(PluginTest.nullReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Integer";
+        expectedvalue = 14;
+        addResult(type, expectedvalue, PluginTest.IntegerReturnTest(), row);
+        check(PluginTest.IntegerReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Double";
+        expectedvalue = 14.14;
+        addResult(type, expectedvalue, PluginTest.DoubleReturnTest(), row);
+        check(PluginTest.DoubleReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Float";
+        expectedvalue = 14.114;
+        addResult(type, expectedvalue, PluginTest.FloatReturnTest(), row);
+        check(PluginTest.FloatReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Long";
+        expectedvalue = 6927694925;
+        addResult(type, expectedvalue, PluginTest.LongReturnTest(), row);
+        check(PluginTest.LongReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean";
+        expectedvalue = "false";
+        addResult(type, expectedvalue, PluginTest.BooleanReturnTest(), row);
+        check(PluginTest.BooleanReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Character";
+        expectedvalue = "â";
+        addResult(type, expectedvalue, PluginTest.CharacterReturnTest(), row);
+        check(PluginTest.CharacterReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Byte";
+        expectedvalue = 46;
+        addResult(type, expectedvalue, PluginTest.ByteReturnTest(), row);
+        check(PluginTest.ByteReturnTest(), expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Character[] (direct element access)";
+        expectedvalue = "â";
+        addResult(type, expectedvalue, PluginTest.CharacterArrayReturnTest()[1], row);
+        check(PluginTest.CharacterArrayReturnTest()[1], expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Character[] (Full array)";
+        expectedvalue = "[Ljava.lang.Character;@";
+        addResult(type, expectedvalue+"*", PluginTest.CharacterArrayReturnTest(), row);
+        if (PluginTest.CharacterArrayReturnTest().toString().substr(0,23)  == "[Ljava.lang.Character;@")
+            if (typeof(PluginTest.CharacterArrayReturnTest()) == "object") {
+                pass(row);
+            } else {
+                fail(row, "Type mismatch: " + typeof(SMPluginTest.Da) + " != object");
+            }
+        else
+            fail(row, "");                
+
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+
+    tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_get_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_get_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_get_tests.js	(revision 403)
@@ -0,0 +1,260 @@
+/********************************************
+ * Tests for getting members from Java side *
+ ********************************************/
+
+function getMemberTests() {
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java get tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Member Type";
+    columnNames[1] = "Expected Value";
+    columnNames[2] = "Actual Value";
+    columnNames[3] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    PluginTest.setUpForGMTests();
+
+    try {
+        row = document.createElement("tr");
+        type = "int";
+        expectedvalue = 42;
+        addResult(type, expectedvalue, PluginTest.i, row);
+        check(PluginTest.i, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "double";
+        expectedvalue = 42.42;
+        addResult(type, expectedvalue, PluginTest.d, row);
+        check(PluginTest.d, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "float";
+        expectedvalue = 42.099998474121094;
+        addResult(type, expectedvalue, PluginTest.f, row);
+        check(PluginTest.f, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "long";
+        expectedvalue = 4294967296;
+        addResult(type, expectedvalue, PluginTest.l, row);
+        check(PluginTest.l, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "boolean";
+        expectedvalue = true;
+        addResult(type, expectedvalue, PluginTest.b, row);
+        check(PluginTest.b, expectedvalue, "boolean", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "char";
+        expectedvalue = 8995;
+        addResult(type, expectedvalue, PluginTest.c, row);
+        check(PluginTest.c, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "byte";
+        expectedvalue = 43;
+        addResult(type, expectedvalue, PluginTest.by, row);
+        check(PluginTest.by, expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "int[] (element access)";
+        expectedvalue = "1024";
+        addResult(type, expectedvalue, PluginTest.ia[4], row);
+        check(PluginTest.ia[4], expectedvalue, "number", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "int[] (beyond length)";
+        expectedvalue = null;
+        addResult(type, expectedvalue, PluginTest.ia[30], row);
+        check(PluginTest.ia[30], expectedvalue, "undefined", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Regular String";
+        expectedvalue = "I'm a string!";
+        addResult(type, expectedvalue, PluginTest.rs, row);
+        check(PluginTest.rs, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String with special characters";
+        expectedvalue = "ð ãÂ£$Ç£â¬ð";
+        addResult(type, expectedvalue, PluginTest.ss, row);
+        check(PluginTest.ss, expectedvalue, "string", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "null";
+        expectedvalue = null;
+        addResult(type, expectedvalue, PluginTest.n, row);
+        check(PluginTest.n, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Integer";
+        expectedvalue = 24;
+        addResult(type, expectedvalue, PluginTest.I, row);
+        check(PluginTest.I, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Double";
+        expectedvalue = 24.24;
+        addResult(type, expectedvalue, PluginTest.D, row);
+        check(PluginTest.D, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Float";
+        expectedvalue = 24.124;
+        addResult(type, expectedvalue, PluginTest.F, row);
+        check(PluginTest.F, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Long";
+        expectedvalue = 6927694924;
+        addResult(type, expectedvalue, PluginTest.L, row);
+        check(PluginTest.L, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean";
+        expectedvalue = "false";
+        addResult(type, expectedvalue, PluginTest.B, row);
+        check(PluginTest.B, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Character";
+        expectedvalue = 'áŠ';
+        addResult(type, expectedvalue, PluginTest.C, row);
+        check(PluginTest.C, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Byte";
+        expectedvalue = 34;
+        addResult(type, expectedvalue, PluginTest.By, row);
+        check(PluginTest.By, expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Double[] (element access)";
+        expectedvalue = "24.24";
+        addResult(type, expectedvalue, PluginTest.Da1[9], row);
+        check(PluginTest.Da1[9], expectedvalue, "object", row);
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Double[] (Full array)";
+        expectedvalue = "[Ljava.lang.Double;@";
+        addResult(type, expectedvalue+"*", PluginTest.Da1, row);
+        
+        if (PluginTest.Da1.toString().substr(0,20)  == expectedvalue)
+            if (typeof(PluginTest.Da1) == "object") {
+                pass(row);
+            } else {
+                fail(row, "Type mismatch: " + typeof(PluginTest.Da1) + " != object");
+            }
+        else
+            fail(row, "");
+    } catch (e) {
+        error(type, expectedvalue, e, row);
+    }
+
+    tblBody.appendChild(row);
+}
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_set_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_set_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_set_tests.js	(revision 403)
@@ -0,0 +1,318 @@
+/******************************************
+ * Tests for setting members on Java side *
+ ******************************************/
+
+function setMemberTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java set tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Member Type";
+    columnNames[1] = "Old Value";
+    columnNames[2] = "Setting To";
+    columnNames[3] = "New Value";
+    columnNames[4] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    PluginTest.setUpForSMTests();
+
+    try {
+        row = document.createElement("tr");
+        type = "int";
+        setto = 42;
+        curr = PluginTest.i;
+        PluginTest.i = setto;
+        now = PluginTest.i;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "double";
+        setto = 42.42;
+        curr = PluginTest.d;
+        PluginTest.d = setto;
+        now = PluginTest.d;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "float";
+        setto = 42.421;
+        curr = PluginTest.f;
+        PluginTest.f = setto;
+        now = PluginTest.f;
+        addResult(type, curr, 42.42100143432617, now, row);
+        check(now, 42.42100143432617, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "long";
+        setto = 4294967296;
+        curr = PluginTest.l;
+        PluginTest.l = setto;
+        now = PluginTest.l;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "boolean";
+        setto = true;
+        curr = PluginTest.b;
+        PluginTest.b = setto;
+        now = PluginTest.b;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "char";
+        setto = 58;
+        curr = PluginTest.c;
+        PluginTest.c = setto;
+        now = PluginTest.c;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "byte";
+        setto = 43;
+        curr = PluginTest.by;
+        PluginTest.by = setto;
+        now = PluginTest.by;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "int[] (element)";
+        setto = 100;
+        curr = PluginTest.ia[4];
+        PluginTest.ia[4] = setto;
+        now = PluginTest.ia[4];
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "int[] (beyond length)";
+        setto = 100;
+        curr = PluginTest.ia[30];
+        PluginTest.ia[30] = setto;
+        now = PluginTest.ia[30];
+        addResult(type, curr, setto, now, row);
+        check(now, null, "undefined", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Regular string";
+        setto = 'Test string';
+        curr = PluginTest.rs;
+        PluginTest.rs = setto;
+        now = PluginTest.rs;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String with special chars";
+        setto = "ð ãÂ£$Ç£â¬ð";
+        curr = PluginTest.ss;
+        PluginTest.ss = setto;
+        now = PluginTest.ss;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "null";
+        setto = null;
+        curr = PluginTest.n;
+        PluginTest.n = setto;
+        now = PluginTest.n;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Integer";
+        setto = 24;
+        curr = PluginTest.I;
+        PluginTest.I = setto;
+        now = PluginTest.I;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Double";
+        setto = 24.24;
+        curr = PluginTest.D;
+        PluginTest.D = setto;
+        now = PluginTest.D;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Float";
+        setto = 24.124;
+        curr = PluginTest.F;
+        PluginTest.F = setto;
+        now = PluginTest.F;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Long";
+        setto = 6927694924;
+        curr = PluginTest.L;
+        PluginTest.L = setto;
+        now = PluginTest.L;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean";
+        setto = new java.lang.Boolean("true");
+        curr = PluginTest.B;
+        PluginTest.B = setto;
+        now = PluginTest.B;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Character";
+        setto = new java.lang.Character(64);
+        curr = PluginTest.C;
+        PluginTest.C = setto;
+        now = PluginTest.C;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Byte";
+        setto = new java.lang.Byte(39);
+        curr = PluginTest.By;
+        PluginTest.By = setto;
+        now = PluginTest.By;
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Double[] (element)";
+        setto = 100.100;
+        curr = PluginTest.Da1[9];
+        PluginTest.Da1[9] = setto;
+        now = PluginTest.Da1[9];
+        addResult(type, curr, setto, now, row);
+        check(now, setto, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Double[] (Full array)";
+        curr = PluginTest.Da2;
+        PluginTest.Da2 = java.lang.reflect.Array.newInstance(java.lang.Double, 3);
+        PluginTest.Da2[0] = 1.1;
+        PluginTest.Da2[1] = 2.1;
+        addResult(type, curr, "[1.1,2.1,null]", "["+PluginTest.Da2[0]+","+PluginTest.Da2[1]+","+PluginTest.Da2[2]+"]", row);
+        check("["+PluginTest.Da2[0]+","+PluginTest.Da2[1]+","+PluginTest.Da2[2]+"]", "[1.1,2.1,null]", "string", row);
+    } catch (e) {
+        error(type, "[1.0,2.0,]", e, row);
+    }
+
+    tblBody.appendChild(row);
+}
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_casting_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_casting_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_casting_tests.js	(revision 403)
@@ -0,0 +1,825 @@
+/************************************************************
+ * Tests for data type conversion from JS to Java variables *
+ ************************************************************/
+
+function typeCastingTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java type casting tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Test Type";
+    columnNames[1] = "Send Value";
+    columnNames[2] = "Expected Value";
+    columnNames[3] = "Actual Value";
+    columnNames[4] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.String (Integer)";
+        setto = 1;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.String (Double)";
+        setto = 1.1;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.Object (Integer)";
+        setto = 1.0;
+        PluginTest.Object_type = setto;
+        now = PluginTest.Object_type + " | Superclass = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        addResult (type, setto, setto + " | Superclass = java.lang.Number", now, row);
+        check(now, setto + " | Superclass = java.lang.Number", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.Object (Double)";
+        setto = 1.1;
+        PluginTest.Object_type = setto;
+        now = PluginTest.Object_type + " | Superclass = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        addResult (type, setto, setto + " | Superclass = java.lang.Number", now, row);
+        check(now, setto + " | Superclass = java.lang.Number", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+   
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> boolean (0)";
+        setto = 0;
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, false, now, row);
+        check(now, false, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> boolean (1.1)";
+        setto = 1.1;
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, true, now, row);
+        check(now, true, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Boolean (true)";
+        setto = true;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Boolean (false)";
+        setto = false;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type;
+        addResult (type, setto, "false", now, row);
+        check(now, "false", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Object";
+        setto = true;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type + " | Class = " + PluginTest.Boolean_type.getClass().getName();
+        addResult (type, setto, "true | Class = java.lang.Boolean", now, row);
+        check(now, "true | Class = java.lang.Boolean", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.String";
+        setto = true;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.String";
+        setto = true;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> byte (true)";
+        setto = true;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> char (true)";
+        setto = true;
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> short (true)";
+        setto = true;
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> int (true)";
+        setto = true;
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> long (true)";
+        setto = true;
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> float (true)";
+        setto = true;
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> double (true)";
+        setto = true;
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> byte (false)";
+        setto = false;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> char (false)";
+        setto = false;
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> short (false)";
+        setto = false;
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> int (false)";
+        setto = false;
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> long (false)";
+        setto = false;
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> float (false)";
+        setto = false;
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> double (false)";
+        setto = false;
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> Object";
+        setto = "ð ãÂ£$Ç£â¬ð";
+        PluginTest.Object_type = setto;
+        
+        // Some weird FF bug is causing getClass to not work correctly when set 
+        // to a String (hasProperty/hasMethod "getClass" doesn't come through 
+        // to the plugin at all, so it is definitely an ff issue). So for now, 
+        // we just compare values.
+
+        //now = PluginTest.Object_type + " | Class = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        //addResult (type, setto, setto + " | Class = java.lang.String", now, row);
+        //check(now, setto + " | Class = java.lang.String", "string", row);
+        
+        now = PluginTest.Object_type;
+        PluginTest.Object_type.charAt(3); // try a String specific function to be sure it is a String
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> byte";
+        setto = "1";
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> short";
+        setto = "2";
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 2, now, row);
+        check(now, 2, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> int";
+        setto = "3";
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 3, now, row);
+        check(now, 3, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> long";
+        setto = "4";
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 4, now, row);
+        check(now, 4, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> float";
+        setto = "0.0";
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> double";
+        setto = "6.2";
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 6.2, now, row);
+        check(now, 6.2, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> char";
+        setto = "7";
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 7, now, row);
+        check(now, 7, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> boolean (empty/false)";
+        setto = "";
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, false, now, row);
+        check(now, false, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> boolean (non-empty/true)";
+        setto = "A non-empty string";
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, true, now, row);
+        check(now, true, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> byte[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.byte_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.byte_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> char[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.char_array = setto;
+
+        // For char array, don't convert to string.. the empty/null/0 character messes it up
+        now = PluginTest.char_array[0] + "," + PluginTest.char_array[1] + "," + PluginTest.char_array[2];
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> short[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.short_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.short_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> int[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.int_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.int_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> long[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.long_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.long_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> float[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.float_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.float_array);
+        addResult (type, setto, "1.0,0.0,2.0", now, row);
+        check(now, "1.0,0.0,2.0", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> double[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.double_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.double_array);
+        addResult (type, setto, "1.0,0.0,2.0", now, row);
+        check(now, "1.0,0.0,2.0", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> String[] (int)";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.String_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.String_array);
+        addResult (type, setto, "1,null,2", now, row);
+        check(now, "1,null,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Array -> String[] (int)";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.String_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.String_array);
+        addResult (type, setto, "1,null,2", now, row);
+        check(now, "1,null,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+    
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = "100";
+        a[0][2] = "102";
+        a[2][0] = "120";
+        a[2][1] = "121";
+        a[2][3] = "123";
+        
+        //
+        //    a = [[00, , 02]      // normal
+        //         []              // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> char[][] (string to primitive)";
+        PluginTest.char_array_array = a;
+        now = PluginTest.char_array_array[0][0] + "," + 
+                PluginTest.char_array_array[0][1] + "," + 
+                PluginTest.char_array_array[0][2] + "," + 
+              PluginTest.char_array_array[1][0] + "," + 
+              PluginTest.char_array_array[2][0] + "," + 
+                PluginTest.char_array_array[2][1] + "," + 
+                PluginTest.char_array_array[2][2] + "," + 
+                PluginTest.char_array_array[2][3];
+        expected = "100,0,102,undefined,120,121,0,123"
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = 100;
+        a[0][2] = 102;
+        a[2][0] = 120;
+        a[2][1] = 121;
+        a[2][3] = 123;
+        
+        //
+        //    a = [[00, , 02]     // normal
+        //         []          // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> String[][] (int to complex)";
+        PluginTest.String_array_array = a;
+        now = PluginTest.String_array_array[0][0] + "," + 
+                PluginTest.String_array_array[0][1] + "," + 
+                PluginTest.String_array_array[0][2] + "," + 
+              PluginTest.String_array_array[1][0] + "," + 
+              PluginTest.String_array_array[2][0] + "," + 
+                PluginTest.String_array_array[2][1] + "," + 
+                PluginTest.String_array_array[2][2] + "," + 
+                PluginTest.String_array_array[2][3];
+        expected = "100,null,102,undefined,120,121,null,123";
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = 100;
+        a[0][2] = 102;
+        a[2][0] = 120;
+        a[2][1] = 121;
+        a[2][3] = 123;
+        
+        //
+        //    a = [[00, , 02]      // normal
+        //         []              // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> String";
+        PluginTest.String_type = a;
+        now = PluginTest.String_type;
+        expected = "100,,102,,120,121,,123";
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "JSObject -> JSObject";
+        setto = window;
+        PluginTest.JSObject_type = setto;
+        now = PluginTest.JSObject_type;
+        addResult (type, setto, "[object Window]", now, row);
+        check(now, "[object Window]", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "JSObject -> String";
+        setto = window;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "[object Window]", now, row);
+        check(now, "[object Window]", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+        try {
+        row = document.createElement("tr");
+        type = "Java Object -> Java Object";
+        PluginTest.Float_type = 1.111;
+        orig_hash = PluginTest.Float_type.hashCode();
+        PluginTest.Object_type = PluginTest.Float_type;
+        new_hash = PluginTest.Object_type.hashCode();
+        addResult (type, "hashcode=" + orig_hash, orig_hash, new_hash, row);
+        check(new_hash, orig_hash, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Java Object -> String";
+        setto = new PluginTest.Packages.DummyObject("Test object");
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "Test object", now, row);
+        check(now, "Test object", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "null -> Java Object (String)";
+        
+        // Assuming the set tests have passed, we know that object is non-null after this
+        PluginTest.String_type = "Not Null"; 
+
+        setto = null;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, null, now, row);
+        check(now, null, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+/*
+    // NULL -> primitive tests are disabled for now due to ambiguity.
+    // Section 2.2 here: http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/
+    // States that null to primitive is not allowed, yet, section 2.3.7 claims it is..
+
+    try {
+        row = document.createElement("tr");
+        type = "null -> byte";
+        
+        // Assuming the set tests have passed, we know that object is non-null after this
+        PluginTest.byte_type = "100"; 
+
+        setto = null;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, null, now, row);
+        check(now, null, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+*/
+
+}
+
+
+
Index: /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_conversion_tests.js
===================================================================
--- /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_conversion_tests.js	(revision 403)
+++ /tags/icedtea-web/beta/plugin/tests/LiveConnect/jsj_type_conversion_tests.js	(revision 403)
@@ -0,0 +1,825 @@
+/************************************************************
+ * Tests for data type conversion from JS to Java variables *
+ ************************************************************/
+
+function typeCastingTests() {
+
+    document.getElementById("results").innerHTML +=  "<h2>JS -> Java type casting tests:</h2>";
+
+    var tbl = document.createElement("table");
+    var tblBody = document.createElement("tbody");
+    var columnNames = new Array();
+    columnNames[0] = "Test Type";
+    columnNames[1] = "Send Value";
+    columnNames[2] = "Expected Value";
+    columnNames[3] = "Actual Value";
+    columnNames[4] = "Status";
+    var row;
+
+    createResultTable(tbl, tblBody, columnNames);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.String (Integer)";
+        setto = 1;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.String (Double)";
+        setto = 1.1;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.Object (Integer)";
+        setto = 1.0;
+        PluginTest.Object_type = setto;
+        now = PluginTest.Object_type + " | Superclass = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        addResult (type, setto, setto + " | Superclass = java.lang.Number", now, row);
+        check(now, setto + " | Superclass = java.lang.Number", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> java.lang.Object (Double)";
+        setto = 1.1;
+        PluginTest.Object_type = setto;
+        now = PluginTest.Object_type + " | Superclass = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        addResult (type, setto, setto + " | Superclass = java.lang.Number", now, row);
+        check(now, setto + " | Superclass = java.lang.Number", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+   
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> boolean (0)";
+        setto = 0;
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, false, now, row);
+        check(now, false, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Numeric -> boolean (1.1)";
+        setto = 1.1;
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, true, now, row);
+        check(now, true, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Boolean (true)";
+        setto = true;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Boolean (false)";
+        setto = false;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type;
+        addResult (type, setto, "false", now, row);
+        check(now, "false", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.Object";
+        setto = true;
+        PluginTest.Boolean_type = setto;
+        now = PluginTest.Boolean_type + " | Class = " + PluginTest.Boolean_type.getClass().getName();
+        addResult (type, setto, "true | Class = java.lang.Boolean", now, row);
+        check(now, "true | Class = java.lang.Boolean", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.String";
+        setto = true;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> java.lang.String";
+        setto = true;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "true", now, row);
+        check(now, "true", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> byte (true)";
+        setto = true;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> char (true)";
+        setto = true;
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> short (true)";
+        setto = true;
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> int (true)";
+        setto = true;
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> long (true)";
+        setto = true;
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> float (true)";
+        setto = true;
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> double (true)";
+        setto = true;
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> byte (false)";
+        setto = false;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> char (false)";
+        setto = false;
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> short (false)";
+        setto = false;
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> int (false)";
+        setto = false;
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> long (false)";
+        setto = false;
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> float (false)";
+        setto = false;
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Boolean -> double (false)";
+        setto = false;
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> Object";
+        setto = "ð ãÂ£$Ç£â¬ð";
+        PluginTest.Object_type = setto;
+        
+        // Some weird FF bug is causing getClass to not work correctly when set 
+        // to a String (hasProperty/hasMethod "getClass" doesn't come through 
+        // to the plugin at all, so it is definitely an ff issue). So for now, 
+        // we just compare values.
+
+        //now = PluginTest.Object_type + " | Class = " + PluginTest.Object_type.getClass().getSuperclass().getName();
+        //addResult (type, setto, setto + " | Class = java.lang.String", now, row);
+        //check(now, setto + " | Class = java.lang.String", "string", row);
+        
+        now = PluginTest.Object_type;
+        PluginTest.Object_type.charAt(3); // try a String specific function to be sure it is a String
+        addResult (type, setto, setto, now, row);
+        check(now, setto, "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> byte";
+        setto = "1";
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, 1, now, row);
+        check(now, 1, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> short";
+        setto = "2";
+        PluginTest.short_type = setto;
+        now = PluginTest.short_type;
+        addResult (type, setto, 2, now, row);
+        check(now, 2, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> int";
+        setto = "3";
+        PluginTest.int_type = setto;
+        now = PluginTest.int_type;
+        addResult (type, setto, 3, now, row);
+        check(now, 3, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> long";
+        setto = "4";
+        PluginTest.long_type = setto;
+        now = PluginTest.long_type;
+        addResult (type, setto, 4, now, row);
+        check(now, 4, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> float";
+        setto = "0.0";
+        PluginTest.float_type = setto;
+        now = PluginTest.float_type;
+        addResult (type, setto, 0, now, row);
+        check(now, 0, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "String -> double";
+        setto = "6.2";
+        PluginTest.double_type = setto;
+        now = PluginTest.double_type;
+        addResult (type, setto, 6.2, now, row);
+        check(now, 6.2, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> char";
+        setto = "7";
+        PluginTest.char_type = setto;
+        now = PluginTest.char_type;
+        addResult (type, setto, 7, now, row);
+        check(now, 7, "number", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> boolean (empty/false)";
+        setto = "";
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, false, now, row);
+        check(now, false, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+
+    try {
+        row = document.createElement("tr");
+        type = "String -> boolean (non-empty/true)";
+        setto = "A non-empty string";
+        PluginTest.boolean_type = setto;
+        now = PluginTest.boolean_type;
+        addResult (type, setto, true, now, row);
+        check(now, true, "boolean", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> byte[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.byte_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.byte_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> char[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.char_array = setto;
+
+        // For char array, don't convert to string.. the empty/null/0 character messes it up
+        now = PluginTest.char_array[0] + "," + PluginTest.char_array[1] + "," + PluginTest.char_array[2];
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> short[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.short_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.short_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> int[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.int_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.int_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> long[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.long_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.long_array);
+        addResult (type, setto, "1,0,2", now, row);
+        check(now, "1,0,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> float[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.float_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.float_array);
+        addResult (type, setto, "1.0,0.0,2.0", now, row);
+        check(now, "1.0,0.0,2.0", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> double[]";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.double_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.double_array);
+        addResult (type, setto, "1.0,0.0,2.0", now, row);
+        check(now, "1.0,0.0,2.0", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Array -> String[] (int)";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.String_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.String_array);
+        addResult (type, setto, "1,null,2", now, row);
+        check(now, "1,null,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "Array -> String[] (int)";
+        setto = new Array();
+        setto[0] = 1;
+        setto[2] = 2;
+        PluginTest.String_array = setto;
+        now = PluginTest.getArrayAsStr(PluginTest.String_array);
+        addResult (type, setto, "1,null,2", now, row);
+        check(now, "1,null,2", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+    
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = "100";
+        a[0][2] = "102";
+        a[2][0] = "120";
+        a[2][1] = "121";
+        a[2][3] = "123";
+        
+        //
+        //    a = [[00, , 02]      // normal
+        //         []              // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> char[][] (string to primitive)";
+        PluginTest.char_array_array = a;
+        now = PluginTest.char_array_array[0][0] + "," + 
+                PluginTest.char_array_array[0][1] + "," + 
+                PluginTest.char_array_array[0][2] + "," + 
+              PluginTest.char_array_array[1][0] + "," + 
+              PluginTest.char_array_array[2][0] + "," + 
+                PluginTest.char_array_array[2][1] + "," + 
+                PluginTest.char_array_array[2][2] + "," + 
+                PluginTest.char_array_array[2][3];
+        expected = "100,0,102,undefined,120,121,0,123"
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = 100;
+        a[0][2] = 102;
+        a[2][0] = 120;
+        a[2][1] = 121;
+        a[2][3] = 123;
+        
+        //
+        //    a = [[00, , 02]     // normal
+        //         []          // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> String[][] (int to complex)";
+        PluginTest.String_array_array = a;
+        now = PluginTest.String_array_array[0][0] + "," + 
+                PluginTest.String_array_array[0][1] + "," + 
+                PluginTest.String_array_array[0][2] + "," + 
+              PluginTest.String_array_array[1][0] + "," + 
+              PluginTest.String_array_array[2][0] + "," + 
+                PluginTest.String_array_array[2][1] + "," + 
+                PluginTest.String_array_array[2][2] + "," + 
+                PluginTest.String_array_array[2][3];
+        expected = "100,null,102,undefined,120,121,null,123";
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        var a = [];
+        a[0] = [];
+        a[1] = [];
+        a[2] = [];
+        a[0][0] = 100;
+        a[0][2] = 102;
+        a[2][0] = 120;
+        a[2][1] = 121;
+        a[2][3] = 123;
+        
+        //
+        //    a = [[00, , 02]      // normal
+        //         []              // empty
+        //         [20, 21, , 23]] // length = element0.length + 1
+        //
+
+        row = document.createElement("tr");
+        type = "Array -> String";
+        PluginTest.String_type = a;
+        now = PluginTest.String_type;
+        expected = "100,,102,,120,121,,123";
+        addResult (type, a, expected, now, row);
+        check(now, expected, "string", row);
+    } catch (e) {
+        error(type, a, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "JSObject -> JSObject";
+        setto = window;
+        PluginTest.JSObject_type = setto;
+        now = PluginTest.JSObject_type;
+        addResult (type, setto, "[object Window]", now, row);
+        check(now, "[object Window]", "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "JSObject -> String";
+        setto = window;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "[object Window]", now, row);
+        check(now, "[object Window]", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+        try {
+        row = document.createElement("tr");
+        type = "Java Object -> Java Object";
+        PluginTest.Float_type = 1.111;
+        orig_hash = PluginTest.Float_type.hashCode();
+        PluginTest.Object_type = PluginTest.Float_type;
+        new_hash = PluginTest.Object_type.hashCode();
+        addResult (type, "hashcode=" + orig_hash, orig_hash, new_hash, row);
+        check(new_hash, orig_hash, "number", row);
+    } catch (e) {
+        error(type, "", e, row);
+    }
+    tblBody.appendChild(row);
+
+    try {
+        row = document.createElement("tr");
+        type = "Java Object -> String";
+        setto = new PluginTest.Packages.DummyObject("Test object");
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, "Test object", now, row);
+        check(now, "Test object", "string", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+    
+    try {
+        row = document.createElement("tr");
+        type = "null -> Java Object (String)";
+        
+        // Assuming the set tests have passed, we know that object is non-null after this
+        PluginTest.String_type = "Not Null"; 
+
+        setto = null;
+        PluginTest.String_type = setto;
+        now = PluginTest.String_type;
+        addResult (type, setto, null, now, row);
+        check(now, null, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+
+/*
+    // NULL -> primitive tests are disabled for now due to ambiguity.
+    // Section 2.2 here: http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/
+    // States that null to primitive is not allowed, yet, section 2.3.7 claims it is..
+
+    try {
+        row = document.createElement("tr");
+        type = "null -> byte";
+        
+        // Assuming the set tests have passed, we know that object is non-null after this
+        PluginTest.byte_type = "100"; 
+
+        setto = null;
+        PluginTest.byte_type = setto;
+        now = PluginTest.byte_type;
+        addResult (type, setto, null, now, row);
+        check(now, null, "object", row);
+    } catch (e) {
+        error(type, setto, e, row);
+    }
+    tblBody.appendChild(row);
+*/
+
+}
+
+
+
Index: /tags/icedtea-web/beta/plugin_os2.def
===================================================================
--- /tags/icedtea-web/beta/plugin_os2.def	(revision 403)
+++ /tags/icedtea-web/beta/plugin_os2.def	(revision 403)
@@ -0,0 +1,12 @@
+LIBRARY NPICEDT INITINSTANCE TERMINSTANCE
+
+CODE      MOVEABLE DISCARDABLE LOADONCALL
+DATA      MULTIPLE NONSHARED READWRITE LOADONCALL
+
+EXPORTS
+    NP_GetEntryPoints
+    NP_Initialize
+    NP_Shutdown
+
+;    NP_GetMIMEDescription
+;    NP_GetValue
Index: /tags/icedtea-web/beta/plugin_os2.rc.in
===================================================================
--- /tags/icedtea-web/beta/plugin_os2.rc.in	(revision 403)
+++ /tags/icedtea-web/beta/plugin_os2.rc.in	(revision 403)
@@ -0,0 +1,21 @@
+#include <npapi.h>
+
+/* RC_DATA types for version info - required */
+RCDATA NP_INFO_ProductVersion    { @PACKAGE_VER_MAJOR@,@PACKAGE_VER_MINOR@,@PACKAGE_VER_PATCH@,0 }
+RCDATA NP_INFO_MIMEType          { "application/x-java-vm\0" }
+RCDATA NP_INFO_FileOpenName      { "Java Plugin\0" }
+RCDATA NP_INFO_FileExtents       { "*\0" }
+
+/* RC_DATA types for version info - used if found */
+RCDATA NP_INFO_FileDescription   { "@PLUGIN_VERSION@\0" }
+RCDATA NP_INFO_ProductName       { "@PLUGIN_NAME@\0" }
+
+/* RC_DATA types for version info - optional */
+RCDATA NP_INFO_CompanyName       { "netlabs.org\0" }
+RCDATA NP_INFO_FileVersion       { @PACKAGE_VER_MAJOR@,@PACKAGE_VER_MINOR@,@PACKAGE_VER_PATCH@,0 }
+RCDATA NP_INFO_InternalName      { "NPICEDT.DLL\0" }
+RCDATA NP_INFO_LegalCopyright    { "Copyright (C) 2012\0" }
+RCDATA NP_INFO_OriginalFilename  { "NPICEDT.DLL\0" }
+
+/* BLDLEVEL info */
+RCDATA 9999 { "@#netlabs.org:@PACKAGE_VER_MAJOR@.@PACKAGE_VER_MINOR@#@##1## @BUILDDATE@ @HOSTNAME@::en::@PACKAGE_VER_PATCH@::@@@PLUGIN_NAME@" }
Index: /tags/icedtea-web/beta/tests/junit-runner/CommandLine.java
===================================================================
--- /tags/icedtea-web/beta/tests/junit-runner/CommandLine.java	(revision 403)
+++ /tags/icedtea-web/beta/tests/junit-runner/CommandLine.java	(revision 403)
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 Red Hat, Inc.
+ * Based on code from JUnit
+ *
+ * This file is made available under the terms of the Common Public License
+ * v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.internal.JUnitSystem;
+import org.junit.internal.RealSystem;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+public class CommandLine extends JUnitCore {
+
+    public static void main(String... args) {
+        runMainAndExit(new RealSystem(), args);
+    }
+
+    public static void runMainAndExit(JUnitSystem system, String... args) {
+        new CommandLine().runMain(system, args);
+        system.exit(0);
+    }
+
+    @Override
+    public Result runMain(JUnitSystem system, String... args) {
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+        List<Failure> missingClasses = new ArrayList<Failure>();
+        for (String each : args) {
+            try {
+                classes.add(Class.forName(each));
+            } catch (ClassNotFoundException e) {
+                system.out().println("ERROR: Could not find class: " + each);
+            }
+        }
+        RunListener listener = new LessVerboseTextListener(system);
+        addListener(listener);
+        Result result = run(classes.toArray(new Class[0]));
+        for (Failure each : missingClasses) {
+            result.getFailures().add(each);
+        }
+        return result;
+    }
+
+}
Index: /tags/icedtea-web/beta/tests/junit-runner/LessVerboseTextListener.java
===================================================================
--- /tags/icedtea-web/beta/tests/junit-runner/LessVerboseTextListener.java	(revision 403)
+++ /tags/icedtea-web/beta/tests/junit-runner/LessVerboseTextListener.java	(revision 403)
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This file is made available under the terms of the Common Public License
+ * v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ */
+import java.io.PrintStream;
+
+import org.junit.internal.JUnitSystem;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+public class LessVerboseTextListener extends RunListener {
+
+    private PrintStream writer;
+    private boolean testFailed = false;
+
+    public LessVerboseTextListener(JUnitSystem system) {
+        writer= system.out();
+    }
+
+    @Override
+    public void testStarted(Description description) throws Exception {
+        testFailed = false;
+    }
+
+    @Override
+    public void testFailure(Failure failure) {
+        testFailed = true;
+        writer.println("FAILED: " + failure.getTestHeader() + " " + failure.getMessage());
+    }
+
+    @Override
+    public void testFinished(org.junit.runner.Description description) throws Exception {
+        if (!testFailed) {
+            writer.println("Passed: " + description.getClassName() + "." + description.getMethodName());
+        }
+    }
+
+    @Override
+    public void testRunFinished(Result result) throws Exception {
+        int passed = result.getRunCount() - result.getFailureCount() - result.getIgnoreCount();
+        int failed = result.getFailureCount();
+        int ignored = result.getIgnoreCount();
+        writer.println("Test results: passed: " + passed + "; failed: " + failed + "; ignored: " + ignored);
+    }
+
+}
Index: /tags/icedtea-web/beta/tests/junit-runner/README
===================================================================
--- /tags/icedtea-web/beta/tests/junit-runner/README	(revision 403)
+++ /tags/icedtea-web/beta/tests/junit-runner/README	(revision 403)
@@ -0,0 +1,3 @@
+junit-runner is used to run tests instead of the standard runner
+org.junit.runner.JUnitCore.  It provides output similar to that used by JTreg,
+which is useful for automated comparison.
Index: /tags/icedtea-web/beta/tests/netx/pac/pac-funcs-test.js
===================================================================
--- /tags/icedtea-web/beta/tests/netx/pac/pac-funcs-test.js	(revision 403)
+++ /tags/icedtea-web/beta/tests/netx/pac/pac-funcs-test.js	(revision 403)
@@ -0,0 +1,443 @@
+
+var ICEDTEA_CLASSPATH_ORG_IP = "208.78.240.231";
+var CLASSPATH_ORG_IP = "199.232.41.10";
+
+var testsFailed = 0;
+var testsPassed = 0;
+
+print("loading needed files\n");
+file = arguments[0] + "";
+load(file)
+print("finished loaded needed files\n");
+
+
+function main() {
+
+	testIsPlainHostName();
+	testDnsDomainIs();
+	testLocalHostOrDomainIs();
+	testIsResolvable();
+	testIsInNet();
+	testDnsResolve();
+	testDnsDomainLevels();
+	testShExpMatch();
+	testWeekdayRange();
+	testDateRange();
+	testTimeRange();
+
+	java.lang.System.out.println("Test results: passed: " + testsPassed + "; failed: " + testsFailed + ";");
+}
+
+function runTests(name, tests) {
+
+	var undefined_var;
+
+	for ( var i = 0; i < tests.length; i++) {
+
+		var expectedVal = tests[i][0];
+		var args = tests[i].slice(1);
+		var returnVal;
+		try {
+			returnVal = name.apply(null, args);
+		} catch (e) {
+			returnVal = e;
+		}
+		if (returnVal === expectedVal) {
+			java.lang.System.out.println("Passed: " + name.name + "(" + args.join(", ") + ")");
+			testsPassed++;
+		} else {
+			java.lang.System.out.println("FAILED: " + name.name + "(" + args.join(", ") + ")");
+			java.lang.System.out.println("        Expected '" + expectedVal + "' but got '" + returnVal + "'");
+			testsFailed++;
+		}
+	}
+}
+
+function testIsPlainHostName() {
+    var tests = [
+        [ false, "icedtea.classpath.org" ],
+        [ false, "classpath.org" ],
+        [ true, "org" ],
+        [ true, "icedtea" ],
+        [ false, ".icedtea.classpath.org" ],
+        [ false, "icedtea." ],
+        [ false, "icedtea.classpath." ]
+    ];
+
+    runTests(isPlainHostName, tests);
+}
+
+function testDnsDomainIs() {
+    var tests = [
+        [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+        [ true, "icedtea.classpath.org", ".classpath.org" ],
+        [ true, "icedtea.classpath.org", ".org" ],
+        [ false, "icedtea.classpath.org", "icedtea.classpath.com" ],
+        [ false, "icedtea.classpath.org", "icedtea.classpath" ],
+        [ false, "icedtea.classpath", "icedtea.classpath.org" ],
+        [ false, "icedtea", "icedtea.classpath.org" ]
+    ];
+
+    runTests(dnsDomainIs, tests);
+}
+
+function testLocalHostOrDomainIs() {
+
+    var tests = [
+        [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+        [ true, "icedtea", "icedtea.classpath.org" ],
+        [ false, "icedtea.classpath.org", "icedtea.classpath.com" ],
+        [ false, "icedtea.classpath", "icedtea.classpath.org" ],
+        [ false, "foo.classpath.org", "icedtea.classpath.org" ],
+        [ false, "foo", "icedtea.classpath.org" ]
+    ];
+
+    runTests(localHostOrDomainIs, tests);
+}
+
+function testIsResolvable() {
+
+    var tests = [
+        [ true, "icedtea.classpath.org", "icedtea.classpath.org" ],
+        [ true, "classpath.org" ],
+        [ false, "NotIcedTeaHost" ],
+        [ false, "foobar.classpath.org" ],
+        [ false, "icedtea.classpath.com" ]
+    ];
+
+    runTests(isResolvable, tests);
+}
+
+function testIsInNet() {
+
+	var parts = ICEDTEA_CLASSPATH_ORG_IP.split("\.");
+
+	var fakeParts = ICEDTEA_CLASSPATH_ORG_IP.split("\.");
+	fakeParts[0] = fakeParts[0] + 1;
+
+	function createIp(array) {
+		return array[0] + "." + array[1] + "." + array[2] + "." + array[3];
+	}
+
+	var tests = [
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.255"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.0"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.0.0"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.0.0.0"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "0.0.0.0"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "255.255.255.255"],
+	    [ true, "icedtea.classpath.org", ICEDTEA_CLASSPATH_ORG_IP, "0.0.0.0"],
+	    [ true, "icedtea.classpath.org", createIp(parts), "255.255.255.255" ],
+	    [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.255.255"],
+	    [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.255.0"],
+	    [ false, "icedtea.classpath.org", createIp(fakeParts), "255.255.0.0"],
+	    [ false, "icedtea.classpath.org", createIp(fakeParts), "255.0.0.0"],
+	    [ true, "icedtea.classpath.org", createIp(fakeParts), "0.0.0.0"]
+	];
+
+	runTests(isInNet, tests);
+}
+
+function testDnsResolve() {
+    var tests = [
+        [ ICEDTEA_CLASSPATH_ORG_IP, "icedtea.classpath.org" ],
+        //[ CLASSPATH_ORG_IP, "classpath.org" ],
+        [ "127.0.0.1", "localhost" ]
+    ];
+
+    runTests(dnsResolve, tests);
+}
+
+function testDnsDomainLevels() {
+    var tests = [
+        [ 0, "org" ],
+        [ 1, "classpath.org" ],
+        [ 2, "icedtea.classpath.org" ],
+        [ 3, "foo.icedtea.classpath.org" ]
+    ];
+
+    runTests(dnsDomainLevels, tests);
+
+}
+function testShExpMatch() {
+    var tests = [
+         [ true, "icedtea.classpath.org", "icedtea.classpath.org"],
+         [ false, "icedtea.classpath.org", ".org"],
+         [ false, "icedtea.classpath.org", "icedtea."],
+         [ false, "icedtea", "icedtea.classpath.org"],
+
+         [ true, "icedtea.classpath.org", "*" ],
+         [ true, "icedtea.classpath.org", "*.classpath.org" ],
+         [ true, "http://icedtea.classpath.org", "*.classpath.org" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*/foobar/*" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*foobar*" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*foo*" ],
+         [ false, "http://icedtea.classpath.org/foobar/", "*/foo/*" ],
+         [ false, "http://icedtea.classpath.org/foobar/", "*/foob/*" ],
+         [ false, "http://icedtea.classpath.org/foobar/", "*/fooba/*" ],
+         [ false, "http://icedtea.classpath.org/foo/", "*foobar*" ],
+
+         [ true, "1", "?" ],
+         [ true, "12", "??" ],
+         [ true, "123", "1?3" ],
+         [ true, "123", "?23" ],
+         [ true, "123", "12?" ],
+         [ true, "1234567890", "??????????" ],
+         [ false, "1234567890", "?????????" ],
+         [ false, "123", "1?1" ],
+         [ false, "123", "??" ],
+
+         [ true, "http://icedtea.classpath.org/f1/", "*/f?/*" ],
+         [ true, "http://icedtea1.classpath.org/f1/", "*icedtea?.classpath*/f?/*" ],
+         [ false, "http://icedtea.classpath.org/f1/", "*/f2/*" ],
+         [ true, "http://icedtea.classpath.org/f1/", "*/f?/*" ],
+         [ false, "http://icedtea.classpath.org/f1", "f?*"],
+         [ false, "http://icedtea.classpath.org/f1", "f?*"],
+         [ false, "http://icedtea.classpath.org/f1", "f?*"],
+
+         [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+         [ true, "http://icedtea.classpath.org/foobar/", "*.classpath.org/*" ],
+
+         [ true, "http://icedtea.classpath.org/foo.php?id=bah", "*foo.php*" ],
+         [ false, "http://icedtea.classpath.org/foo_php?id=bah", "*foo.php*" ]
+     ];
+
+     runTests(shExpMatch, tests);
+}
+
+function testWeekdayRange() {
+
+    var today = new Date();
+    var day = today.getDay();
+
+    function dayToStr(day) {
+        switch (day) {
+            case -2: return "FRI";
+            case -1: return "SAT";
+            case 0: return "SUN";
+            case 1: return "MON";
+            case 2: return "TUE";
+            case 3: return "WED";
+            case 4: return "THU";
+            case 5: return "FRI";
+            case 6: return "SAT";
+            case 7: return "SUN";
+            case 8: return "MON";
+            default: return "FRI";
+        }
+
+    }
+
+    var tests = [
+       [ true, dayToStr(day) ],
+       [ false, dayToStr(day+1) ],
+       [ false, dayToStr(day-1) ],
+    ];
+}
+
+function testDateRange() {
+
+    function incDate(date) {
+        return (date + 1 - 1) % 31 +1 ;
+    }
+
+    function decDate(date) {
+        return (date - 1 - 1 + 31) % 31 + 1;
+    }
+
+    function monthToStr(month) {
+        switch (month) {
+            case -1: return "DEC";
+            case 0: return "JAN";
+            case 1: return "FEB";
+            case 2: return "MAR";
+            case 3: return "APR";
+            case 4: return "MAY";
+            case 5: return "JUN";
+            case 6: return "JUL";
+            case 7: return "AUG";
+            case 8: return "SEP";
+            case 9: return "OCT";
+            case 10: return "NOV";
+            case 11: return "DEC";
+            case 12: return "JAN";
+            default: throw "Invalid Month";
+        }
+    }
+
+    var today = new Date();
+    var date = today.getDate();
+    var month = today.getMonth();
+    var year = today.getYear();
+
+    var tests = [
+        [ true, date ],
+        [ false, incDate(date) ],
+        [ false, decDate(date) ],
+
+        [ true, monthToStr(month) ],
+        [ false, monthToStr(month+1) ],
+        [ false, monthToStr(month-1) ],
+
+        [ true, year ],
+        [ false, year - 1],
+        [ false, year + 1],
+
+        [ true, date, date ],
+        [ true, date, incDate(date) ],
+        [ true, decDate(date), date ],
+        [ true, decDate(date), incDate(date) ],
+        [ false, incDate(date), decDate(date) ],
+        [ false, decDate(decDate(date)), decDate(date) ],
+        [ false, incDate(date), incDate(incDate(date)) ],
+
+        [ true, monthToStr(month), monthToStr(month) ],
+        [ true, monthToStr(month), monthToStr(month+1) ],
+        [ true, monthToStr(month-1), monthToStr(month) ],
+        [ true, monthToStr(month-1), monthToStr(month+1) ],
+        [ true, "JAN", "DEC" ],
+        [ true, "DEC", "NOV" ],
+        [ true, "JUL", "JUN"],
+        [ false, monthToStr(month+1), monthToStr(month+1) ],
+        [ false, monthToStr(month-1), monthToStr(month-1) ],
+        [ false, monthToStr(month+1), monthToStr(month-1) ],
+
+        [ true, year, year ],
+        [ true, year, year+1 ],
+        [ true, year-1, year ],
+        [ true, year-1, year+1 ],
+        [ false, year-2, year-1 ],
+        [ false, year+1, year+1 ],
+        [ false, year+1, year+2 ],
+        [ false, year+1, year-1 ],
+
+        [ true, date, monthToStr(month) , date, monthToStr(month) ],
+        [ true, decDate(date), monthToStr(month) , date, monthToStr(month) ],
+        [ false, decDate(date), monthToStr(month) , decDate(date), monthToStr(month) ],
+        [ true, date, monthToStr(month) , incDate(date), monthToStr(month) ],
+        [ false, incDate(date), monthToStr(month) , incDate(date), monthToStr(month) ],
+        [ true, decDate(date), monthToStr(month) , incDate(date), monthToStr(month) ],
+        [ false, incDate(date), monthToStr(month) , decDate(date), monthToStr(month) ],
+        [ true, date, monthToStr(month-1) , date, monthToStr(month) ],
+        [ true, date, monthToStr(month) , date, monthToStr(month+1) ],
+        [ true, date, monthToStr(month-1) , date, monthToStr(month+1) ],
+        [ true, incDate(date), monthToStr(month-1) , date, monthToStr(month+1) ],
+        [ true, date, monthToStr(month-1) , decDate(date), monthToStr(month+1) ],
+        [ false, date, monthToStr(month+1) , date, monthToStr(month-1) ],
+        [ false, incDate(date), monthToStr(month+1) , incDate(date), monthToStr(month-1) ],
+        [ false, decDate(date), monthToStr(month+1) , decDate(date), monthToStr(month-1) ],
+        [ true, 1, "JAN", 31, "DEC" ],
+        [ true, 2, "JAN", 1, "JAN" ],
+        [ false, 1, monthToStr(month+1), 31, monthToStr(month+1) ],
+        [ false, 1, monthToStr(month-1), 31, monthToStr(month-1) ],
+
+        [ true, monthToStr(month), year, monthToStr(month), year ],
+        [ true, monthToStr(month-1), year, monthToStr(month), year ],
+        [ true, monthToStr(month), year, monthToStr(month+1), year ],
+        [ true, monthToStr(month-1), year, monthToStr(month+1), year ],
+        [ true, monthToStr(0), year, monthToStr(11), year ],
+        [ false, monthToStr(month+1), year, monthToStr(month-1), year ],
+        [ false, monthToStr(month+1), year, monthToStr(month+1), year ],
+        [ false, monthToStr(month-1), year, monthToStr(month-1), year ],
+        [ false, monthToStr(month), year-1, monthToStr(month-1), year ],
+        [ true, monthToStr(month), year, monthToStr(month), year + 1 ],
+        [ true, monthToStr(month), year-1, monthToStr(month), year ],
+        [ true, monthToStr(month), year-1, monthToStr(month), year+1 ],
+        [ true, monthToStr(0), year, monthToStr(0), year+1 ],
+        [ true, monthToStr(0), year-1, monthToStr(0), year+1 ],
+        [ false, monthToStr(0), year-1, monthToStr(11), year-1 ],
+        [ false, monthToStr(0), year+1, monthToStr(11), year+1 ],
+
+        [ true, date, monthToStr(month), year, date, monthToStr(month), year ],
+        [ true, decDate(date), monthToStr(month), year, incDate(date), monthToStr(month), year ],
+        [ true, decDate(date), monthToStr(month-1), year, incDate(date), monthToStr(month+1), year ],
+        [ true, decDate(date), monthToStr(month-1), year-1, incDate(date), monthToStr(month+1), year+1 ],
+        [ true, incDate(date), monthToStr(month-1), year-1, incDate(date), monthToStr(month+1), year+1 ],
+        [ false, incDate(date), monthToStr(month), year, incDate(date), monthToStr(month+1), year+1 ],
+        [ false, date, monthToStr(month+1), year, incDate(date), monthToStr(month+1), year+1 ],
+        [ true, 1, monthToStr(0), 0, 31, monthToStr(11), 100000 ],
+        [ true, 1, monthToStr(0), year, 31, monthToStr(11), year ],
+        [ true, 1, monthToStr(0), year-1, 31, monthToStr(11), year+1 ],
+        [ false, 1, monthToStr(0), year-1, 31, monthToStr(11), year-1 ],
+        [ false, 1, monthToStr(0), year+1, 31, monthToStr(11), year+1 ],
+
+    ];
+
+    runTests(dateRange, tests);
+
+}
+
+function testTimeRange() {
+    var now = new Date();
+
+    var hour = now.getHours();
+    var min = now.getMinutes();
+    var sec = now.getSeconds();
+
+    function toHour(input) {
+        if (input < 0) {
+            while (input < 0) {
+                input = input + 24;
+            }
+            return (input % 24);
+        } else {
+            return (input % 24);
+        }
+    }
+
+    function toMin(input) {
+        if (input < 0) {
+            while (input < 0) {
+                input = input + 60;
+            }
+            return (input % 60);
+        } else {
+            return (input % 60);
+        }
+    }
+
+    tests = [
+        [ true, hour ],
+        [ false, toHour(hour+1)],
+        [ false, toHour(hour-1)],
+
+        [ true, hour, hour ],
+        [ true, toHour(hour-1), hour ],
+        [ true, hour, toHour(hour+1)],
+        [ true, toHour(hour-1), toHour(hour+1)],
+        [ true, toHour(hour+1), hour ],
+        [ true, hour, toHour(hour-1) ],
+        [ false, toHour(hour-2), toHour(hour-1)],
+        [ false, toHour(hour+1), toHour(hour+2)],
+        [ false, toHour(hour+1), toHour(hour-1) ],
+        [ true, 0, 23 ],
+        [ true, 12, 11 ],
+
+        [ true, hour, min, hour, min ],
+        [ true, hour, min, hour, toMin(min+1) ],
+        [ true, hour, toMin(min-1), hour, min ],
+        [ true, hour, toMin(min-1), hour, toMin(min+1) ],
+        [ true, hour, toMin(min+2), hour, toMin(min+1) ],
+        [ false, hour, toMin(min+1), hour, toMin(min+1) ],
+        [ false, hour, toMin(min-1), hour, toMin(min-1) ],
+        [ false, hour, toMin(min+1), hour, toMin(min-1) ],
+        [ true, toHour(hour-1), min, hour, min ],
+        [ true, hour, min, toHour(hour+1), min ],
+        [ true, toHour(hour-1), min, toHour(hour+1), min ],
+        [ true, 0, 0, 23, 59 ],
+        [ true, 0, 1, 0, 0 ],
+
+        [ true, 0, 1, 0, 0, 0, 0 ],
+        [ true, hour, min, sec, hour, min, sec ],
+        [ true, hour, min, sec, hour, min + 10, sec ],
+        [ true, hour, min, sec - 10, hour, min, sec ],
+        [ true, hour, min, sec, hour, min-1 , sec ],
+
+    ];
+
+    runTests(timeRange, tests);
+}
+
+main();
Index: /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserBasic.java
===================================================================
--- /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserBasic.java	(revision 403)
+++ /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserBasic.java	(revision 403)
@@ -0,0 +1,282 @@
+/* ParserBasic.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Test that the parser works with basic jnlp files */
+public class ParserBasic {
+
+    private static Node root;
+    private static Parser parser;
+
+    @BeforeClass
+    public static void setUp() throws ParseException {
+        ClassLoader cl = ParserBasic.class.getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+        InputStream jnlpStream = cl.getResourceAsStream("net/sourceforge/jnlp/basic.jnlp");
+        root = Parser.getRootNode(jnlpStream);
+        parser = new Parser(null, null, root, false, false);
+    }
+
+    @Test
+    public void testJNLP() {
+        Assert.assertEquals("1.0", parser.getSpecVersion().toString());
+        Assert.assertEquals("http://localhost/", parser.getCodeBase().toString());
+        Assert.assertEquals("http://localhost/jnlp.jnlp", parser.getFileLocation().toString());
+    }
+
+    @Test
+    public void testInformation() throws ParseException {
+        List<InformationDesc> infos = parser.getInfo(root);
+        Assert.assertNotNull(infos);
+        Assert.assertEquals(1, infos.size());
+        InformationDesc info = infos.get(0);
+        Assert.assertNotNull(info);
+    }
+
+    @Test
+    public void testInformationTitle() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        Assert.assertEquals("Large JNLP", info.getTitle());
+    }
+
+    @Test
+    public void testInformationVendor() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        Assert.assertEquals("The IcedTea Project", info.getVendor());
+    }
+
+    @Test
+    public void testInformationHomePage() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        Assert.assertEquals("http://homepage/", info.getHomepage().toString());
+    }
+
+    @Test
+    public void testInformationDescription() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        Assert.assertEquals("one-line", info.getDescription("one-line"));
+        Assert.assertEquals("short", info.getDescription("short"));
+        Assert.assertEquals("tooltip", info.getDescription("tooltip"));
+    }
+
+    @Test
+    public void testInformationOfflineAllowed() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        Assert.assertEquals(true, info.isOfflineAllowed());
+
+    }
+
+    @Test
+    public void testInformationIcon() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+
+        IconDesc[] icons = info.getIcons(IconDesc.DEFAULT);
+        Assert.assertNotNull(icons);
+        Assert.assertEquals(1, icons.length);
+        IconDesc icon = icons[0];
+        Assert.assertNotNull(icon);
+        Assert.assertEquals("http://localhost/icon.png", icon.getLocation().toString());
+        icons = info.getIcons(IconDesc.SPLASH);
+        Assert.assertNotNull(icons);
+        Assert.assertEquals(1, icons.length);
+        icon = icons[0];
+        Assert.assertNotNull(icon);
+        Assert.assertEquals("http://localhost/splash.png", icon.getLocation().toString());
+
+    }
+
+    @Test
+    public void testInformationShortcut() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+
+        ShortcutDesc shortcut = info.getShortcut();
+        Assert.assertNotNull(shortcut);
+        Assert.assertTrue(shortcut.isOnline());
+        Assert.assertTrue(shortcut.onDesktop());
+        MenuDesc menu = shortcut.getMenu();
+        Assert.assertNotNull(menu);
+        Assert.assertEquals("submenu", menu.getSubMenu());
+    }
+
+    @Test
+    public void testInformationAssociation() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+        AssociationDesc[] associations = info.getAssociations();
+        Assert.assertNotNull(associations);
+        Assert.assertEquals(1, associations.length);
+        AssociationDesc association = associations[0];
+        Assert.assertNotNull(association);
+        String[] extensions = association.getExtensions();
+        Assert.assertNotNull(extensions);
+        Assert.assertEquals(1, extensions.length);
+        String extension = extensions[0];
+        Assert.assertNotNull(extension);
+        Assert.assertEquals("*.foo", extension);
+        String mimeType = association.getMimeType();
+        Assert.assertNotNull(mimeType);
+        Assert.assertEquals("foo/bar", mimeType);
+    }
+
+    @Test
+    public void testInformationRelatedContent() throws ParseException {
+        InformationDesc info = parser.getInfo(root).get(0);
+
+        RelatedContentDesc[] relatedContents = info.getRelatedContents();
+        Assert.assertNotNull(relatedContents);
+        Assert.assertEquals(1, relatedContents.length);
+        RelatedContentDesc relatedContent = relatedContents[0];
+        Assert.assertNotNull(relatedContent);
+        Assert.assertEquals("related-content title", relatedContent.getTitle());
+        Assert.assertNotNull(relatedContent.getLocation());
+        Assert.assertEquals("http://related-content/", relatedContent.getLocation().toString());
+        Assert.assertEquals("decription of related-content", relatedContent.getDescription());
+        IconDesc relatedIcon = relatedContent.getIcon();
+        Assert.assertNotNull(relatedIcon.getLocation());
+        Assert.assertEquals("http://localhost/related-content-icon.png", relatedIcon.getLocation().toString());
+
+    }
+
+    @Test
+    public void testSecurity() throws ParseException {
+        SecurityDesc security = parser.getSecurity(root);
+        Assert.assertNotNull(security);
+        Assert.assertEquals(SecurityDesc.ALL_PERMISSIONS, security.getSecurityType());
+    }
+
+    @Test
+    public void testResources() throws ParseException {
+        List<ResourcesDesc> allResources = parser.getResources(root, false);
+        Assert.assertNotNull(allResources);
+        Assert.assertEquals(1, allResources.size());
+        ResourcesDesc resources = allResources.get(0);
+        Assert.assertNotNull(resources);
+    }
+
+    @Test
+    public void testResourcesJava() throws ParseException {
+        ResourcesDesc resources = parser.getResources(root, false).get(0);
+        JREDesc[] jres = resources.getJREs();
+        Assert.assertNotNull(jres);
+        Assert.assertEquals(1, jres.length);
+        JREDesc jre = jres[0];
+        Assert.assertNotNull(jre);
+        Assert.assertEquals("1.3+", jre.getVersion().toString());
+        Assert.assertEquals("http://java-url/", jre.getLocation().toString());
+        Assert.assertEquals("64m", jre.getInitialHeapSize());
+        Assert.assertEquals("128m", jre.getMaximumHeapSize());
+    }
+
+    @Test
+    public void testResourcesJar() throws ParseException {
+        ResourcesDesc resources = parser.getResources(root, false).get(0);
+
+        boolean foundNative = false;
+        boolean foundEager = false;
+        boolean foundLazy = false;
+
+        JARDesc[] jars = resources.getJARs();
+        Assert.assertEquals(3, jars.length);
+        for (int i = 0; i < jars.length; i++) {
+            if (jars[i].isNative()) {
+                foundNative = true;
+                Assert.assertEquals("http://localhost/native.jar", jars[i].getLocation().toString());
+            } else if (jars[i].isEager()) {
+                foundEager = true;
+                Assert.assertEquals("http://localhost/eager.jar", jars[i].getLocation().toString());
+            } else if (jars[i].isLazy()) {
+                foundLazy = true;
+                Assert.assertEquals("http://localhost/lazy.jar", jars[i].getLocation().toString());
+            } else {
+                Assert.assertFalse(true);
+            }
+        }
+
+        Assert.assertTrue(foundNative);
+        Assert.assertTrue(foundLazy);
+        Assert.assertTrue(foundEager);
+    }
+
+    @Test
+    public void testResourcesExtensions() throws ParseException {
+        ResourcesDesc resources = parser.getResources(root, false).get(0);
+
+        ExtensionDesc[] extensions = resources.getExtensions();
+        Assert.assertNotNull(extensions);
+        Assert.assertEquals(1, extensions.length);
+        ExtensionDesc extension = extensions[0];
+        Assert.assertNotNull(extension);
+        Assert.assertEquals("http://extension/", extension.getLocation().toString());
+        Assert.assertEquals("extension", extension.getName());
+        Assert.assertEquals("0.1.1", extension.getVersion().toString());
+    }
+
+    @Test
+    public void testResourcesProperty() throws ParseException {
+        ResourcesDesc resources = parser.getResources(root, false).get(0);
+
+        PropertyDesc[] properties = resources.getProperties();
+        Assert.assertNotNull(properties);
+        Assert.assertEquals(1, properties.length);
+
+        PropertyDesc property = properties[0];
+        Assert.assertNotNull(property);
+        Assert.assertEquals("key", property.getKey());
+        Assert.assertEquals("value", property.getValue());
+    }
+
+    @Test
+    public void testApplication() throws ParseException {
+        ApplicationDesc app = (ApplicationDesc) parser.getLauncher(root);
+        Assert.assertNotNull(app);
+        Assert.assertEquals("MainClass", app.getMainClass());
+        Assert.assertArrayEquals(new String[] { "arg1", "arg2" }, app.getArguments());
+    }
+
+}
Index: /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserCornerCases.java
===================================================================
--- /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserCornerCases.java	(revision 403)
+++ /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserCornerCases.java	(revision 403)
@@ -0,0 +1,91 @@
+/* ParserCornerCases.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp;
+
+import java.io.ByteArrayInputStream;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/** Test various corner cases of the parser */
+public class ParserCornerCases {
+    @Test
+    public void testUnsupportedSpecNumber() throws ParseException {
+        String malformedJnlp = "<?xml?><jnlp spec='11.11'></jnlp>";
+        Node root = Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+        Parser parser = new Parser(null, null, root, false, false);
+        Assert.assertEquals("11.11", parser.getSpecVersion().toString());
+    }
+
+    @Test
+    public void testApplicationAndComponent() throws ParseException {
+        String malformedJnlp = "<?xml?><jnlp><application-desc/><component-desc/></jnlp>";
+        Node root = Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+        Parser parser = new Parser(null, null, root, false, false);
+        Assert.assertNotNull(parser.getLauncher(root));
+    }
+
+    @Test
+    public void testCommentInElements() throws ParseException {
+        String malformedJnlp = "<?xml?><jnlp spec='1.0' <!-- comment -->> </jnlp>";
+        Node root = Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+        Parser p = new Parser(null, null, root, false, false);
+        Assert.assertEquals("1.0", p.getSpecVersion().toString());
+    }
+
+    @Test
+    public void testCommentInAttributes() throws ParseException {
+        String malformedJnlp = "<?xml?><jnlp spec='<!-- something -->'></jnlp>";
+        Node root = Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+        Parser p = new Parser(null, null, root, false, false);
+        Assert.assertEquals("<!-- something -->", p.getSpecVersion().toString());
+    }
+
+    @Test
+    public void testNestedComments() throws ParseException {
+        String malformedJnlp = "<?xml?>" +
+                "<jnlp><information><description>" +
+                "<!-- outer <!-- inner --> -->" +
+                "</description></information></jnlp>";
+        Node root = Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+        Parser p = new Parser(null, null, root, false, false);
+        Assert.assertEquals(" -->", p.getInfo(root).get(0).getDescription());
+    }
+}
Index: /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserMalformedXml.java
===================================================================
--- /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserMalformedXml.java	(revision 403)
+++ /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/ParserMalformedXml.java	(revision 403)
@@ -0,0 +1,94 @@
+/* ParserMalformedXml.java
+   Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Test how well the parser deals with malformed xml */
+public class ParserMalformedXml {
+
+    private static String originalJnlp = null;
+
+    @BeforeClass
+    public static void setUp() throws IOException {
+        ClassLoader cl = ParserMalformedXml.class.getClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+        InputStream is = cl.getResourceAsStream("net/sourceforge/jnlp/basic.jnlp");
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+        StringBuilder jnlpBuilder = new StringBuilder();
+        String line;
+        while ( (line = reader.readLine()) != null) {
+            jnlpBuilder.append(line).append("\n");
+        }
+        originalJnlp = jnlpBuilder.toString();
+    }
+
+    @Test
+    public void testMissingXmlDecleration() throws ParseException {
+        String malformedJnlp = originalJnlp.replaceFirst("<\\?xml.*\\?>", "");
+        Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+    }
+
+    @Test
+    public void testMalformedArguments() throws ParseException {
+        String malformedJnlp = originalJnlp.replace("arg2</argument", "arg2<argument");
+        Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+    }
+
+    @Test
+    public void testTagNotClosed() throws ParseException {
+        String malformedJnlp = originalJnlp.replace("</jnlp>", "<jnlp>");
+        Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+    }
+
+    @Test
+    public void testUnquotedAttributes() throws ParseException {
+        String malformedJnlp = originalJnlp.replace("'jnlp.jnlp'", "jnlp.jnlp");
+        Parser.getRootNode(new ByteArrayInputStream(malformedJnlp.getBytes()));
+    }
+
+}
Index: /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/basic.jnlp
===================================================================
--- /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/basic.jnlp	(revision 403)
+++ /tags/icedtea-web/beta/tests/netx/unit/net/sourceforge/jnlp/basic.jnlp	(revision 403)
@@ -0,0 +1,47 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- this is a sample jnlp file -->
+<jnlp spec='1.0'
+    codebase='http://localhost/'
+    href='jnlp.jnlp'>
+  <information>
+    <!-- this is the information section -->
+    <title>Large JNLP</title>
+    <vendor>The IcedTea Project</vendor>
+    <homepage href='http://homepage/' />
+    <description kind='one-line'>one-line</description>
+    <description kind='short'>short</description>
+    <description kind='tooltip'>tooltip</description>
+    <icon href='icon.png' />
+    <icon href='splash.png' kind='splash' />
+    <offline-allowed />
+    <shortcut online='true'>
+      <desktop/>
+      <menu submenu='submenu'/>
+    </shortcut>
+    <association extensions='*.foo' mime-type='foo/bar'/>
+    <related-content href='http://related-content/'>
+      <title>related-content <!-- or something -->title</title>
+      <description>decription of related-content</description>
+      <icon href='related-content-icon.png' />
+    </related-content>
+  </information>
+  <security>
+    <all-permissions/>
+  </security>
+  <resources>
+    <!-- the resources section describes things needed -->
+    <java version='1.3+' href='http://java-url/'
+        initial-heap-size='64m'
+        max-heap-size='128m' />
+    <jar href='eager.jar' download='eager'/>
+    <jar href='lazy.jar' download='lazy'/>
+    <nativelib href='native.jar'/>
+    <extension name='extension' version='0.1.1' href='http://extension/'/>
+    <property name='key' value='value'/>
+  </resources>
+  <application-desc main-class='MainClass'>
+    <argument>arg1</argument>
+    <argument>arg2</argument>
+  </application-desc>
+</jnlp>
+
