Changeset 429 for trunk/icedtea-web/netx/net
- Timestamp:
- Sep 24, 2014, 9:34:21 PM (11 years ago)
- Location:
- trunk/icedtea-web/netx/net/sourceforge
- Files:
-
- 19 deleted
- 103 edited
- 50 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/icedtea-web/netx/net/sourceforge/jnlp/AbstractLaunchHandler.java
r418 r429 38 38 package net.sourceforge.jnlp; 39 39 40 import java.io.PrintStream;41 40 42 import net.sourceforge.jnlp. runtime.JNLPRuntime;41 import net.sourceforge.jnlp.util.logging.OutputController; 43 42 44 43 public abstract class AbstractLaunchHandler implements LaunchHandler { 45 44 46 protected final PrintStream outputStream;45 protected final OutputController logger; 47 46 48 public AbstractLaunchHandler( PrintStream outputStream) {49 this. outputStream = outputStream;47 public AbstractLaunchHandler(OutputController logger) { 48 this.logger = logger; 50 49 } 51 50 … … 64 63 result.append(recursiveDescription(ex.getCause())); 65 64 } 66 outputStream.println(result);65 logger.log(OutputController.Level.MESSAGE_ALL, result.toString()); 67 66 68 if (JNLPRuntime.isDebug()) { 69 ex.printStackTrace(outputStream); 70 } 67 logger.log(ex); 68 71 69 } 72 70 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/DefaultLaunchHandler.java
r418 r429 17 17 package net.sourceforge.jnlp; 18 18 19 import java.io.PrintStream;20 19 21 20 import net.sourceforge.jnlp.runtime.*; 21 import net.sourceforge.jnlp.util.logging.OutputController; 22 22 23 23 /** … … 31 31 public class DefaultLaunchHandler extends AbstractLaunchHandler { 32 32 33 public DefaultLaunchHandler( PrintStreamout) {33 public DefaultLaunchHandler(OutputController out) { 34 34 super(out); 35 35 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ExtensionDesc.java
r348 r429 24 24 25 25 import net.sourceforge.jnlp.runtime.JNLPRuntime; 26 import net.sourceforge.jnlp.util.logging.OutputController; 26 27 27 28 /** … … 123 124 file = new JNLPFile(location); 124 125 125 if (JNLPRuntime.isDebug()) 126 System.out.println("Resolve: " + file.getInformation().getTitle()); 126 OutputController.getLogger().log("Resolve: " + file.getInformation().getTitle()); 127 127 128 128 // check for it being an extension descriptor -
trunk/icedtea-web/netx/net/sourceforge/jnlp/GuiLaunchHandler.java
r418 r429 1 1 /* GuiLaunchHandler.java 2 Copyright (C) 201 1Red Hat, Inc.2 Copyright (C) 2012 Red Hat, Inc. 3 3 4 4 This file is part of IcedTea. … … 38 38 package net.sourceforge.jnlp; 39 39 40 import java.io.PrintStream;41 40 import java.lang.reflect.InvocationTargetException; 42 41 import java.net.URL; … … 48 47 import net.sourceforge.jnlp.runtime.ApplicationInstance; 49 48 import net.sourceforge.jnlp.util.BasicExceptionDialog; 49 import net.sourceforge.jnlp.util.logging.OutputController; 50 50 51 51 /** … … 55 55 public class GuiLaunchHandler extends AbstractLaunchHandler { 56 56 57 private JNLPSplashScreen splashScreen = null;57 private volatile JNLPSplashScreen splashScreen = null; 58 58 private final Object mutex = new Object(); 59 59 private UpdatePolicy policy = UpdatePolicy.ALWAYS; 60 60 61 public GuiLaunchHandler( PrintStreamoutputStream) {61 public GuiLaunchHandler(OutputController outputStream) { 62 62 super(outputStream); 63 63 } … … 81 81 82 82 private void closeSplashScreen() { 83 synchronized (mutex) {83 synchronized (mutex) { 84 84 if (splashScreen != null) { 85 85 if (splashScreen.isSplashScreenValid()) { 86 86 splashScreen.setVisible(false); 87 splashScreen.stopAnimation(); 87 88 } 88 89 splashScreen.dispose(); … … 103 104 @Override 104 105 public void launchInitialized(final JNLPFile file) { 105 106 106 107 int preferredWidth = 500; 107 108 int preferredHeight = 400; … … 110 111 IconDesc.SPLASH, preferredWidth, preferredHeight); 111 112 113 final ResourceTracker resourceTracker = new ResourceTracker(true); 112 114 if (splashImageURL != null) { 113 final ResourceTracker resourceTracker = new ResourceTracker(true);114 115 resourceTracker.addResource(splashImageURL, file.getFileVersion(), null, policy); 115 synchronized(mutex) { 116 try { 117 SwingUtilities.invokeAndWait(new Runnable() { 118 @Override 119 public void run() { 120 splashScreen = new JNLPSplashScreen(resourceTracker, null, null); 121 } 122 }); 123 } catch (InterruptedException ie) { 124 // Wait till splash screen is created 125 while (splashScreen == null); 126 } catch (InvocationTargetException ite) { 127 ite.printStackTrace(); 128 } 116 } 117 synchronized (mutex) { 118 try { 119 SwingUtilities.invokeAndWait(new Runnable() { 129 120 130 splashScreen.setSplashImageURL(splashImageURL); 121 @Override 122 public void run() { 123 splashScreen = new JNLPSplashScreen(resourceTracker, file); 124 } 125 }); 126 } catch (InterruptedException ie) { 127 // Wait till splash screen is created 128 while (splashScreen == null); 129 } catch (InvocationTargetException ite) { 130 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ite); 131 131 } 132 try { 133 SwingUtilities.invokeAndWait(new Runnable() { 134 135 @Override 136 public void run() { 137 splashScreen.setSplashImageURL(splashImageURL); 138 } 139 }); 140 } catch (InterruptedException ie) { 141 // Wait till splash screen is created 142 while (!splashScreen.isSplashImageLoaded()); 143 } catch (InvocationTargetException ite) { 144 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ite); 145 } 146 147 132 148 } 133 149 134 150 SwingUtilities.invokeLater(new Runnable() { 151 135 152 @Override 136 153 public void run() { 137 if (splash ImageURL!= null) {138 synchronized (mutex) {154 if (splashScreen != null) { 155 synchronized (mutex) { 139 156 if (splashScreen.isSplashScreenValid()) { 140 157 splashScreen.setVisible(true); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/InformationDesc.java
r348 r429 22 22 23 23 /** 24 * The information element. <p>24 * The information element. 25 25 * 26 26 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 35 35 36 36 /** one-line description */ 37 public static final Object ONE_LINE = "oneline"; 37 /**http://docs.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html**/ 38 public static final Object ONE_LINE = "one-line"; 38 39 39 40 /** short description */ … … 52 53 private List<Object> info; 53 54 54 /** the JNLPFile this information is for */55 private JNLPFile jnlpFile;56 55 57 56 /** 58 57 * Create an information element object. 59 58 * 60 * @param jnlpFile file that the information is for61 59 * @param locales the locales the information is for 62 60 */ 63 public InformationDesc(JNLPFile jnlpFile, Locale locales[]) { 64 this.jnlpFile = jnlpFile; 61 public InformationDesc(Locale locales[]) { 65 62 this.locales = locales; 66 63 } … … 111 108 */ 112 109 public String getDescription(Object kind) { 113 String result = (String) getItem("description-" +kind);110 String result = getDescriptionStrict(kind); 114 111 if (result == null) 115 112 return (String) getItem("description-" + DEFAULT); 116 113 else 117 114 return result; 115 } 116 117 /** 118 * Returns the application's description of the specified type. 119 * 120 * @param kind one of Information.SHORT, Information.ONE_LINE, 121 * Information.TOOLTIP, Information.DEFAULT 122 */ 123 public String getDescriptionStrict(Object kind) { 124 return (String) getItem("description-" + kind); 125 118 126 } 119 127 … … 160 168 } 161 169 170 // FIXME if there's no larger icon, choose the closest smaller icon 171 // instead of the first 162 172 if (best == null) 163 173 best = icons[0]; … … 171 181 public Locale[] getLocales() { 172 182 return locales; 173 }174 175 /**176 * Returns the JNLPFile the information is for.177 */178 public JNLPFile getJNLPFile() {179 return jnlpFile;180 183 } 181 184 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JARDesc.java
r348 r429 22 22 * The JAR element. 23 23 * 24 * This class is immutable and thread safe 24 25 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author 25 26 * @version $Revision: 1.6 $ … … 28 29 29 30 /** the location of the JAR file */ 30 private URL location;31 private final URL location; 31 32 32 33 /** the required JAR versions, or null */ 33 private Version version;34 private final Version version; 34 35 35 36 /** the part name */ 36 private String part;37 private final String part; 37 38 38 39 /** whether to load the JAR on demand */ 39 private boolean lazy;40 private final boolean lazy; 40 41 41 42 /** whether the JAR contains the main class */ 42 private boolean main;43 private final boolean main; 43 44 44 45 /** whether the JAR contains native libraries */ 45 private boolean nativeJar;46 private final boolean nativeJar; 46 47 47 48 /** whether the JAR can be cached */ 48 private boolean cacheable;49 private final boolean cacheable; 49 50 50 51 /** -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPCreator.java
r418 r429 29 29 30 30 public class JNLPCreator { 31 public JNLPFile create(URL location, Version version, boolean strict,31 public JNLPFile create(URL location, Version version, ParserSettings settings, 32 32 UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException { 33 return new JNLPFile(location, version, s trict, policy, forceCodebase);33 return new JNLPFile(location, version, settings, policy, forceCodebase); 34 34 } 35 35 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPFile.java
r418 r429 17 17 package net.sourceforge.jnlp; 18 18 19 import java.io.File; 20 import java.io.FileInputStream; 19 21 import static net.sourceforge.jnlp.runtime.Translator.R; 20 22 21 23 import java.io.IOException; 22 24 import java.io.InputStream; 23 import java.io.Reader;24 25 import java.net.URL; 25 26 import java.util.ArrayList; … … 29 30 import java.util.List; 30 31 import java.util.Locale; 31 32 import java.util.jar.Attributes; 33 34 import net.sourceforge.jnlp.SecurityDesc.RequestedPermissionLevel; 32 35 import net.sourceforge.jnlp.cache.ResourceTracker; 33 36 import net.sourceforge.jnlp.cache.UpdatePolicy; 37 import net.sourceforge.jnlp.runtime.JNLPClassLoader; 34 38 import net.sourceforge.jnlp.runtime.JNLPRuntime; 39 import net.sourceforge.jnlp.util.ClasspathMatcher; 40 import net.sourceforge.jnlp.util.logging.OutputController; 35 41 36 42 /** 43 * <p> 37 44 * Provides methods to access the information in a Java Network 38 45 * Launching Protocol (JNLP) file. The Java Network Launching 39 46 * Protocol specifies in an XML file the information needed to 40 47 * load, cache, and run Java code over the network and in a secure 41 * environment.<p> 42 * 48 * environment. 49 * </p> 50 * <p> 43 51 * This class represents the overall information about a JNLP file 44 52 * from the jnlp element. Other information is accessed through … … 46 54 * (information, resources, application-desc, etc). References to 47 55 * these objects are obtained by calling the getInformation, 48 * getResources, getSecurity, etc methods.<p> 56 * getResources, getSecurity, etc methods. 57 * </p> 49 58 * 50 59 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 52 61 */ 53 62 public class JNLPFile { 63 64 public static enum ManifestBoolean { 65 TRUE, FALSE, UNDEFINED; 66 } 67 54 68 55 69 // todo: save the update policy, then if file was not updated … … 68 82 protected URL fileLocation; 69 83 84 /** the ParserSettings which were used to parse this file */ 85 protected ParserSettings parserSettings = null; 86 70 87 /** A key that uniquely identifies connected instances (main jnlp+ext) */ 71 88 protected String uniqueKey = null; … … 119 136 */ 120 137 private String[] generalProperties = SecurityDesc.getJnlpRIAPermissions(); 138 139 /** important manifests' attributes */ 140 private final ManifestsAttributes manifestsAttributes = new ManifestsAttributes(); 141 142 public static final String TITLE_NOT_FOUND = "Application title was not found in manifest. Check with application vendor"; 143 121 144 122 145 { // initialize defaults if security allows … … 146 169 */ 147 170 public JNLPFile(URL location) throws IOException, ParseException { 148 this(location, false); // not strict171 this(location, new ParserSettings()); 149 172 } 150 173 … … 154 177 * 155 178 * @param location the location of the JNLP file 156 * @param s trict whether to enforce the spec when179 * @param settings the parser settings to use while parsing the file 157 180 * @throws IOException if an IO exception occurred 158 181 * @throws ParseException if the JNLP file was invalid 159 182 */ 160 public JNLPFile(URL location, boolean strict) throws IOException, ParseException {161 this(location, (Version) null, s trict);183 public JNLPFile(URL location, ParserSettings settings) throws IOException, ParseException { 184 this(location, (Version) null, settings); 162 185 } 163 186 … … 168 191 * @param location the location of the JNLP file 169 192 * @param version the version of the JNLP file 170 * @param s trict whether to enforce the spec when193 * @param settings the parser settings to use while parsing the file 171 194 * @throws IOException if an IO exception occurred 172 195 * @throws ParseException if the JNLP file was invalid 173 196 */ 174 public JNLPFile(URL location, Version version, boolean strict) throws IOException, ParseException {175 this(location, version, s trict, JNLPRuntime.getDefaultUpdatePolicy());197 public JNLPFile(URL location, Version version, ParserSettings settings) throws IOException, ParseException { 198 this(location, version, settings, JNLPRuntime.getDefaultUpdatePolicy()); 176 199 } 177 200 … … 182 205 * @param location the location of the JNLP file 183 206 * @param version the version of the JNLP file 184 * @param s trict whether to enforce the spec when207 * @param settings the {@link ParserSettings} to use when parsing the {@code location} 185 208 * @param policy the update policy 186 209 * @throws IOException if an IO exception occurred 187 210 * @throws ParseException if the JNLP file was invalid 188 211 */ 189 public JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {190 this(location, version, strict, policy, null);212 public JNLPFile(URL location, Version version, ParserSettings settings, UpdatePolicy policy) throws IOException, ParseException { 213 this(location, version, settings, policy, null); 191 214 } 192 215 … … 197 220 * @param location the location of the JNLP file 198 221 * @param version the version of the JNLP file 199 * @param s trict whether to enforce the spec when222 * @param settings the parser settings to use while parsing the file 200 223 * @param policy the update policy 201 224 * @param forceCodebase codebase to use if not specified in JNLP file. … … 203 226 * @throws ParseException if the JNLP file was invalid 204 227 */ 205 protected JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException { 206 Node root = Parser.getRootNode(openURL(location, version, policy)); 207 parse(root, strict, location, forceCodebase); 228 protected JNLPFile(URL location, Version version, ParserSettings settings, UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException { 229 InputStream input = openURL(location, version, policy); 230 this.parserSettings = settings; 231 parse(input, location, forceCodebase); 208 232 209 233 //Downloads the original jnlp file into the cache if possible … … 221 245 location; 222 246 223 if (JNLPRuntime.isDebug()) 224 System.err.println("UNIQUEKEY=" + this.uniqueKey); 247 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "UNIQUEKEY=" + this.uniqueKey); 225 248 } 226 249 … … 232 255 * @param uniqueKey A string that uniquely identifies connected instances 233 256 * @param version the version of the JNLP file 234 * @param s trict whether to enforce the spec when257 * @param settings the parser settings to use while parsing the file 235 258 * @param policy the update policy 236 259 * @throws IOException if an IO exception occurred 237 260 * @throws ParseException if the JNLP file was invalid 238 261 */ 239 public JNLPFile(URL location, String uniqueKey, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {240 this(location, version, s trict, policy);262 public JNLPFile(URL location, String uniqueKey, Version version, ParserSettings settings, UpdatePolicy policy) throws IOException, ParseException { 263 this(location, version, settings, policy); 241 264 this.uniqueKey = uniqueKey; 242 265 243 if (JNLPRuntime.isDebug()) 244 System.err.println("UNIQUEKEY (override) =" + this.uniqueKey); 266 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "UNIQUEKEY (override) =" + this.uniqueKey); 245 267 } 246 268 … … 251 273 * @throws ParseException if the JNLP file was invalid 252 274 */ 253 public JNLPFile(InputStream input, boolean strict) throws ParseException { 254 parse(Parser.getRootNode(input), strict, null, null); 255 } 256 257 /** 258 * Create a JNLPFile from a character stream. 259 * 260 * @param input the stream 261 * @param strict whether to enforce the spec when 275 public JNLPFile(InputStream input, ParserSettings settings) throws ParseException { 276 this.parserSettings = settings; 277 parse(input, null, null); 278 } 279 280 /** 281 * Create a JNLPFile from an input stream. 282 * 283 * @param input input stream of JNLP file. 284 * @param codebase codebase to use if not specified in JNLP file.. 285 * @param settings the {@link ParserSettings} to use when parsing 262 286 * @throws IOException if an IO exception occurred 263 287 * @throws ParseException if the JNLP file was invalid 264 288 */ 265 private JNLPFile(Reader input, boolean strict) throws ParseException { 266 // todo: now that we are using NanoXML we can use a Reader 267 //parse(Parser.getRootNode(input), strict, null); 268 } 289 public JNLPFile(InputStream input, URL codebase, ParserSettings settings) throws ParseException { 290 this.parserSettings = settings; 291 parse(input, null, codebase); 292 } 293 269 294 270 295 /** … … 279 304 ResourceTracker tracker = new ResourceTracker(false); // no prefetch 280 305 tracker.addResource(location, version, null, policy); 281 282 return tracker.getInputStream(location);306 File f = tracker.getCacheFile(location); 307 return new FileInputStream(f); 283 308 } catch (Exception ex) { 284 309 throw new IOException(ex.getMessage()); … … 289 314 * Returns the JNLP file's best localized title. This method returns the same 290 315 * value as InformationDesc.getTitle(). 316 * 317 * Since jdk7 u45, also manifest title, and mainclass are taken to consideration; 318 * See PluginBridge 291 319 */ 292 320 public String getTitle() { 321 String jnlpTitle = getTitleFromJnlp(); 322 String manifestTitle = getTitleFromManifest(); 323 if (jnlpTitle != null && manifestTitle != null) { 324 if (jnlpTitle.equals(manifestTitle)) { 325 return jnlpTitle; 326 } 327 return jnlpTitle+" ("+manifestTitle+")"; 328 } 329 if (jnlpTitle != null && manifestTitle == null) { 330 return jnlpTitle; 331 } 332 if (jnlpTitle == null && manifestTitle != null) { 333 return manifestTitle; 334 } 335 String mainClass = getManifestsAttributes().getMainClass(); 336 return mainClass; 337 } 338 339 /** 340 * Returns the JNLP file's best localized title. This method returns the same 341 * value as InformationDesc.getTitle(). 342 */ 343 public String getTitleFromJnlp() { 293 344 return getInformation().getTitle(); 294 345 } 346 347 public String getTitleFromManifest() { 348 String inManifestTitle = getManifestsAttributes().getApplicationName(); 349 if (inManifestTitle == null && getManifestsAttributes().isLoader()){ 350 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, TITLE_NOT_FOUND); 351 } 352 return inManifestTitle; 353 } 354 355 295 356 296 357 /** … … 326 387 327 388 /** 389 * Returns the ParserSettings that was used to parse this file 390 */ 391 public ParserSettings getParserSettings() { 392 return parserSettings; 393 } 394 395 /** 328 396 * Returns the JNLP file's version. 329 397 */ … … 359 427 */ 360 428 public InformationDesc getInformation(final Locale locale) { 361 return new InformationDesc( this,new Locale[] { locale }) {429 return new InformationDesc(new Locale[] { locale }) { 362 430 @Override 363 431 protected List<Object> getItems(Object key) { … … 424 492 } 425 493 494 public RequestedPermissionLevel getRequestedPermissionLevel() { 495 return this.security.getRequestedPermissionLevel(); 496 } 497 426 498 /** 427 499 * Returns the resources section of the JNLP file as viewed … … 597 669 /** 598 670 * Returns whether a locale is matched by one of more other 599 * locales. 671 * locales. Only the non-empty language, country, and variant 600 672 * codes are compared; for example, a requested locale of 601 673 * Locale("","","") would always return true. 602 674 * 603 * @param requested the local675 * @param requested the requested locale 604 676 * @param available the available locales 605 * @param precision the depth with which to match locales. 1 checks only606 * language, 2 checks language and country, 3 checks language, country and607 * variant for matches. Passing 0 will always return true.608 * @ return true if requested matches any of available, or if609 * available is empty or null.610 */ 611 public boolean localeMatches(Locale requested, Locale available[], Match matchLevel) {677 * @param matchLevel the depth with which to match locales. 678 * @return {@code true} if {@code requested} matches any of {@code available}, or if 679 * {@code available} is empty or {@code null}. 680 * @see Locale 681 * @see Match 682 */ 683 public boolean localeMatches(Locale requested, Locale[] available, Match matchLevel) { 612 684 613 685 if (matchLevel == Match.GENERALIZED) … … 672 744 * from the constructor. 673 745 * 674 * @param root the root node 675 * @param strict whether to enforce the spec when 676 * @param location the file location or null 677 */ 678 private void parse(Node root, boolean strict, URL location, URL forceCodebase) throws ParseException { 746 * @param location the file location or {@code null} 747 */ 748 private void parse(InputStream input, URL location, URL forceCodebase) throws ParseException { 679 749 try { 680 750 //if (location != null) 681 751 // location = new URL(location, "."); // remove filename 682 752 683 Parser parser = new Parser(this, location, root, strict, true, forceCodebase); // true == allow extensions 753 Node root = Parser.getRootNode(input, parserSettings); 754 Parser parser = new Parser(this, location, root, parserSettings, forceCodebase); // true == allow extensions 684 755 685 756 // JNLP tag information … … 701 772 throw ex; 702 773 } catch (Exception ex) { 703 if (JNLPRuntime.isDebug()) 704 ex.printStackTrace(); 705 774 OutputController.getLogger().log(ex); 706 775 throw new RuntimeException(ex.toString()); 707 776 } … … 777 846 778 847 /** 779 * XXX: this method does a "==" comparison between the input JARDesc and 780 * jars it finds through getResourcesDescs(). If ever the implementation 781 * of that function should change to return copies of JARDescs objects, 782 * then the "jar == aJar" comparison below should change accordingly. 783 * @param jar: the jar whose download options to get. 784 * @return the download options. 785 */ 786 public DownloadOptions getDownloadOptionsForJar(JARDesc jar) { 848 * @return the download options to use for downloading jars listed in this jnlp file. 849 */ 850 public DownloadOptions getDownloadOptions() { 787 851 boolean usePack = false; 788 852 boolean useVersion = false; 789 ResourcesDesc[] descs = getResourcesDescs(); 790 for (ResourcesDesc desc: descs) { 791 JARDesc[] jars = desc.getJARs(); 792 for (JARDesc aJar: jars) { 793 if (jar == aJar) { 794 if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.packEnabled"))) { 795 usePack = true; 796 } 797 if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.versionEnabled"))) { 798 useVersion = true; 799 } 800 } 801 } 853 ResourcesDesc desc = getResources(); 854 if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.packEnabled"))) { 855 usePack = true; 856 } 857 if (Boolean.valueOf(desc.getPropertiesMap().get("jnlp.versionEnabled"))) { 858 useVersion = true; 802 859 } 803 860 return new DownloadOptions(usePack, useVersion); … … 820 877 missingSignedJNLP = true; 821 878 } 879 880 public ManifestsAttributes getManifestsAttributes() { 881 return manifestsAttributes; 882 } 883 884 885 public class ManifestsAttributes { 886 887 public static final String APP_NAME = "Application-Name"; 888 public static final String CALLER_ALLOWABLE = "Caller-Allowable-Codebase"; 889 public static final String APP_LIBRARY_ALLOWABLE = "Application-Library-Allowable-Codebase"; 890 public static final String PERMISSIONS = "Permissions"; 891 public static final String CODEBASE = "Codebase"; 892 public static final String TRUSTED_ONLY = "Trusted-Only"; 893 public static final String TRUSTED_LIBRARY = "Trusted-Library"; 894 private JNLPClassLoader loader; 895 896 897 public void setLoader(JNLPClassLoader loader) { 898 this.loader = loader; 899 } 900 901 public boolean isLoader() { 902 return loader != null; 903 } 904 905 906 907 /** 908 * main class can be defined outside of manifest. 909 * This method is mostly for completeness 910 */ 911 public String getMainClass(){ 912 if (loader == null) { 913 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Jars not ready to provide main class"); 914 return null; 915 } 916 return loader.getMainClass(); 917 } 918 919 /** 920 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#app_name 921 */ 922 public String getApplicationName(){ 923 return getAttribute(APP_NAME); 924 } 925 926 /** 927 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#caller_allowable 928 */ 929 public ClasspathMatcher.ClasspathMatchers getCallerAllowableCodebase() { 930 return getCodeBaseMatchersAttribute(CALLER_ALLOWABLE, false); 931 } 932 933 /** 934 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#app_library 935 */ 936 public ClasspathMatcher.ClasspathMatchers getApplicationLibraryAllowableCodebase() { 937 return getCodeBaseMatchersAttribute(APP_LIBRARY_ALLOWABLE, true); 938 } 939 940 /** 941 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#codebase 942 */ 943 public ClasspathMatcher.ClasspathMatchers getCodebase() { 944 return getCodeBaseMatchersAttribute(CODEBASE, false); 945 } 946 947 /** 948 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#trusted_only 949 */ 950 public ManifestBoolean isTrustedOnly() { 951 return processBooleanAttribute(TRUSTED_ONLY); 952 953 } 954 955 /** 956 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#trusted_library 957 */ 958 public ManifestBoolean isTrustedLibrary() { 959 return processBooleanAttribute(TRUSTED_LIBRARY); 960 961 } 962 963 /** 964 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#permissions 965 */ 966 public ManifestBoolean isSandboxForced() { 967 String s = getAttribute(PERMISSIONS); 968 if (s == null) { 969 return ManifestBoolean.UNDEFINED; 970 } else if (s.trim().equalsIgnoreCase(SecurityDesc.RequestedPermissionLevel.SANDBOX.toHtmlString())) { 971 return ManifestBoolean.TRUE; 972 } else if (s.trim().equalsIgnoreCase(SecurityDesc.RequestedPermissionLevel.ALL.toHtmlString())) { 973 return ManifestBoolean.FALSE; 974 } else { 975 throw new IllegalArgumentException("Unknown value of " + PERMISSIONS + " attribute " + s + ". Expected "+SecurityDesc.RequestedPermissionLevel.SANDBOX.toHtmlString()+" or "+SecurityDesc.RequestedPermissionLevel.ALL.toHtmlString()); 976 } 977 978 979 } 980 /** 981 * http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#permissions 982 */ 983 public String permissionsToString() { 984 String s = getAttribute(PERMISSIONS); 985 if (s == null) { 986 return "Not defined"; 987 } else if (s.trim().equalsIgnoreCase(SecurityDesc.RequestedPermissionLevel.SANDBOX.toHtmlString())) { 988 return s.trim(); 989 } else if (s.trim().equalsIgnoreCase(SecurityDesc.RequestedPermissionLevel.ALL.toHtmlString())) { 990 return s.trim(); 991 } else { 992 return "illegal"; 993 } 994 } 995 996 /** 997 * get custom attribute. 998 */ 999 public String getAttribute(String name) { 1000 return getAttribute(new Attributes.Name(name)); 1001 } 1002 1003 /** 1004 * get standard attribute 1005 */ 1006 public String getAttribute(Attributes.Name name) { 1007 if (loader == null) { 1008 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Jars not ready to provide attribute " + name); 1009 return null; 1010 } 1011 return loader.checkForAttributeInJars(Arrays.asList(getResources().getJARs()), name); 1012 } 1013 1014 public ClasspathMatcher.ClasspathMatchers getCodeBaseMatchersAttribute(String s, boolean includePath) { 1015 return getCodeBaseMatchersAttribute(new Attributes.Name(s), includePath); 1016 } 1017 1018 public ClasspathMatcher.ClasspathMatchers getCodeBaseMatchersAttribute(Attributes.Name name, boolean includePath) { 1019 String s = getAttribute(name); 1020 if (s == null) { 1021 return null; 1022 } 1023 return ClasspathMatcher.ClasspathMatchers.compile(s, includePath); 1024 } 1025 1026 private ManifestBoolean processBooleanAttribute(String id) throws IllegalArgumentException { 1027 String s = getAttribute(id); 1028 if (s == null) { 1029 return ManifestBoolean.UNDEFINED; 1030 } else { 1031 s = s.toLowerCase().trim(); 1032 if (s.equals("true")) { 1033 return ManifestBoolean.TRUE; 1034 } else if (s.equals("false")) { 1035 return ManifestBoolean.FALSE; 1036 } else { 1037 throw new IllegalArgumentException("Unknown value of " + id + " attribute " + s + ". Expected true or false"); 1038 } 1039 } 1040 } 1041 } 822 1042 } 1043 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPMatcher.java
r418 r429 48 48 import java.util.Collections; 49 49 import java.util.LinkedList; 50 import net.sourceforge.jnlp.util.logging.OutputController; 50 51 import net.sourceforge.nanoxml.XMLElement; 51 52 … … 203 204 204 205 /** 205 * Compares attributes of two Nodes regardless of order 206 * 207 * @param appTemplateNode 208 * signed application or template's Node with attributes 209 * @param launchJNLPNode 210 * launching JNLP file's Node with attributes 211 * 212 * @return true if both Nodes have 'matched' attributes, otherwise false 206 * Compares attributes of two {@link Node Nodes} regardless of order 207 * 208 * @param templateNode signed application or template's {@link Node} with attributes 209 * @param launchNode launching JNLP file's {@link Node} with attributes 210 * 211 * @return {@code true} if both {@link Node Nodes} have 'matched' attributes, otherwise {@code false} 213 212 */ 214 213 private boolean matchAttributes(Node templateNode, Node launchNode) { … … 262 261 stream.close(); 263 262 } catch (Exception e) { 264 e.printStackTrace(System.err);263 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 265 264 } 266 265 } … … 277 276 stream.close(); 278 277 } catch (Exception e) { 279 e.printStackTrace(System.err);278 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 280 279 } 281 280 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPMatcherException.java
r418 r429 1 /* JNLPMatcherException.java 2 Copyright (C) 2011 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 1 38 package net.sourceforge.jnlp; 2 39 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPSplashScreen.java
r418 r429 1 /* JNLPSplashScreen.java 2 Copyright (C) 2012 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 IcedTea is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with IcedTea; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 1 38 package net.sourceforge.jnlp; 2 39 40 import java.awt.BorderLayout; 3 41 import java.awt.Dimension; 4 42 import java.awt.Graphics; … … 6 44 import java.awt.Image; 7 45 import java.awt.Insets; 8 import java.awt. Toolkit;46 import java.awt.Rectangle; 9 47 import java.io.IOException; 10 48 import java.net.URL; 11 12 49 import javax.imageio.ImageIO; 13 50 import javax.swing.JDialog; 14 15 51 import net.sourceforge.jnlp.cache.ResourceTracker; 16 52 import net.sourceforge.jnlp.runtime.JNLPRuntime; 53 import net.sourceforge.jnlp.splashscreen.SplashPanel; 54 import net.sourceforge.jnlp.splashscreen.SplashUtils; 55 import net.sourceforge.jnlp.splashscreen.parts.InformationElement; 17 56 import net.sourceforge.jnlp.util.ImageResources; 57 import net.sourceforge.jnlp.util.logging.OutputController; 58 import net.sourceforge.jnlp.util.ScreenFinder; 18 59 19 60 public class JNLPSplashScreen extends JDialog { 20 61 21 String applicationTitle;22 String applicationVendor;23 62 24 63 ResourceTracker resourceTracker; … … 26 65 URL splashImageUrl; 27 66 Image splashImage; 67 private final JNLPFile file; 68 public static final int DEF_WIDTH=635; 69 public static final int DEF_HEIGHT=480; 70 private SplashPanel componetSplash; 71 private boolean splashImageLoaded=false; 28 72 29 public JNLPSplashScreen(ResourceTracker resourceTracker, 30 String applicationTitle, String applicationVendor) { 73 public JNLPSplashScreen(ResourceTracker resourceTracker, final JNLPFile file) { 31 74 32 75 setIconImages(ImageResources.INSTANCE.getApplicationImages()); … … 37 80 38 81 this.resourceTracker = resourceTracker; 39 this.applicationTitle = applicationTitle; 40 this.applicationVendor = applicationVendor; 82 this.file=file; 41 83 42 84 } 43 85 44 86 public void setSplashImageURL(URL url) { 45 splashImageUrl = url; 46 splashImage = null; 87 splashImageLoaded = false; 47 88 try { 48 splashImage = ImageIO.read(resourceTracker 49 .getCacheFile(splashImageUrl)); 89 if (url != null) { 90 splashImageUrl = url; 91 splashImage = null; 92 try { 93 splashImage = ImageIO.read(resourceTracker.getCacheFile(splashImageUrl)); 94 if (splashImage == null) { 95 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Error loading splash image: " + url); 96 } 97 } catch (IOException e) { 98 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Error loading splash image: " + url); 99 splashImage = null; 100 } catch (IllegalArgumentException argumentException) { 101 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Error loading splash image: " + url); 102 splashImage = null; 103 } 104 } 105 50 106 if (splashImage == null) { 51 if (JNLPRuntime.isDebug()) { 52 System.err.println("Error loading splash image: " + url); 107 this.setLayout(new BorderLayout()); 108 SplashPanel splash = SplashUtils.getSplashScreen(DEF_WIDTH, DEF_HEIGHT); 109 if (splash != null) { 110 splash.startAnimation(); 111 splash.setInformationElement(InformationElement.createFromJNLP(file)); 112 this.add(splash.getSplashComponent()); 113 this.componetSplash = splash; 53 114 } 54 return;55 115 } 56 } catch (IOException e) { 57 if (JNLPRuntime.isDebug()) { 58 System.err.println("Error loading splash image: " + url); 59 } 60 splashImage = null; 61 return; 62 } catch (IllegalArgumentException argumentException) { 63 if (JNLPRuntime.isDebug()) { 64 System.err.println("Error loading splash image: " + url); 65 } 66 splashImage = null; 67 return; 116 correctSize(); 117 } finally { 118 splashImageLoaded = true; 68 119 } 69 70 correctSize();71 120 } 72 121 122 public boolean isSplashImageLoaded() { 123 return splashImageLoaded; 124 } 125 126 73 127 public boolean isSplashScreenValid() { 74 return (splashImage != null) ;128 return (splashImage != null) || (componetSplash != null); 75 129 } 76 130 77 131 private void correctSize() { 78 79 Insets insets = getInsets(); 80 int minimumWidth = splashImage.getWidth(null) + insets.left 81 + insets.right; 82 int minimumHeight = splashImage.getHeight(null) + insets.top 83 + insets.bottom; 84 setMinimumSize(new Dimension(minimumWidth, minimumHeight)); 85 86 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 87 setLocation((screenSize.width - minimumWidth) / 2, 88 (screenSize.height - minimumHeight) / 2); 132 int minimumWidth = DEF_WIDTH; 133 int minimumHeight = DEF_HEIGHT; 134 if (splashImage != null) { 135 Insets insets = getInsets(); 136 minimumWidth = splashImage.getWidth(null) + insets.left 137 + insets.right; 138 minimumHeight = splashImage.getHeight(null) + insets.top 139 + insets.bottom; 140 } 141 setMinimumSize(new Dimension(0, 0)); 142 setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); 143 setSize(new Dimension(minimumWidth, minimumHeight)); 144 setPreferredSize(new Dimension(minimumWidth, minimumHeight)); 145 ScreenFinder.centerWindowsToCurrentScreen(this); 89 146 } 90 147 … … 92 149 public void paint(Graphics g) { 93 150 if (splashImage == null) { 151 super.paint(g); 94 152 return; 95 153 } … … 100 158 101 159 } 160 161 public boolean isCustomSplashscreen() { 162 return (componetSplash!=null); 163 } 164 165 public void stopAnimation() { 166 if (isCustomSplashscreen()) componetSplash.stopAnimation(); 167 } 102 168 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JREDesc.java
r348 r429 21 21 import java.net.*; 22 22 import java.util.*; 23 import java.util.regex.Matcher; 24 import java.util.regex.Pattern; 23 25 24 26 /** … … 29 31 */ 30 32 public class JREDesc { 33 34 private static final Pattern heapPattern= Pattern.compile("\\d+[kmg]?"); 31 35 32 36 /** the platform version or the product version if location is not null */ 33 private Version version;37 final private Version version; 34 38 35 39 /** the location of a JRE product or null */ 36 private URL location;40 final private URL location; 37 41 38 42 /** inital heap size */ 39 private String initialHeapSize;43 final private String initialHeapSize; 40 44 41 45 /** maximum head size */ 42 private String maximumHeapSize;46 final private String maximumHeapSize; 43 47 44 48 /** args to pass to the vm */ 45 private String vmArgs;49 final private String vmArgs; 46 50 47 51 /** list of ResourceDesc objects */ 48 private Listresources;52 final private List<ResourcesDesc> resources; 49 53 50 54 /** … … 60 64 public JREDesc(Version version, URL location, 61 65 String vmArgs, String initialHeapSize, 62 String maximumHeapSize, List resources) throws ParseException {66 String maximumHeapSize, List<ResourcesDesc> resources) throws ParseException { 63 67 this.version = version; 64 68 this.location = location; 65 69 this.vmArgs = vmArgs; 66 checkHeapSize(initialHeapSize); 67 this.initialHeapSize = initialHeapSize; 68 checkHeapSize(maximumHeapSize); 69 this.maximumHeapSize = maximumHeapSize; 70 this.initialHeapSize = checkHeapSize(initialHeapSize); 71 this.maximumHeapSize = checkHeapSize(maximumHeapSize); 70 72 this.resources = resources; 71 73 } … … 113 115 * Returns the resources defined for this JRE. 114 116 */ 115 public List getResourcesDesc() {117 public List<ResourcesDesc> getResourcesDesc() { 116 118 return resources; 117 119 } … … 127 129 /** 128 130 * Check for valid heap size string 131 * @return trimed heapSize if correct 129 132 * @throws ParseException if heapSize is invalid 130 133 */ 131 static private voidcheckHeapSize(String heapSize) throws ParseException {134 static String checkHeapSize(String heapSize) throws ParseException { 132 135 // need to implement for completeness even though not used in netx 133 136 if (heapSize == null) { 134 return ;137 return null; 135 138 } 136 137 boolean lastCharacterIsDigit = true; 138 // the last character must be 0-9 or k/K/m/M 139 char lastChar = Character.toLowerCase(heapSize.charAt(heapSize.length() - 1)); 140 if ((lastChar < '0' || lastChar > '9')) { 141 lastCharacterIsDigit = false; 142 if (lastChar != 'k' && lastChar != 'm') { 143 throw new ParseException(R("PBadHeapSize", heapSize)); 144 } 139 heapSize = heapSize.trim(); 140 // the last character must be 0-9 or k/K/m/M/g/G 141 //0 or 0k/m/g is also accepted value 142 String heapSizeLower = heapSize.toLowerCase(); 143 Matcher heapMatcher = heapPattern.matcher(heapSizeLower); 144 if (!heapMatcher.matches()) { 145 throw new ParseException(R("PBadHeapSize", heapSize)); 145 146 } 146 147 int indexOfLastDigit = heapSize.length() - 1; 148 if (!lastCharacterIsDigit) { 149 indexOfLastDigit = indexOfLastDigit - 1; 150 } 151 152 String size = heapSize.substring(0, indexOfLastDigit); 153 try { 154 // check that the number is a number! 155 Integer.valueOf(size); 156 } catch (NumberFormatException numberFormat) { 157 throw new ParseException(R("PBadHeapSize", heapSize), numberFormat); 158 } 159 147 return heapSize; 148 160 149 } 161 150 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/LaunchException.java
r418 r429 17 17 package net.sourceforge.jnlp; 18 18 19 import java.util.Collections; 20 import java.util.Date; 21 import java.util.LinkedList; 22 import java.util.List; 23 19 24 /** 20 25 * Thrown when a JNLP application, applet, or installer could not … … 25 30 */ 26 31 public class LaunchException extends Exception { 32 33 34 public static class LaunchExceptionWithStamp{ 35 private final LaunchException ex; 36 private final Date stamp; 37 38 private LaunchExceptionWithStamp(LaunchException ex) { 39 this.ex=ex; 40 this.stamp=new Date(); 41 } 42 43 public LaunchException getEx() { 44 return ex; 45 } 46 47 public Date getStamp() { 48 return stamp; 49 } 50 51 52 53 } 54 private static final List<LaunchExceptionWithStamp> launchExceptionChain = Collections.synchronizedList(new LinkedList<LaunchExceptionWithStamp>()); 27 55 28 56 private static final long serialVersionUID = 7283827853612357423L; … … 55 83 this.description = description; 56 84 this.severity = severity; 85 saveLaunchException(this); 57 86 } 58 87 … … 62 91 public LaunchException(Throwable cause) { 63 92 super(cause); 93 saveLaunchException(this); 64 94 } 65 95 … … 69 99 public LaunchException(String message, Throwable cause) { 70 100 super(message, cause); 101 saveLaunchException(this); 71 102 } 72 103 … … 79 110 public LaunchException(String message) { 80 111 super(message); 112 saveLaunchException(this); 81 113 } 82 114 … … 118 150 } 119 151 152 private synchronized void saveLaunchException(LaunchException ex) { 153 launchExceptionChain.add(new LaunchExceptionWithStamp(ex)); 154 155 } 156 157 public synchronized static List<LaunchExceptionWithStamp> getLaunchExceptionChain() { 158 return launchExceptionChain; 159 } 160 161 162 120 163 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/LaunchHandler.java
r418 r429 62 62 * splash screen. 63 63 * 64 * @param application the applicationinstance that is starting64 * @param file the JNLP file of the instance that is starting 65 65 */ 66 66 public void launchInitialized(JNLPFile file); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Launcher.java
r418 r429 20 20 21 21 import java.applet.Applet; 22 import java.applet.AppletStub; 22 23 import java.awt.Container; 24 import java.awt.SplashScreen; 23 25 import java.io.File; 24 26 import java.lang.reflect.Method; … … 30 32 import java.util.List; 31 33 import java.util.Map; 32 import java.util.jar.JarFile;34 import net.sourceforge.jnlp.util.JarFile; 33 35 34 36 import net.sourceforge.jnlp.cache.CacheUtil; … … 43 45 import javax.swing.SwingUtilities; 44 46 import javax.swing.text.html.parser.ParserDelegator; 47 import net.sourceforge.jnlp.splashscreen.SplashUtils; 48 import net.sourceforge.jnlp.util.logging.OutputController; 45 49 46 50 import sun.awt.SunToolkit; 47 51 48 52 /** 49 * Launches JNLPFiles either in the foreground or background. <p>50 * 53 * Launches JNLPFiles either in the foreground or background. 54 * <p> 51 55 * An optional LaunchHandler can be specified that is notified of 52 56 * warning and error condition while launching and that indicates 53 57 * whether a launch may proceed after a warning has occurred. If 54 58 * specified, the LaunchHandler is notified regardless of whether 55 * the file is launched in the foreground or background.<p> 59 * the file is launched in the foreground or background. 60 * </p> 56 61 * 57 62 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 74 79 private boolean context = true; 75 80 76 /** If the application should call System.exit on fatal errors */81 /** If the application should call JNLPRuntime.exit on fatal errors */ 77 82 private boolean exitOnFailure = true; 78 83 … … 88 93 this(null, null); 89 94 90 if (handler == null) 95 if (handler == null) { 91 96 handler = JNLPRuntime.getDefaultLaunchHandler(); 97 } 92 98 } 93 99 … … 101 107 this(null, null); 102 108 103 if (handler == null) 109 if (handler == null) { 104 110 handler = JNLPRuntime.getDefaultLaunchHandler(); 111 } 105 112 106 113 this.exitOnFailure = exitOnFailure; … … 137 144 */ 138 145 public void setUpdatePolicy(UpdatePolicy policy) { 139 if (policy == null) 146 if (policy == null) { 140 147 throw new IllegalArgumentException(R("LNullUpdatePolicy")); 148 } 141 149 142 150 this.updatePolicy = policy; … … 220 228 //file. 221 229 if (!file.getInformation().isOfflineAllowed()) { 222 try { 223 //Checks the offline/online status of the system. 224 //If system is offline do not launch. 225 InetAddress.getByName(file.getSourceLocation().getHost()); 226 227 } catch (UnknownHostException ue) { 228 System.err.println("File cannot be launched because offline-allowed tag not specified and system currently offline."); 230 //offline status should be already known from jnlp downloading 231 if (!JNLPRuntime.isOnlineDetected()) { 232 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "File cannot be launched because offline-allowed tag not specified and system currently offline."); 229 233 return null; 230 } catch (Exception e) { 231 System.err.println(e); 232 } 233 } 234 235 if (file instanceof PluginBridge && cont != null) 234 } 235 } 236 237 if (file instanceof PluginBridge && cont != null) { 236 238 tg = new TgThread(file, cont, true); 237 else if (cont == null) 239 } 240 else if (cont == null) { 238 241 tg = new TgThread(file); 239 else 242 } 243 else { 240 244 tg = new TgThread(file, cont); 245 } 241 246 242 247 tg.start(); … … 249 254 } 250 255 251 if (tg.getException() != null) 252 throw tg.getException(); // passed to handler when first created 253 254 if (handler != null) 256 if (tg.getException() != null) { 257 throw tg.getException(); 258 } // passed to handler when first created 259 260 if (handler != null) { 255 261 handler.launchCompleted(tg.getApplication()); 262 } 256 263 257 264 return tg.getApplication(); 258 265 } 266 259 267 260 268 /** … … 263 271 * 264 272 * @param location the URL of the JNLP file to launch 265 * @throws LaunchException if there was an exception266 * @return the application instance267 */268 public ApplicationInstance launch(URL location) throws LaunchException {269 return launch(toFile(location));270 }271 272 /**273 * Launches a JNLP file by calling the launch method for the274 * appropriate file type.275 *276 * @param location the URL of the JNLP file to launch277 * @param fromSource if true, the JNLP file will be re-read from the source278 273 * location to get the pristine version 279 274 * @throws LaunchException if there was an exception 280 275 * @return the application instance 281 276 */ 282 public ApplicationInstance launch(URL location, boolean fromSource) throws LaunchException { 283 return launch(fromUrl(location, fromSource)); 277 public ApplicationInstance launch(URL location) throws LaunchException { 278 JNLPRuntime.saveHistory(location.toExternalForm()); 279 return launch(fromUrl(location)); 284 280 } 285 281 … … 370 366 } 371 367 372 /** 373 * Launches a JNLP file by calling the launch method for the 374 * appropriate file type in a different thread. 375 * 376 * @param file the JNLP file to launch 377 */ 378 public void launchBackground(JNLPFile file) { 379 BgRunner runner = new BgRunner(file, null); 380 new Thread(runner).start(); 381 } 382 383 /** 384 * Launches the JNLP file at the specified location in the 385 * background by calling the launch method for its file type. 386 * 387 * @param location the location of the JNLP file 388 */ 389 public void launchBackground(URL location) { 390 BgRunner runner = new BgRunner(null, location); 391 new Thread(runner).start(); 392 } 393 368 394 369 /** 395 370 * Launches the JNLP file in a new JVM instance. The launched … … 407 382 List<String> updatedArgs = new LinkedList<String>(javawsArgs); 408 383 409 if (file.getFileLocation() != null) 384 if (file.getFileLocation() != null) { 410 385 updatedArgs.add(file.getFileLocation().toString()); 411 else if (file.getSourceLocation() != null) 386 } 387 else if (file.getSourceLocation() != null) { 412 388 updatedArgs.add(file.getFileLocation().toString()); 413 else 389 } 390 else { 414 391 launchError(new LaunchException(file, null, R("LSFatal"), R("LCExternalLaunch"), R("LNullLocation"), R("LNullLocationInfo"))); 392 } 415 393 416 394 launchExternal(vmArgs, updatedArgs); … … 471 449 * Returns the JNLPFile for the URL, with error handling. 472 450 */ 473 private JNLPFile fromUrl(URL location , boolean fromSource) throws LaunchException {451 private JNLPFile fromUrl(URL location) throws LaunchException { 474 452 try { 475 JNLPFile file = null; 476 477 file = new JNLPFile(location, parserSettings.isStrict()); 478 479 if (fromSource) { 480 // Launches the jnlp file where this file originated. 481 if (file.getSourceLocation() != null) { 482 file = new JNLPFile(file.getSourceLocation(), parserSettings.isStrict()); 453 JNLPFile file = new JNLPFile(location, parserSettings); 454 455 boolean isLocal = false; 456 boolean haveHref = false; 457 if ("file".equalsIgnoreCase(location.getProtocol()) && new File(location.getFile()).exists()) { 458 isLocal = true; 459 } 460 if (file.getSourceLocation() != null) { 461 haveHref = true; 462 } 463 if (!isLocal && haveHref){ 464 //this is case when remote file have href to different file 465 if (!location.equals(file.getSourceLocation())){ 466 //mark local true, so the folowing condition will be true and 467 //new jnlp file will be downlaoded 468 isLocal = true; 469 //maybe this check is to strict, and will force redownlaod to often 470 //another check can be just on jnlp name. But it will not work 471 //if the href will be the file of same name, but on diferent path (or even domain) 483 472 } 473 } 474 475 if (isLocal && haveHref) { 476 file = new JNLPFile(file.getSourceLocation(), parserSettings); 484 477 } 485 478 return file; 486 479 } catch (Exception ex) { 487 if (ex instanceof LaunchException) 480 if (ex instanceof LaunchException) { 488 481 throw (LaunchException) ex; // already sent to handler when first thrown 489 else482 } else { 490 483 // IO and Parse 491 484 throw launchError(new LaunchException(null, ex, R("LSFatal"), R("LCReadError"), R("LCantRead"), R("LCantReadInfo"))); 492 } 493 } 494 495 /** 496 * Returns the JNLPFile for the URL, with error handling. 497 */ 498 @Deprecated 499 private JNLPFile toFile(URL location) throws LaunchException { 500 try { 501 JNLPFile file = null; 502 503 try { 504 file = new JNLPFile(location, (Version) null, true, updatePolicy); // strict 505 } catch (ParseException ex) { 506 file = new JNLPFile(location, (Version) null, false, updatePolicy); 507 508 // only here if strict failed but lax did not fail 509 LaunchException lex = 510 launchWarning(new LaunchException(file, ex, R("LSMinor"), R("LCFileFormat"), R("LNotToSpec"), R("LNotToSpecInfo"))); 511 512 if (lex != null) 513 throw lex; 514 } 515 516 return file; 517 } catch (Exception ex) { 518 if (ex instanceof LaunchException) 519 throw (LaunchException) ex; // already sent to handler when first thrown 520 else 521 // IO and Parse 522 throw launchError(new LaunchException(null, ex, R("LSFatal"), R("LCReadError"), R("LCantRead"), R("LCantReadInfo"))); 523 } 524 } 525 526 /** 485 } 486 } 487 } 488 489 /** 527 490 * Launches a JNLP application. This method should be called 528 491 * from a thread in the application's thread group. 529 492 */ 530 493 protected ApplicationInstance launchApplication(JNLPFile file) throws LaunchException { 531 if (!file.isApplication()) 494 if (!file.isApplication()) { 532 495 throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplication"), R("LNotApplicationInfo"))); 496 } 533 497 534 498 try { … … 537 501 ServiceUtil.checkExistingSingleInstance(file); 538 502 } catch (InstanceExistsException e) { 503 OutputController.getLogger().log("Single instance application is already running."); 539 504 return null; 540 505 } 541 506 542 507 if (JNLPRuntime.getForksAllowed() && file.needsNewVM()) { 508 if (!JNLPRuntime.isHeadless()){ 509 SplashScreen sp = SplashScreen.getSplashScreen(); 510 if (sp!=null) { 511 sp.close(); 512 } 513 } 543 514 List<String> netxArguments = new LinkedList<String>(); 544 515 netxArguments.add("-Xnofork"); … … 567 538 } 568 539 569 if (mainName == null) 540 if (mainName == null) { 570 541 throw launchError(new LaunchException(file, null, 571 542 R("LSFatal"), R("LCClient"), R("LCantDetermineMainClass"), 572 543 R("LCantDetermineMainClassInfo"))); 544 } 573 545 574 546 Class<?> mainClass = app.getClassLoader().loadClass(mainName); … … 579 551 SwingUtilities.invokeAndWait(new Runnable() { 580 552 // dummy method to force Event Dispatch Thread creation 553 @Override 581 554 public void run() { 582 555 } … … 589 562 main.setAccessible(true); 590 563 591 if (JNLPRuntime.isDebug()) { 592 System.out.println("Invoking main() with args: " + Arrays.toString(args)); 593 } 564 OutputController.getLogger().log("Invoking main() with args: " + Arrays.toString(args)); 594 565 main.invoke(null, new Object[] { args }); 595 566 … … 625 596 for (Thread thread : threads) { 626 597 if (thread != null) { 627 if (JNLPRuntime.isDebug()) { 628 System.err.println("Setting " + classLoader + " as the classloader for thread " + thread.getName()); 629 } 598 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Setting " + classLoader + " as the classloader for thread " + thread.getName()); 630 599 thread.setContextClassLoader(classLoader); 631 600 } … … 636 605 /** 637 606 * Launches a JNLP applet. This method should be called from a 638 * thread in the application's thread group. <p>639 * 607 * thread in the application's thread group. 608 * <p> 640 609 * The enableCodeBase parameter adds the applet's codebase to 641 610 * the locations searched for resources and classes. This can … … 644 613 * JNLP file. If the applet JNLP file does not specify any 645 614 * resources then the code base will be enabled regardless of 646 * the specified value.<p> 615 * the specified value. 616 * </p> 647 617 * 648 618 * @param file the JNLP file … … 650 620 */ 651 621 protected ApplicationInstance launchApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { 652 if (!file.isApplet()) 622 if (!file.isApplet()) { 653 623 throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo"))); 654 624 } 625 626 if (JNLPRuntime.getForksAllowed() && file.needsNewVM()) { 627 if (!JNLPRuntime.isHeadless()) { 628 SplashScreen sp = SplashScreen.getSplashScreen(); 629 if (sp != null) { 630 sp.close(); 631 } 632 } 633 } 634 if (handler != null) { 635 handler.launchInitialized(file); 636 } 637 638 AppletInstance applet = null; 655 639 try { 656 AppletInstance applet = createApplet(file, enableCodeBase, cont); 640 ServiceUtil.checkExistingSingleInstance(file); 641 applet = createApplet(file, enableCodeBase, cont); 657 642 applet.initialize(); 658 659 643 applet.getAppletEnvironment().startApplet(); // this should be a direct call to applet instance 660 644 return applet; 645 } catch (InstanceExistsException ieex) { 646 OutputController.getLogger().log("Single instance applet is already running."); 647 throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists")), applet); 661 648 } catch (LaunchException lex) { 662 throw launchError(lex );649 throw launchError(lex, applet); 663 650 } catch (Exception ex) { 664 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo"))); 651 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")), applet); 652 }finally{ 653 if (handler != null) { 654 handler.launchStarting(applet); 655 } 665 656 } 666 657 } … … 670 661 */ 671 662 protected ApplicationInstance getApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { 672 if (!file.isApplet()) 663 if (!file.isApplet()) { 673 664 throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo"))); 674 665 } 666 AppletInstance applet = null; 675 667 try { 676 AppletInstance applet = createApplet(file, enableCodeBase, cont); 668 ServiceUtil.checkExistingSingleInstance(file); 669 applet = createApplet(file, enableCodeBase, cont); 677 670 applet.initialize(); 678 671 return applet; 672 673 } catch (InstanceExistsException ieex) { 674 OutputController.getLogger().log("Single instance applet is already running."); 675 throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists")), applet); 679 676 } catch (LaunchException lex) { 680 throw launchError(lex );677 throw launchError(lex, applet); 681 678 } catch (Exception ex) { 682 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")) );679 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")), applet); 683 680 } 684 681 } … … 689 686 */ 690 687 protected ApplicationInstance launchInstaller(JNLPFile file) throws LaunchException { 688 // TODO Check for an existing single instance once implemented. 689 // ServiceUtil.checkExistingSingleInstance(file); 691 690 throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCNotSupported"), R("LNoInstallers"), R("LNoInstallersInfo"))); 692 691 } … … 697 696 * @param enableCodeBase whether to add the code base URL to the classloader 698 697 */ 699 protected AppletInstance createApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { 700 try { 701 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy); 698 //FIXME - when multiple applets are on one page, this method is visited simultaneously 699 //and then appelts creates in little bit strange manner. This issue is visible with 700 //randomly showing/notshowing spalshscreens. 701 //See also PluginAppletViewer.framePanel 702 protected AppletInstance createApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { 703 AppletInstance appletInstance = null; 704 try { 705 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy, enableCodeBase); 702 706 703 707 if (enableCodeBase) { … … 712 716 // services. This could potentially be done in applet constructor 713 717 // so initialize appletInstance before creating applet. 714 AppletInstance appletInstance;715 if (cont == null)716 appletInstance = new AppletInstance(file, group, loader, null);717 else718 appletInstance = new AppletInstance(file, group, loader, null, cont);718 if (cont == null) { 719 appletInstance = new AppletInstance(file, group, loader, null); 720 } else { 721 appletInstance = new AppletInstance(file, group, loader, null, cont); 722 } 719 723 720 724 loader.setApplication(appletInstance); … … 723 727 // appletInstance. 724 728 String appletName = file.getApplet().getMainClass(); 725 Class appletClass = loader.loadClass(appletName);729 Class<?> appletClass = loader.loadClass(appletName); 726 730 Applet applet = (Applet) appletClass.newInstance(); 731 applet.setStub((AppletStub)cont); 727 732 // Finish setting up appletInstance. 728 733 appletInstance.setApplet(applet); … … 733 738 return appletInstance; 734 739 } catch (Exception ex) { 735 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo")) );740 throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo")), appletInstance); 736 741 } 737 742 } … … 745 750 protected Applet createAppletObject(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { 746 751 try { 747 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy );752 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy, enableCodeBase); 748 753 749 754 if (enableCodeBase) { … … 754 759 755 760 String appletName = file.getApplet().getMainClass(); 756 Class appletClass = loader.loadClass(appletName);761 Class<?> appletClass = loader.loadClass(appletName); 757 762 Applet applet = (Applet) appletClass.newInstance(); 758 763 … … 768 773 protected ApplicationInstance createApplication(JNLPFile file) throws LaunchException { 769 774 try { 770 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy );775 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy, false); 771 776 ThreadGroup group = Thread.currentThread().getThreadGroup(); 772 777 … … 788 793 */ 789 794 protected ThreadGroup createThreadGroup(JNLPFile file) { 790 ThreadGroup tg = null;795 final ThreadGroup tg; 791 796 792 797 if (file instanceof PluginBridge) { … … 804 809 */ 805 810 private LaunchException launchError(LaunchException ex) { 806 if (handler != null) 811 return launchError(ex, null); 812 } 813 814 private LaunchException launchError(LaunchException ex, AppletInstance applet) { 815 if (applet != null) { 816 SplashUtils.showErrorCaught(ex, applet); 817 } 818 if (handler != null) { 807 819 handler.launchError(ex); 820 } 808 821 809 822 return ex; … … 818 831 */ 819 832 private LaunchException launchWarning(LaunchException ex) { 820 if (handler != null) 833 if (handler != null) { 821 834 if (!handler.launchWarning(ex)) 822 835 // no need to destroy the app b/c it hasn't started 823 return ex; // chose to abort 836 return ex; 837 } // chose to abort 824 838 825 839 return null; // chose to continue, or no handler … … 843 857 } 844 858 845 /**859 /** 846 860 * This runnable is used to call the appropriate launch method 847 861 * for the application, applet, or installer in its thread group. … … 872 886 } 873 887 888 @Override 874 889 public void run() { 875 890 try { 876 891 // Do not create new AppContext if we're using NetX and icedteaplugin. 877 892 // The plugin needs an AppContext too, but it has to be created earlier. 878 if (context && !isPlugin) 893 if (context && !isPlugin) { 879 894 SunToolkit.createNewAppContext(); 895 } 880 896 881 897 doPerApplicationAppContextHacks(); … … 886 902 application = getApplet(file, ((PluginBridge)file).codeBaseLookup(), cont); 887 903 } else { 888 if (file.isApplication()) 904 if (file.isApplication()) { 889 905 application = launchApplication(file); 890 else if (file.isApplet()) 891 application = launchApplet(file, true, cont); // enable applet code base 892 else if (file.isInstaller()) 906 } 907 else if (file.isApplet()) { 908 application = launchApplet(file, true, cont); 909 } // enable applet code base 910 else if (file.isInstaller()) { 893 911 application = launchInstaller(file); 894 else 912 } 913 else { 895 914 throw launchError(new LaunchException(file, null, 896 915 R("LSFatal"), R("LCClient"), R("LNotLaunchable"), 897 916 R("LNotLaunchableInfo"))); 917 } 898 918 } 899 919 } catch (LaunchException ex) { 900 ex.printStackTrace();920 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 901 921 exception = ex; 902 922 // Exit if we can't launch the application. 903 if (exitOnFailure) 904 System.exit(1); 923 if (exitOnFailure) { 924 JNLPRuntime.exit(1); 925 } 926 } catch (Throwable ex) { 927 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 928 throw new RuntimeException(ex); 905 929 } 906 930 } … … 916 940 }; 917 941 918 /**919 * This runnable is used by the <code>launchBackground</code>920 * methods to launch a JNLP file from a separate thread.921 */922 private class BgRunner implements Runnable {923 private JNLPFile file;924 private URL location;925 926 BgRunner(JNLPFile file, URL location) {927 this.file = file;928 this.location = location;929 }930 931 public void run() {932 try {933 if (file != null)934 launch(file);935 if (location != null)936 launch(location);937 } catch (LaunchException ex) {938 // launch method communicates error conditions to the939 // handler if it exists, otherwise we don't care because940 // there's nothing that can be done about the exception.941 }942 }943 };944 945 942 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/NetxPanel.java
r418 r429 1 1 /* 2 * Copyright 20 07Red Hat, Inc.2 * Copyright 2012 Red Hat, Inc. 3 3 * This file is part of IcedTea, http://icedtea.classpath.org 4 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. … … 23 23 package net.sourceforge.jnlp; 24 24 25 import net.sourceforge.jnlp.AppletLog;26 25 import net.sourceforge.jnlp.runtime.AppletInstance; 27 26 import net.sourceforge.jnlp.runtime.JNLPRuntime; … … 29 28 import java.net.URL; 30 29 import java.util.HashMap; 31 import java.util.Hashtable;32 30 import java.util.Map; 33 31 import java.util.concurrent.ConcurrentHashMap; 34 32 import java.util.concurrent.ConcurrentMap; 35 36 import sun.applet.AppletViewerPanel; 33 import net.sourceforge.jnlp.splashscreen.SplashController; 34 import net.sourceforge.jnlp.splashscreen.SplashPanel; 35 import net.sourceforge.jnlp.splashscreen.SplashUtils; 36 import net.sourceforge.jnlp.util.logging.OutputController; 37 38 import sun.applet.AppletViewerPanelAccess; 37 39 import sun.awt.SunToolkit; 38 40 39 41 /** 40 42 * This panel calls into netx to run an applet, and pipes the display 41 * into a panel from gcjwebplugin.42 * 43 * @author Francis Kung <fkung@redhat.com>43 * into a panel from the icedtea-web browser plugin. 44 * 45 * @author Francis Kung <fkung@redhat.com> 44 46 */ 45 public class NetxPanel extends AppletViewerPanel { 47 public class NetxPanel extends AppletViewerPanelAccess implements SplashController { 48 private final PluginParameters parameters; 46 49 private PluginBridge bridge = null; 47 private boolean exitOnFailure = true;48 50 private AppletInstance appInst = null; 49 private boolean appletAlive;50 private final String uKey;51 private SplashController splashController; 52 private volatile boolean initialized; 51 53 52 54 // We use this so that we can create exactly one thread group … … 66 68 new ConcurrentHashMap<String, Boolean>(); 67 69 68 public NetxPanel(URL documentURL, Hashtable<String, String> atts) { 69 super(documentURL, atts); 70 71 /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html, 72 * classloaders are shared iff these properties match: 73 * codebase, cache_archive, java_archive, archive 74 * 75 * To achieve this, we create the uniquekey based on those 4 values, 76 * always in the same order. The initial "<NAME>=" parts ensure a 77 * bad tag cannot trick the loader into getting shared with another. 78 */ 79 80 // Firefox sometimes skips the codebase if it is default -- ".", 81 // so set it that way if absent 82 String codebaseAttr = atts.get("codebase") != null ? 83 atts.get("codebase") : "."; 84 85 String cache_archiveAttr = atts.get("cache_archive") != null ? 86 atts.get("cache_archive") : ""; 87 88 String java_archiveAttr = atts.get("java_archive") != null ? 89 atts.get("java_archive") : ""; 90 91 String archiveAttr = atts.get("archive") != null ? 92 atts.get("archive") : ""; 93 94 this.uKey = "codebase=" + codebaseAttr + 95 "cache_archive=" + cache_archiveAttr + 96 "java_archive=" + java_archiveAttr + 97 "archive=" + archiveAttr; 98 99 // when this was being done (incorrectly) in Launcher, the call was 100 // new AppThreadGroup(mainGroup, file.getTitle()); 70 public NetxPanel(URL documentURL, PluginParameters params) { 71 super(documentURL, params.getUnderlyingHashtable()); 72 73 this.parameters = params; 74 this.initialized = false; 75 76 String uniqueKey = params.getUniqueKey(getCodeBase()); 101 77 synchronized(TGMapMutex) { 102 if (!uKeyToTG.containsKey( this.uKey)) {103 ThreadGroup tg = new ThreadGroup(Launcher.mainGroup, this. documentURL.toString());104 uKeyToTG.put( this.uKey, tg);78 if (!uKeyToTG.containsKey(uniqueKey)) { 79 ThreadGroup tg = new ThreadGroup(Launcher.mainGroup, this.getDocumentURL().toString()); 80 uKeyToTG.put(uniqueKey, tg); 105 81 } 106 82 } 107 }108 109 // overloaded constructor, called when initialized via plugin110 public NetxPanel(URL documentURL, Hashtable<String, String> atts,111 boolean exitOnFailure) {112 this(documentURL, atts);113 this.exitOnFailure = exitOnFailure;114 this.appletAlive = true;115 83 } 116 84 … … 121 89 * and stopping the applet. 122 90 */ 123 AppletLog.log(t);91 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, t); //new logger 124 92 super.showAppletException(t); 125 93 } … … 127 95 //Overriding to use Netx classloader. You might need to relax visibility 128 96 //in sun.applet.AppletPanel for runLoader(). 129 protected void runLoader() { 97 @Override 98 protected void ourRunLoader() { 130 99 131 100 try { 132 bridge = new PluginBridge( baseURL,101 bridge = new PluginBridge(getBaseURL(), 133 102 getDocumentBase(), 134 103 getJarFiles(), … … 136 105 getWidth(), 137 106 getHeight(), 138 atts, uKey);107 parameters); 139 108 140 109 doInit = true; … … 142 111 status = APPLET_LOAD; 143 112 144 Launcher l = new Launcher(exitOnFailure); 145 146 try { 147 appInst = (AppletInstance) l.launch(bridge, this); 148 } catch (LaunchException e) { 149 // Assume user has indicated he does not trust the 150 // applet. 151 if (exitOnFailure) 152 System.exit(1); 153 } 154 applet = appInst.getApplet(); 155 156 //On the other hand, if you create an applet this way, it'll work 157 //fine. Note that you might to open visibility in sun.applet.AppletPanel 158 //for this to work (the loader field, and getClassLoader). 159 //loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); 160 //applet = createApplet(loader); 161 162 // This shows that when using NetX's JNLPClassLoader, keyboard input 163 // won't make it to the applet, whereas using sun.applet.AppletClassLoader 164 // works just fine. 165 166 dispatchAppletEvent(APPLET_LOADING_COMPLETED, null); 167 168 if (applet != null) { 113 Launcher l = new Launcher(false); 114 115 // May throw LaunchException: 116 appInst = (AppletInstance) l.launch(bridge, this); 117 setApplet(appInst.getApplet()); 118 119 if (getApplet() != null) { 169 120 // Stick it in the frame 170 applet.setStub(this);171 applet.setVisible(false);172 add("Center", applet);121 getApplet().setStub(this); 122 getApplet().setVisible(false); 123 add("Center", getApplet()); 173 124 showAppletStatus("loaded"); 174 125 validate(); 175 126 } 176 127 } catch (Exception e) { 177 this.appletAlive = false; 178 e.printStackTrace(); 128 status = APPLET_ERROR; 129 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 130 replaceSplash(SplashUtils.getErrorSplashScreen(getWidth(), getHeight(), e)); 131 } finally { 132 // PR1157: This needs to occur even in the case of an exception 133 // so that the applet's event listeners are signaled. 134 // Once PluginAppletViewer.AppletEventListener is signaled PluginAppletViewer can properly stop waiting 135 // in PluginAppletViewer.waitForAppletInit 136 this.initialized = true; 137 dispatchAppletEvent(APPLET_LOADING_COMPLETED, null); 179 138 } 180 139 } … … 185 144 */ 186 145 // Reminder: Relax visibility in sun.applet.AppletPanel 146 @Override 187 147 protected synchronized void createAppletThread() { 188 148 // initialize JNLPRuntime in the main threadgroup … … 190 150 //The custom NetX Policy and SecurityManager are set here. 191 151 if (!JNLPRuntime.isInitialized()) { 192 if (JNLPRuntime.isDebug()) 193 System.out.println("initializing JNLPRuntime..."); 152 OutputController.getLogger().log("initializing JNLPRuntime..."); 194 153 195 154 JNLPRuntime.initialize(false); 196 155 } else { 197 if (JNLPRuntime.isDebug()) 198 System.out.println("JNLPRuntime already initialized"); 156 OutputController.getLogger().log("JNLPRuntime already initialized"); 199 157 } 200 158 } 201 159 202 handler = new Thread(getThreadGroup(), this );160 handler = new Thread(getThreadGroup(), this, "NetxPanelThread@" + this.getDocumentURL()); 203 161 handler.start(); 204 162 } 205 163 206 164 public void updateSizeInAtts(int height, int width) { 207 this.atts.put("height", Integer.toString(height)); 208 this.atts.put("width", Integer.toString(width)); 165 parameters.updateSize(width, height); 209 166 } 210 167 … … 213 170 } 214 171 215 public boolean is Alive() {216 return handler != null && handler.isAlive() && this.appletAlive;172 public boolean isInitialized() { 173 return initialized; 217 174 } 218 175 219 176 public ThreadGroup getThreadGroup() { 220 177 synchronized(TGMapMutex) { 221 return uKeyToTG.get( uKey);178 return uKeyToTG.get(parameters.getUniqueKey(getCodeBase())); 222 179 } 223 180 } … … 229 186 // only create a new context if one hasn't already been created for the 230 187 // applets with this unique key. 231 if (null == appContextCreated.putIfAbsent( uKey, Boolean.TRUE)) {188 if (null == appContextCreated.putIfAbsent(parameters.getUniqueKey(getCodeBase()), Boolean.TRUE)) { 232 189 SunToolkit.createNewAppContext(); 233 190 } 234 191 } 192 193 public void setAppletViewerFrame(SplashController framePanel) { 194 splashController=framePanel; 195 } 196 197 @Override 198 public void removeSplash() { 199 splashController.removeSplash(); 200 } 201 202 @Override 203 public void replaceSplash(SplashPanel r) { 204 splashController.replaceSplash(r); 205 } 206 207 @Override 208 public int getSplashWidth() { 209 return splashController.getSplashWidth(); 210 } 211 212 @Override 213 public int getSplashHeigth() { 214 return splashController.getSplashHeigth(); 215 } 216 235 217 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Node.java
r418 r429 1 /* Node.java 2 Copyright (C) 2011 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 1 38 package net.sourceforge.jnlp; 2 39 … … 27 64 28 65 Node getFirstChild() { 29 if (children == null) 66 if (children == null) { 30 67 getChildNodes(); 31 32 if (children.length == 0) 68 } 69 70 if (children.length == 0) { 33 71 return null; 34 else 72 } 73 else { 35 74 return children[0]; 75 } 36 76 } 37 77 … … 51 91 List<Node> list = new ArrayList<Node>(); 52 92 53 for (Enumeration e = xml.enumerateChildren(); e.hasMoreElements();) 54 list.add(new Node((XMLElement) e.nextElement())); 93 for (Enumeration<XMLElement> e = xml.enumerateChildren(); e.hasMoreElements();) { 94 list.add(new Node(e.nextElement())); 95 } 55 96 56 97 children = list.toArray(new Node[list.size()]); 57 98 58 for (int i = 0; i < children.length - 1; i++) 99 for (int i = 0; i < children.length - 1; i++) { 59 100 children[i].next = children[i + 1]; 101 } 60 102 } 61 103 … … 71 113 attributeNames= new ArrayList<String>(); 72 114 73 for (Enumeration e = xml.enumerateAttributeNames(); e.hasMoreElements();) 74 attributeNames.add(new String((String) e.nextElement())); 115 for (Enumeration<String> e = xml.enumerateAttributeNames(); e.hasMoreElements();) { 116 attributeNames.add(new String(e.nextElement())); 117 } 75 118 } 76 119 … … 83 126 84 127 String getNodeName() { 85 if (xml.getName() == null) 128 if (xml.getName() == null) { 86 129 return ""; 87 else 130 } 131 else { 88 132 return xml.getName(); 89 } 90 133 } 134 } 135 136 @Override 91 137 public String toString() { 92 138 return getNodeName(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ParseException.java
r348 r429 31 31 // element, parse position, etc. 32 32 33 /** the original exception */ 34 private Throwable cause = null; 35 33 36 34 /** 37 35 * Create a parse exception with the specified message. … … 46 44 */ 47 45 public ParseException(String message, Throwable cause) { 48 super(message); 49 50 // replace with setCause when no longer 1.3 compatible 51 this.cause = cause; 52 } 53 54 /** 55 * Return the cause of the launch exception or null if there 56 * is no cause exception. 57 */ 58 public Throwable getCause() { 59 return cause; 60 } 61 62 /** 63 * Print the stack trace and the cause exception (1.3 64 * compatible) 65 */ 66 public void printStackTrace(PrintStream stream) { 67 super.printStackTrace(stream); 68 69 if (cause != null) { 70 stream.println("Caused by: "); 71 cause.printStackTrace(stream); 72 } 73 } 74 75 /** 76 * Print the stack trace and the cause exception (1.3 77 * compatible) 78 */ 79 public void printStackTrace(PrintWriter stream) { 80 super.printStackTrace(stream); 81 82 if (cause != null) { 83 stream.println("Caused by: "); 84 cause.printStackTrace(stream); 85 } 86 } 46 super(message, cause); 47 } 87 48 88 49 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Parser.java
r418 r429 1 1 // Copyright (C) 2001-2003 Jon A. Maxwell (JAM) 2 // Copyright (C) 20 12Red Hat, Inc.2 // Copyright (C) 2009-2013 Red Hat, Inc. 3 3 // 4 4 // This library is free software; you can redistribute it and/or … … 21 21 22 22 import java.io.*; 23 import java.lang.reflect.InvocationTargetException; 24 import java.lang.reflect.Method; 23 25 import java.net.*; 24 26 import java.util.*; 25 //import javax.xml.parsers.*; // commented to use right Node 26 //import org.w3c.dom.*; // class for using Tiny XML | NanoXML 27 //import org.xml.sax.*; 28 //import gd.xml.tiny.*; 27 28 import net.sourceforge.jnlp.SecurityDesc.RequestedPermissionLevel; 29 29 import net.sourceforge.jnlp.UpdateDesc.Check; 30 30 import net.sourceforge.jnlp.UpdateDesc.Policy; 31 31 import net.sourceforge.jnlp.runtime.JNLPRuntime; 32 import net.sourceforge. nanoxml.*;32 import net.sourceforge.jnlp.util.logging.OutputController; 33 33 34 34 /** … … 61 61 } 62 62 public void warning(SAXParseException exception) { 63 System.err.println("XML parse warning:");64 exception.printStackTrace();63 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "XML parse warning:"); 64 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, exception); 65 65 } 66 66 }; … … 96 96 97 97 /** 98 * Create a parser for the JNLP file. 98 * Create a parser for the JNLP file. If the location 99 99 * parameters is not null it is used as the default codebase 100 100 * (does not override value of jnlp element's href 101 * attribute). <p>102 * 101 * attribute). 102 * <p> 103 103 * The root node may be normalized as a side effect of this 104 104 * constructor. 105 * 105 * </p> 106 106 * @param file the (uninitialized) file reference 107 107 * @param base if codebase is not specified, a default base for relative URLs 108 108 * @param root the root node 109 * @param strict whether to enforce strict compliance with the JNLP spec 110 * @param allowExtensions whether to allow extensions to the JNLP spec 111 * @throws ParseException if the JNLP file is invalid 112 */ 113 public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions) throws ParseException { 114 this(file, base, root, strict, allowExtensions, null); 115 } 116 117 /** 118 * Create a parser for the JNLP file. If the location 109 * @param settings the parser settings to use when parsing the JNLP file 110 * @throws ParseException if the JNLP file is invalid 111 */ 112 public Parser(JNLPFile file, URL base, Node root, ParserSettings settings) throws ParseException { 113 this(file, base, root, settings, null); 114 } 115 116 /** 117 * Create a parser for the JNLP file. If the location 119 118 * parameters is not null it is used as the default codebase 120 119 * (does not override value of jnlp element's href 121 * attribute). <p>122 * 120 * attribute). 121 * <p> 123 122 * The root node may be normalized as a side effect of this 124 123 * constructor. 125 * 124 * </p> 126 125 * @param file the (uninitialized) file reference 127 126 * @param base if codebase is not specified, a default base for relative URLs 128 127 * @param root the root node 129 * @param strict whether to enforce strict compliance with the JNLP spec 130 * @param allowExtensions whether to allow extensions to the JNLP spec 128 * @param settings the parser settings to use when parsing the JNLP file 131 129 * @param codebase codebase to use if we did not parse one from JNLP file. 132 130 * @throws ParseException if the JNLP file is invalid 133 131 */ 134 public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions, URL codebase) throws ParseException {132 public Parser(JNLPFile file, URL base, Node root, ParserSettings settings, URL codebase) throws ParseException { 135 133 this.file = file; 136 134 this.root = root; 137 this.strict = s trict;138 this.allowExtensions = allowExtensions;135 this.strict = settings.isStrict(); 136 this.allowExtensions = settings.isExtensionAllowed(); 139 137 140 138 // ensure it's a JNLP node … … 144 142 // JNLP tag information 145 143 this.spec = getVersion(root, "spec", "1.0+"); 146 this.codebase = addSlash(getURL(root, "codebase", base)); 147 if (this.codebase == null) // We only override it if it is not specified. 144 145 try { 146 this.codebase = addSlash(getURL(root, "codebase", base)); 147 } catch (ParseException e) { 148 //If parsing fails, continue by overriding the codebase with the one passed in 149 } 150 151 if (this.codebase == null) // Codebase is overwritten if codebase was not specified in file or if parsing of it failed 148 152 this.codebase = codebase; 153 149 154 this.base = (this.codebase != null) ? this.codebase : base; // if codebase not specified use default codebase 150 155 fileLocation = getURL(root, "href", this.base); … … 247 252 248 253 // ensure that there are at least one information section present 249 if (resources.length == 0 && !j2se) 254 if (resources.length == 0 && !j2se) { 250 255 throw new ParseException(R("PNoResources")); 251 256 } 252 257 // create objects from the resources sections 253 for (int i = 0; i < resources.length; i++) 258 for (int i = 0; i < resources.length; i++) { 254 259 result.add(getResourcesDesc(resources[i], j2se)); 255 260 } 256 261 return result; 257 262 } … … 299 304 // check for duplicate main entries 300 305 if (jar.isMain()) { 301 if (mainFlag == true) 302 if (strict) 306 if (mainFlag == true) { 307 if (strict) { 303 308 throw new ParseException(R("PTwoMains")); 309 } 310 } 304 311 mainFlag = true; 305 312 } … … 340 347 String initialHeap = getAttribute(node, "initial-heap-size", null); 341 348 String maxHeap = getAttribute(node, "max-heap-size", null); 342 List resources = getResources(node, true);349 List<ResourcesDesc> resources = getResources(node, true); 343 350 344 351 // require version attribute … … 436 443 */ 437 444 void checkForInformation() throws RequiredElementException { 438 if (JNLPRuntime.isDebug()) { 439 System.out.println("Homepage: " + file.getInformation().getHomepage()); 440 System.out.println("Description: " + file.getInformation().getDescription()); 441 } 445 OutputController.getLogger().log("Homepage: " + file.getInformation().getHomepage()); 446 OutputController.getLogger().log("Description: " + file.getInformation().getDescription()); 442 447 443 448 String title = file.getTitle(); … … 446 451 if (title == null || title.trim().isEmpty()) 447 452 throw new MissingTitleException(); 448 else if (JNLPRuntime.isDebug()) 449 System.out.println("Acceptable title tag found, contains: " + title); 453 else OutputController.getLogger().log("Acceptable title tag found, contains: " + title); 450 454 451 455 if (vendor == null || vendor.trim().isEmpty()) 452 456 throw new MissingVendorException(); 453 else if (JNLPRuntime.isDebug()) 454 System.out.println("Acceptable vendor tag found, contains: " + vendor); 457 else OutputController.getLogger().log("Acceptable vendor tag found, contains: " + vendor); 455 458 } 456 459 … … 492 495 493 496 // create information 494 InformationDesc info = new InformationDesc( file,locales);497 InformationDesc info = new InformationDesc(locales); 495 498 496 499 // step through the elements … … 594 597 595 598 Object type = SecurityDesc.SANDBOX_PERMISSIONS; 596 597 if (nodes.length == 0) 599 RequestedPermissionLevel requestedPermissionLevel = RequestedPermissionLevel.NONE; 600 601 if (nodes.length == 0) { 598 602 type = SecurityDesc.SANDBOX_PERMISSIONS; 599 else if (null != getChildNode(nodes[0], "all-permissions")) 603 requestedPermissionLevel = RequestedPermissionLevel.NONE; 604 } else if (null != getChildNode(nodes[0], "all-permissions")) { 600 605 type = SecurityDesc.ALL_PERMISSIONS; 601 else if (null != getChildNode(nodes[0], "j2ee-application-client-permissions")) 606 requestedPermissionLevel = RequestedPermissionLevel.ALL; 607 } else if (null != getChildNode(nodes[0], "j2ee-application-client-permissions")) { 602 608 type = SecurityDesc.J2EE_PERMISSIONS; 603 else if (strict) 609 requestedPermissionLevel = RequestedPermissionLevel.J2EE; 610 } else if (strict) { 604 611 throw new ParseException(R("PEmptySecurity")); 605 606 if (base != null) 607 return new SecurityDesc(file, type, base.getHost()); 608 else 609 return new SecurityDesc(file, type, null); 612 } 613 614 if (base != null) { 615 return new SecurityDesc(file, requestedPermissionLevel, type, base.getHost()); 616 } else { 617 return new SecurityDesc(file, requestedPermissionLevel, type, null); 618 } 610 619 } 611 620 … … 913 922 914 923 /** 915 * Returns a Localefrom a single locale.916 * 917 * @param locale the locale string924 * Returns a {@link Locale} from a single locale. 925 * 926 * @param localeStr the locale string 918 927 */ 919 928 public Locale getLocale(String localeStr) { … … 1047 1056 /** 1048 1057 * Returns a URL object from a href string relative to the 1049 * code base. 1058 * code base. If the href denotes a relative URL, it must 1050 1059 * reference a location that is a subdirectory of the 1051 * codebase. <p>1060 * codebase. 1052 1061 * 1053 1062 * @param node the node … … 1074 1083 1075 1084 // check for going above the codebase 1076 if (!result.toString().startsWith(base.toString()) )1077 if (strict) 1085 if (!result.toString().startsWith(base.toString()) && !base.toString().startsWith(result.toString())){ 1086 if (strict) { 1078 1087 throw new ParseException(R("PUrlNotInCodebase", node.getNodeName(), href, base)); 1079 1088 } 1089 } 1080 1090 return result; 1081 1091 } … … 1259 1269 * @throws ParseException if the JNLP file is invalid 1260 1270 */ 1261 public static Node getRootNode(InputStream input) throws ParseException { 1271 public static Node getRootNode(InputStream input, ParserSettings settings) throws ParseException { 1272 String className = null; 1273 if (settings.isMalformedXmlAllowed()) { 1274 className = "net.sourceforge.jnlp.MalformedXMLParser"; 1275 } else { 1276 className = "net.sourceforge.jnlp.XMLParser"; 1277 } 1278 1262 1279 try { 1263 /* SAX 1264 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 1265 factory.setValidating(false); 1266 factory.setNamespaceAware(true); 1267 DocumentBuilder builder = factory.newDocumentBuilder(); 1268 builder.setErrorHandler(errorHandler); 1269 1270 Document doc = builder.parse(input); 1271 return doc.getDocumentElement(); 1272 */ 1273 1274 /* TINY 1275 Node document = new Node(TinyParser.parseXML(input)); 1276 Node jnlpNode = getChildNode(document, "jnlp"); // skip comments 1277 */ 1278 1279 //A BufferedInputStream is used to allow marking and reseting 1280 //of a stream. 1281 BufferedInputStream bs = new BufferedInputStream(input); 1282 1283 /* NANO */ 1284 final XMLElement xml = new XMLElement(); 1285 final PipedInputStream pin = new PipedInputStream(); 1286 final PipedOutputStream pout = new PipedOutputStream(pin); 1287 final InputStreamReader isr = new InputStreamReader(bs, getEncoding(bs)); 1288 // Clean the jnlp xml file of all comments before passing 1289 // it to the parser. 1290 new Thread( 1291 new Runnable() { 1292 public void run() { 1293 (new XMLElement()).sanitizeInput(isr, pout); 1294 try { 1295 pout.close(); 1296 } catch (IOException ioe) { 1297 ioe.printStackTrace(); 1298 } 1299 } 1300 }).start(); 1301 xml.parseFromReader(new InputStreamReader(pin)); 1302 Node jnlpNode = new Node(xml); 1303 return jnlpNode; 1304 } catch (Exception ex) { 1305 throw new ParseException(R("PBadXML"), ex); 1306 } 1307 } 1308 1309 /** 1310 * Returns the name of the encoding used in this InputStream. 1311 * 1312 * @param input the InputStream 1313 * @return a String representation of encoding 1314 */ 1315 private static String getEncoding(InputStream input) throws IOException { 1316 //Fixme: This only recognizes UTF-8, UTF-16, and 1317 //UTF-32, which is enough to parse the prolog portion of xml to 1318 //find out the exact encoding (if it exists). The reason being 1319 //there could be other encodings, such as ISO 8859 which is 8-bits 1320 //but it supports latin characters. 1321 //So what needs to be done is to parse the prolog and retrieve 1322 //the exact encoding from it. 1323 1324 int[] s = new int[4]; 1325 String encoding = "UTF-8"; 1326 1327 //Determine what the first four bytes are and store 1328 //them into an int array. 1329 input.mark(4); 1330 for (int i = 0; i < 4; i++) { 1331 s[i] = input.read(); 1332 } 1333 input.reset(); 1334 1335 //Set the encoding base on what the first four bytes of the 1336 //inputstream turn out to be (following the information from 1337 //www.w3.org/TR/REC-xml/#sec-guessing). 1338 if (s[0] == 255) { 1339 if (s[1] == 254) { 1340 if (s[2] != 0 || s[3] != 0) { 1341 encoding = "UnicodeLittle"; 1342 } else { 1343 encoding = "X-UTF-32LE-BOM"; 1344 } 1345 } 1346 } else if (s[0] == 254 && s[1] == 255 && (s[2] != 0 || 1347 s[3] != 0)) { 1348 encoding = "UTF-16"; 1349 1350 } else if (s[0] == 0 && s[1] == 0 && s[2] == 254 && 1351 s[3] == 255) { 1352 encoding = "X-UTF-32BE-BOM"; 1353 1354 } else if (s[0] == 0 && s[1] == 0 && s[2] == 0 && 1355 s[3] == 60) { 1356 encoding = "UTF-32BE"; 1357 1358 } else if (s[0] == 60 && s[1] == 0 && s[2] == 0 && 1359 s[3] == 0) { 1360 encoding = "UTF-32LE"; 1361 1362 } else if (s[0] == 0 && s[1] == 60 && s[2] == 0 && 1363 s[3] == 63) { 1364 encoding = "UTF-16BE"; 1365 } else if (s[0] == 60 && s[1] == 0 && s[2] == 63 && 1366 s[3] == 0) { 1367 encoding = "UTF-16LE"; 1368 } 1369 1370 return encoding; 1280 Class<?> klass = null; 1281 try { 1282 klass = Class.forName(className); 1283 } catch (ClassNotFoundException e) { 1284 klass = Class.forName("net.sourceforge.jnlp.XMLParser"); 1285 } 1286 Object instance = klass.newInstance(); 1287 Method m = klass.getMethod("getRootNode", InputStream.class); 1288 1289 return (Node) m.invoke(instance, input); 1290 } catch (InvocationTargetException e) { 1291 if (e.getCause() instanceof ParseException) { 1292 throw (ParseException)(e.getCause()); 1293 } 1294 throw new ParseException(R("PBadXML"), e); 1295 } catch (Exception e) { 1296 throw new ParseException(R("PBadXML"), e); 1297 } 1371 1298 } 1372 1299 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ParserSettings.java
r348 r429 36 36 */ 37 37 38 package net.sourceforge.jnlp; 38 39 39 package net.sourceforge.jnlp; 40 import java.util.Arrays; 41 import java.util.List; 40 42 41 43 /** … … 46 48 public class ParserSettings { 47 49 50 private static ParserSettings globalParserSettings = new ParserSettings(); 51 48 52 private final boolean isStrict; 53 private final boolean extensionAllowed; 54 private final boolean malformedXmlAllowed; 49 55 56 /** Create a new ParserSettings with the defautl parser settings */ 50 57 public ParserSettings() { 51 isStrict = false;58 this(false, true, true); 52 59 } 53 60 54 public ParserSettings(boolean strict) { 55 isStrict = strict; 61 /** Create a new ParserSettings object */ 62 public ParserSettings(boolean strict, boolean extensionAllowed, boolean malformedXmlAllowed) { 63 this.isStrict = strict; 64 this.extensionAllowed = extensionAllowed; 65 this.malformedXmlAllowed = malformedXmlAllowed; 56 66 } 57 67 68 /** @return true if extensions to the spec are allowed */ 69 public boolean isExtensionAllowed() { 70 return extensionAllowed; 71 } 72 73 /** @return true if parsing malformed xml is allowed */ 74 public boolean isMalformedXmlAllowed() { 75 return malformedXmlAllowed; 76 } 77 78 /** @return true if strict parsing mode is to be used */ 58 79 public boolean isStrict() { 59 80 return isStrict; 60 81 } 82 83 /** 84 * Return the global parser settings in use. 85 */ 86 public static ParserSettings getGlobalParserSettings() { 87 return globalParserSettings; 88 } 89 90 /** 91 * Set the global ParserSettings to match the given settings. 92 */ 93 public static void setGlobalParserSettings(ParserSettings parserSettings) { 94 globalParserSettings = parserSettings; 95 } 96 97 /** 98 * Return the ParserSettings to be used according to arguments specified 99 * at boot on the command line. These settings are also stored so they 100 * can be retrieved at a later time. 101 */ 102 public static ParserSettings setGlobalParserSettingsFromArgs(String[] cmdArgs) { 103 List<String> argList = Arrays.asList(cmdArgs); 104 boolean strict = argList.contains("-strict"); 105 boolean malformedXmlAllowed = !argList.contains("-xml"); 106 107 globalParserSettings = new ParserSettings(strict, true, malformedXmlAllowed); 108 return globalParserSettings; 109 } 110 61 111 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/PluginBridge.java
r418 r429 23 23 package net.sourceforge.jnlp; 24 24 25 import java.io.ByteArrayInputStream; 25 26 import java.io.File; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.net.MalformedURLException; 26 30 import java.net.URL; 27 import java.net.MalformedURLException; 31 import java.util.ArrayList; 32 import java.util.Arrays; 28 33 import java.util.HashSet; 34 import java.util.List; 29 35 import java.util.Locale; 30 import java.util.List;31 import java.util.ArrayList;32 36 import java.util.Map; 33 37 import java.util.Set; 34 38 39 import net.sourceforge.jnlp.SecurityDesc.RequestedPermissionLevel; 35 40 import net.sourceforge.jnlp.runtime.JNLPRuntime; 41 import net.sourceforge.jnlp.util.logging.OutputController; 42 import net.sourceforge.jnlp.util.replacements.BASE64Decoder; 36 43 37 44 /** … … 41 48 public class PluginBridge extends JNLPFile { 42 49 43 private String name;50 private PluginParameters params; 44 51 private Set<String> jars = new HashSet<String>(); 52 private List<ExtensionDesc> extensionJars = new ArrayList<ExtensionDesc>(); 45 53 //Folders can be added to the code-base through the archive tag 46 54 private List<String> codeBaseFolders = new ArrayList<String>(); 47 55 private String[] cacheJars = new String[0]; 48 56 private String[] cacheExJars = new String[0]; 49 private Map<String, String> atts;50 57 private boolean usePack; 51 58 private boolean useVersion; 52 private boolean codeBaseLookup;53 59 private boolean useJNLPHref; 54 60 … … 57 63 */ 58 64 public PluginBridge(URL codebase, URL documentBase, String jar, String main, 59 int width, int height, Map<String, String> atts, 60 String uKey) 65 int width, int height, PluginParameters params) 61 66 throws Exception { 62 this(codebase, documentBase, jar, main, width, height, atts, uKey, new JNLPCreator());67 this(codebase, documentBase, jar, main, width, height, params, new JNLPCreator()); 63 68 } 64 69 … … 82 87 83 88 public PluginBridge(URL codebase, URL documentBase, String archive, String main, 84 int width, int height, Map<String, String> atts, 85 String uKey, JNLPCreator jnlpCreator) 89 int width, int height, PluginParameters params, JNLPCreator jnlpCreator) 86 90 throws Exception { 87 91 specVersion = new Version("1.0"); … … 89 93 this.codeBase = codebase; 90 94 this.sourceLocation = documentBase; 91 this.atts = atts; 92 93 if (atts.containsKey("jnlp_href")) { 95 this.params = params; 96 this.parserSettings = ParserSettings.getGlobalParserSettings(); 97 98 if (params.getJNLPHref() != null) { 94 99 useJNLPHref = true; 95 100 try { 96 101 // Use codeBase as the context for the URL. If jnlp_href's 97 102 // value is a complete URL, it will replace codeBase's context. 98 URL jnlp = new URL(codeBase, atts.get("jnlp_href")); 99 JNLPFile jnlpFile = jnlpCreator.create(jnlp, null, false, JNLPRuntime.getDefaultUpdatePolicy(), codeBase); 103 ParserSettings defaultSettings = new ParserSettings(); 104 URL jnlp = new URL(codeBase, params.getJNLPHref()); 105 if (fileLocation == null){ 106 fileLocation = jnlp; 107 } 108 JNLPFile jnlpFile = null; 109 110 if (params.getJNLPEmbedded() != null) { 111 InputStream jnlpInputStream = new ByteArrayInputStream(decodeBase64String(params.getJNLPEmbedded())); 112 jnlpFile = new JNLPFile(jnlpInputStream, codeBase, defaultSettings); 113 } else { 114 jnlpFile = jnlpCreator.create(jnlp, null, defaultSettings, JNLPRuntime.getDefaultUpdatePolicy(), codeBase); 115 } 116 117 if (jnlpFile.isApplet()) 118 main = jnlpFile.getApplet().getMainClass(); 119 100 120 Map<String, String> jnlpParams = jnlpFile.getApplet().getParameters(); 101 121 info = jnlpFile.info; … … 103 123 // Change the parameter name to lowercase to follow conventions. 104 124 for (Map.Entry<String, String> entry : jnlpParams.entrySet()) { 105 this. atts.put(entry.getKey().toLowerCase(), entry.getValue());125 this.params.put(entry.getKey().toLowerCase(), entry.getValue()); 106 126 } 107 127 JARDesc[] jarDescs = jnlpFile.getResources().getJARs(); … … 110 130 this.jars.add(fileName); 111 131 } 132 133 // Store any extensions listed in the JNLP file to be returned later on, namely in getResources() 134 extensionJars = Arrays.asList(jnlpFile.getResources().getExtensions()); 112 135 } catch (MalformedURLException e) { 113 136 // Don't fail because we cannot get the jnlp file. Parameters are optional not required. 114 137 // it is the site developer who should ensure that file exist. 115 System.err.println("Unable to get JNLP file at: " + atts.get("jnlp_href")138 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to get JNLP file at: " + params.getJNLPHref() 116 139 + " with context of URL as: " + codeBase.toExternalForm()); 117 140 } … … 123 146 124 147 // also, see if cache_archive is specified 125 String cacheArchive = atts.get("cache_archive");126 if ( cacheArchive != null && cacheArchive.length() > 0) {148 String cacheArchive = params.getCacheArchive(); 149 if (!cacheArchive.isEmpty()) { 127 150 128 151 String[] versions = new String[0]; 129 152 130 153 // are there accompanying versions? 131 String cacheVersion = atts.get("cache_version");132 if ( cacheVersion != null) {154 String cacheVersion = params.getCacheVersion(); 155 if (!cacheVersion.isEmpty()) { 133 156 versions = cacheVersion.split(","); 134 157 } … … 147 170 } 148 171 149 String cacheArchiveEx = atts.get("cache_archive_ex");150 if ( cacheArchiveEx != null && cacheArchiveEx.length() > 0) {172 String cacheArchiveEx = params.getCacheArchiveEx(); 173 if (!cacheArchiveEx.isEmpty()) { 151 174 cacheExJars = cacheArchiveEx.split(","); 152 175 } … … 157 180 addArchiveEntries(archives); 158 181 159 if (JNLPRuntime.isDebug()) { 160 System.err.println("Jar string: " + archive); 161 System.err.println("jars length: " + archives.length); 162 } 163 } 164 165 name = atts.get("name"); 166 if (name == null) 167 name = "Applet"; 168 else 169 name = name + " applet"; 182 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Jar string: " + archive); 183 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "jars length: " + archives.length); 184 } 170 185 171 186 if (main.endsWith(".class")) … … 174 189 // the class name should be of the form foo.bar.Baz not foo/bar/Baz 175 190 String mainClass = main.replace('/', '.'); 176 launchType = new AppletDesc( name, mainClass, documentBase, width,177 height, atts);191 launchType = new AppletDesc(getTitle(), mainClass, documentBase, width, 192 height, params.getUnmodifiableMap()); 178 193 179 194 if (main.endsWith(".class")) //single class file only … … 183 198 security = null; 184 199 185 this.uniqueKey = uKey;200 this.uniqueKey = params.getUniqueKey(codebase); 186 201 usePack = false; 187 202 useVersion = false; 188 String jargs = atts.get("java_arguments");189 if ( jargs != null) {203 String jargs = params.getJavaArguments(); 204 if (!jargs.isEmpty()) { 190 205 for (String s : jargs.split(" ")) { 191 206 String[] parts = s.trim().split("="); … … 199 214 } 200 215 } 201 String cbl = atts.get("codebase_lookup"); 202 codeBaseLookup = cbl == null || (Boolean.valueOf(cbl)); 216 } 217 218 public List<String> getArchiveJars() { 219 return new ArrayList<String>(jars); 203 220 } 204 221 205 222 public boolean codeBaseLookup() { 206 return codeBaseLookup;223 return params.useCodebaseLookup(); 207 224 } 208 225 … … 211 228 } 212 229 213 /**214 * {@inheritdoc }215 */216 230 @Override 217 public DownloadOptions getDownloadOptionsForJar(JARDesc jar) { 231 public RequestedPermissionLevel getRequestedPermissionLevel() { 232 final String level = params.getPermissions(); 233 if (level == null) { 234 return RequestedPermissionLevel.NONE; 235 } else if (level.equals(SecurityDesc.RequestedPermissionLevel.DEFAULT.toHtmlString())) { 236 return RequestedPermissionLevel.NONE; 237 } else if (level.equals(SecurityDesc.RequestedPermissionLevel.SANDBOX.toHtmlString())) { 238 return RequestedPermissionLevel.SANDBOX; 239 } else if (level.equals(SecurityDesc.RequestedPermissionLevel.ALL.toHtmlString())) { 240 return RequestedPermissionLevel.ALL; 241 } else { 242 return RequestedPermissionLevel.NONE; 243 } 244 } 245 246 /** 247 * {@inheritDoc } 248 */ 249 @Override 250 public DownloadOptions getDownloadOptions() { 218 251 return new DownloadOptions(usePack, useVersion); 219 252 } 220 253 254 @Override 221 255 public String getTitle() { 222 return name; 256 String inManifestTitle = super.getTitleFromManifest(); 257 if (inManifestTitle != null) { 258 return inManifestTitle; 259 } 260 //specification is recommending main class instead of html parameter 261 //http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/manifest.html#app_name 262 String mainClass = getManifestsAttributes().getMainClass(); 263 if (mainClass != null) { 264 return mainClass; 265 } 266 return params.getAppletTitle(); 223 267 } 224 268 … … 243 287 244 288 boolean cacheable = true; 245 246 String cacheOption = atts.get("cache_option"); 247 if (cacheOption != null && cacheOption.equalsIgnoreCase("no")) 289 if (params.getCacheOption().equalsIgnoreCase("no")) 248 290 cacheable = false; 249 291 … … 302 344 } catch (MalformedURLException ex) { /* Ignored */ 303 345 } 346 } else if (launchType.equals(ExtensionDesc.class)) { 347 // We hope this is a safe list of JarDesc objects 348 @SuppressWarnings("unchecked") 349 List<T> castList = (List<T>) extensionJars; // this list is populated when the PluginBridge is first constructed 350 return castList; 304 351 } 305 352 return sharedResources.getResources(launchType); … … 350 397 return false; 351 398 } 399 400 /** 401 * Returns the decoded BASE64 string 402 */ 403 static byte[] decodeBase64String(String encodedString) throws IOException { 404 BASE64Decoder base64 = new BASE64Decoder(); 405 return base64.decodeBuffer(encodedString); 406 } 352 407 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ResourcesDesc.java
r418 r429 20 20 21 21 /** 22 * The resources element. <p>22 * The resources element. 23 23 * 24 24 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 68 68 } 69 69 70 public static JARDesc getMainJAR(JARDesc jars[] ) { 71 return getMainJAR(Arrays.asList(jars)); 72 } 73 74 public static JARDesc getMainJAR(List<JARDesc> jars) { 75 for (JARDesc jar : jars) { 76 if (jar.isMain()) { 77 return jar; 78 } 79 } 80 81 if (jars.size() > 0) { 82 return jars.get(0); 83 } else { 84 return null; 85 } 86 } 70 87 /** 71 88 * Returns the main JAR for these resources. There first JAR … … 74 91 */ 75 92 public JARDesc getMainJAR() { 76 JARDesc jars[] = getJARs(); 77 78 for (JARDesc jar : jars) { 79 if (jar.isMain()) 80 return jar; 81 } 82 83 if (jars.length > 0) 84 return jars[0]; 85 else 86 return null; 93 return getMainJAR(getJARs()); 87 94 } 88 95 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/SecurityDesc.java
r418 r429 17 17 package net.sourceforge.jnlp; 18 18 19 import java.io.*;20 import java.net.*;21 import java.util.*;22 import java.security.*;23 19 import java.awt.AWTPermission; 20 import java.io.FilePermission; 21 import java.lang.reflect.Constructor; 22 import java.lang.reflect.InvocationTargetException; 23 import java.net.SocketPermission; 24 import java.net.URI; 25 import java.net.URISyntaxException; 26 import java.security.AllPermission; 27 import java.security.CodeSource; 28 import java.security.Permission; 29 import java.security.PermissionCollection; 30 import java.security.Permissions; 31 import java.security.Policy; 32 import java.security.URIParameter; 33 import java.util.Collection; 34 import java.util.Collections; 35 import java.util.HashSet; 36 import java.util.PropertyPermission; 37 import java.util.Set; 24 38 25 39 import net.sourceforge.jnlp.config.DeploymentConfiguration; 26 40 import net.sourceforge.jnlp.runtime.JNLPRuntime; 41 import net.sourceforge.jnlp.util.logging.OutputController; 27 42 28 43 /** … … 34 49 public class SecurityDesc { 35 50 51 /** 52 * Represents the security level requested by an applet/application, as specified in its JNLP or HTML. 53 */ 54 public enum RequestedPermissionLevel { 55 NONE(null, null), 56 DEFAULT(null, "default"), 57 SANDBOX(null, "sandbox"), 58 J2EE("j2ee-application-client-permissions", null), 59 ALL("all-permissions", "all-permissions"); 60 61 public static final String PERMISSIONS_NAME = "permissions"; 62 private final String jnlpString, htmlString; 63 64 private RequestedPermissionLevel(final String jnlpString, final String htmlString) { 65 this.jnlpString = jnlpString; 66 this.htmlString = htmlString; 67 } 68 69 /** 70 * This permission level, as it would appear requested in a JNLP file. null if this level 71 * is NONE (unspecified) or cannot be requested in a JNLP file. 72 * @return the String level 73 */ 74 public String toJnlpString() { 75 return this.jnlpString; 76 } 77 78 /** 79 * This permission level, as it would appear requested in an HTML file. null if this level 80 * is NONE (unspecified) or cannot be requested in an HTML file. 81 * @return the String level 82 */ 83 public String toHtmlString() { 84 return this.htmlString; 85 } 86 87 /** 88 * The JNLP permission level corresponding to the given String. If null is given, null comes 89 * back. If there is no permission level that can be granted in JNLP matching the given String, 90 * null is also returned. 91 * @param jnlpString the JNLP permission String 92 * @return the matching RequestedPermissionLevel 93 */ 94 public RequestedPermissionLevel fromJnlpString(final String jnlpString) { 95 for (final RequestedPermissionLevel level : RequestedPermissionLevel.values()) { 96 if (level.jnlpString != null && level.jnlpString.equals(jnlpString)) { 97 return level; 98 } 99 } 100 return null; 101 } 102 103 /** 104 * The HTML permission level corresponding to the given String. If null is given, null comes 105 * back. If there is no permission level that can be granted in HTML matching the given String, 106 * null is also returned. 107 * @param htmlString the JNLP permission String 108 * @return the matching RequestedPermissionLevel 109 */ 110 public RequestedPermissionLevel fromHtmlString(final String htmlString) { 111 for (final RequestedPermissionLevel level : RequestedPermissionLevel.values()) { 112 if (level.htmlString != null && level.htmlString.equals(htmlString)) { 113 return level; 114 } 115 } 116 return null; 117 } 118 } 119 36 120 /* 37 121 * We do not verify security here, the classloader deals with security … … 47 131 public static final Object J2EE_PERMISSIONS = "J2SE"; 48 132 133 /** requested permissions type according to HTML or JNLP */ 134 private final RequestedPermissionLevel requestedPermissionLevel; 135 49 136 /** permissions type */ 50 137 private Object type; … … 57 144 58 145 /** the JNLP file */ 59 private JNLPFile file;146 private final JNLPFile file; 60 147 61 148 private final Policy customTrustedPolicy; 149 150 /** 151 * URLPermission is new in Java 8, so we use reflection to check for it to keep compatibility 152 * with Java 6/7. If we can't find the class or fail to construct it then we continue as usual 153 * without. 154 * 155 * These are saved as fields so that the reflective lookup only needs to be performed once 156 * when the SecurityDesc is constructed, rather than every time a call is made to 157 * {@link SecurityDesc#getSandBoxPermissions()}, which is called frequently. 158 */ 159 private static Class<Permission> urlPermissionClass = null; 160 private static Constructor<Permission> urlPermissionConstructor = null; 161 162 static { 163 try { 164 urlPermissionClass = (Class<Permission>) Class.forName("java.net.URLPermission"); 165 urlPermissionConstructor = urlPermissionClass.getDeclaredConstructor(new Class[] { String.class }); 166 } catch (final SecurityException e) { 167 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while reflectively finding URLPermission - host is probably not running Java 8+"); 168 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 169 urlPermissionClass = null; 170 urlPermissionConstructor = null; 171 } catch (final ClassNotFoundException e) { 172 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while reflectively finding URLPermission - host is probably not running Java 8+"); 173 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 174 urlPermissionClass = null; 175 urlPermissionConstructor = null; 176 } catch (final NoSuchMethodException e) { 177 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while reflectively finding URLPermission - host is probably not running Java 8+"); 178 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 179 urlPermissionClass = null; 180 urlPermissionConstructor = null; 181 } 182 } 62 183 63 184 // We go by the rules here: … … 88 209 new SocketPermission("localhost:1024-", "listen"), 89 210 // new SocketPermission("<DownloadHost>", "connect, accept"), // added by code 211 new PropertyPermission("java.util.Arrays.useLegacyMergeSort", "read,write"), 90 212 new PropertyPermission("java.version", "read"), 91 213 new PropertyPermission("java.vendor", "read"), … … 146 268 * 147 269 * @param file the JNLP file 270 * @param requestedPermissionLevel the permission level specified in the JNLP 148 271 * @param type the type of security 149 272 * @param downloadHost the download host (can always connect to) 150 273 */ 151 public SecurityDesc(JNLPFile file, Object type, String downloadHost) { 274 public SecurityDesc(JNLPFile file, RequestedPermissionLevel requestedPermissionLevel, Object type, String downloadHost) { 275 if (file == null) { 276 throw new NullJnlpFileException(); 277 } 152 278 this.file = file; 279 this.requestedPermissionLevel = requestedPermissionLevel; 153 280 this.type = type; 154 281 this.downloadHost = downloadHost; … … 158 285 159 286 customTrustedPolicy = getCustomTrustedPolicy(); 287 } 288 289 /** 290 * Create a security descriptor. 291 * 292 * @param file the JNLP file 293 * @param type the type of security 294 * @param downloadHost the download host (can always connect to) 295 */ 296 public SecurityDesc(JNLPFile file, Object type, String downloadHost) { 297 this(file, RequestedPermissionLevel.NONE, type, downloadHost); 160 298 } 161 299 … … 178 316 policy = Policy.getInstance("JavaPolicy", new URIParameter(policyUri)); 179 317 } catch (Exception e) { 180 e.printStackTrace();318 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 181 319 } 182 320 } … … 222 360 223 361 /** 362 * @return the permission level requested in the JNLP 363 */ 364 public RequestedPermissionLevel getRequestedPermissionLevel() { 365 return requestedPermissionLevel; 366 } 367 368 /** 224 369 * Returns a PermissionCollection containing the sandbox permissions 225 370 */ 226 371 public PermissionCollection getSandBoxPermissions() { 227 228 Permissions permissions = new Permissions(); 372 final Permissions permissions = new Permissions(); 229 373 230 374 for (int i = 0; i < sandboxPermissions.length; i++) … … 234 378 permissions.add(new AWTPermission("showWindowWithoutWarningBanner")); 235 379 } 236 237 if (file.isApplication()) 238 for (int i = 0; i < jnlpRIAPermissions.length; i++) 239 permissions.add(jnlpRIAPermissions[i]); 380 if (JNLPRuntime.isWebstartApplication()) { 381 if (file == null) { 382 throw new NullJnlpFileException("Can not return sandbox permissions, file is null"); 383 } 384 if (file.isApplication()) { 385 for (int i = 0; i < jnlpRIAPermissions.length; i++) { 386 permissions.add(jnlpRIAPermissions[i]); 387 } 388 } 389 } 240 390 241 391 if (downloadHost != null && downloadHost.length() > 0) … … 243 393 "connect, accept")); 244 394 395 final Collection<Permission> urlPermissions = getUrlPermissions(); 396 for (final Permission permission : urlPermissions) { 397 permissions.add(permission); 398 } 399 245 400 return permissions; 246 401 } 247 402 403 private Set<Permission> getUrlPermissions() { 404 if (urlPermissionClass == null || urlPermissionConstructor == null) { 405 return Collections.emptySet(); 406 } 407 final Set<Permission> permissions = new HashSet<Permission>(); 408 for (final JARDesc jar : file.getResources().getJARs()) { 409 try { 410 // Allow applets all HTTP methods (ex POST, GET) with any request headers 411 // on resources anywhere recursively in or below the applet codebase, only on 412 // default ports and ports explicitly specified in resource locations 413 final URI resourceLocation = jar.getLocation().toURI().normalize(); 414 final URI host = getHost(resourceLocation); 415 final String hostUriString = host.toString(); 416 final String urlPermissionUrlString = appendRecursiveSubdirToCodebaseHostString(hostUriString); 417 final Permission p = urlPermissionConstructor.newInstance(urlPermissionUrlString); 418 permissions.add(p); 419 } catch (final URISyntaxException e) { 420 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Could not determine codebase host for resource at " + jar.getLocation() + " while generating URLPermissions"); 421 OutputController.getLogger().log(e); 422 } catch (final InvocationTargetException e) { 423 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 424 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 425 } catch (final InstantiationException e) { 426 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 427 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 428 } catch (final IllegalAccessException e) { 429 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 430 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 431 } 432 } 433 try { 434 final URI codebase = file.getCodeBase().toURI().normalize(); 435 final URI host = getHost(codebase); 436 final String codebaseHostUriString = host.toString(); 437 final String urlPermissionUrlString = appendRecursiveSubdirToCodebaseHostString(codebaseHostUriString); 438 final Permission p = urlPermissionConstructor.newInstance(urlPermissionUrlString); 439 permissions.add(p); 440 } catch (final URISyntaxException e) { 441 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Could not determine codebase host for codebase " + file.getCodeBase() + " while generating URLPermissions"); 442 OutputController.getLogger().log(e); 443 } catch (final InvocationTargetException e) { 444 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 445 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 446 } catch (final InstantiationException e) { 447 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 448 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 449 } catch (final IllegalAccessException e) { 450 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Exception while attempting to reflectively generate a URLPermission, probably not running on Java 8+?"); 451 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, e); 452 } 453 return permissions; 454 } 455 456 /** 457 * Gets the host domain part of an applet's codebase. Removes path, query, and fragment, but preserves scheme, 458 * user info, and host. The port used is overridden with the specified port. 459 * @param codebase the applet codebase URL 460 * @param port 461 * @return the host domain of the codebase 462 * @throws URISyntaxException 463 */ 464 static URI getHostWithSpecifiedPort(final URI codebase, final int port) throws URISyntaxException { 465 requireNonNull(codebase); 466 return new URI(codebase.getScheme(), codebase.getUserInfo(), codebase.getHost(), port, null, null, null); 467 } 468 469 /** 470 * Gets the host domain part of an applet's codebase. Removes path, query, and fragment, but preserves scheme, 471 * user info, host, and port. 472 * @param codebase the applet codebase URL 473 * @return the host domain of the codebase 474 * @throws URISyntaxException 475 */ 476 static URI getHost(final URI codebase) throws URISyntaxException { 477 requireNonNull(codebase); 478 return getHostWithSpecifiedPort(codebase, codebase.getPort()); 479 } 480 481 /** 482 * Appends a recursive access marker to a codebase host, for granting Java 8 URLPermissions which are no 483 * more restrictive than the existing SocketPermissions 484 * See http://docs.oracle.com/javase/8/docs/api/java/net/URLPermission.html 485 * @param codebaseHost the applet's codebase's host domain URL as a String. Expected to be formatted as eg 486 * "http://example.com:8080" or "http://example.com/" 487 * @return the resulting String eg "http://example.com:8080/- 488 */ 489 static String appendRecursiveSubdirToCodebaseHostString(final String codebaseHost) { 490 requireNonNull(codebaseHost); 491 String result = codebaseHost; 492 while (result.endsWith("/")) { 493 result = result.substring(0, result.length() - 1); 494 } 495 // See http://docs.oracle.com/javase/8/docs/api/java/net/URLPermission.html 496 result = result + "/-"; // allow access to any resources recursively on the host domain 497 return result; 498 } 499 500 private static void requireNonNull(final Object arg) { 501 if (arg == null) { 502 throw new NullPointerException(); 503 } 504 } 505 248 506 /** 249 507 * Returns all the names of the basic JNLP system properties accessible by RIAs -
trunk/icedtea-web/netx/net/sourceforge/jnlp/StreamEater.java
r348 r429 20 20 import java.io.IOException; 21 21 import java.io.InputStream; 22 import net.sourceforge.jnlp.util.logging.OutputController; 22 23 23 24 /** … … 33 34 public void run() { 34 35 try { 36 StringBuilder s = new StringBuilder(); 35 37 while (true) { 36 38 int c = stream.read(); 37 if (c == -1) 39 if (c == -1){ 40 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, s.toString()); 38 41 break; 39 40 System.out.write(c); 42 } else { 43 char ch = (char) c; 44 if (ch == '\n'){ 45 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, s.toString()); 46 s = new StringBuilder(); 47 }else { 48 s.append((char) c); 49 } 50 } 51 41 52 } 42 53 } catch (IOException ex) { -
trunk/icedtea-web/netx/net/sourceforge/jnlp/UpdateDesc.java
r348 r429 1 /* UpdateDesc.java 2 Copyright (C) 2010 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 1 38 package net.sourceforge.jnlp; 2 39 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Version.java
r418 r429 20 20 21 21 /** 22 * <p> 22 23 * A JNLP Version string in the form "1.2-3_abc" followed by an 23 24 * optional + (includes all later versions) or * (matches any 24 25 * suffixes on versions). More than one version can be included 25 * in a string by separating them with spaces.<p> 26 * 26 * in a string by separating them with spaces. 27 * </p> 28 * <p> 27 29 * Version strings are divided by "._-" charecters into parts. 28 30 * These parts are compared numerically if they can be parsed as … … 31 33 * the smaller one is padded with zero or the empty string. Note 32 34 * that the padding in this version means that 1.2+ matches 33 * 1.4.0-beta1, but may not in future versions.<p> 35 * 1.4.0-beta1, but may not in future versions. 36 * </p> 34 37 * 35 38 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 309 312 public String toString() { 310 313 return versionString; 311 } 312 313 /** 314 * Test. 315 */ 316 /* 317 public static void main(String args[]) { 318 Version jvms[] = { 319 new Version("1.1* 1.3*"), 320 new Version("1.2+"), 321 }; 322 323 Version versions[] = { 324 new Version("1.1"), 325 new Version("1.1.8"), 326 new Version("1.2"), 327 new Version("1.3"), 328 new Version("2.0"), 329 new Version("1.3.1"), 330 new Version("1.2.1"), 331 new Version("1.3.1-beta"), 332 new Version("1.1 1.2"), 333 new Version("1.2 1.3"), 334 }; 335 336 for (int j = 0; j < jvms.length; j++) { 337 for (int v = 0; v < versions.length; v++) { 338 System.out.print( jvms[j].toString() + " " ); 339 if (!jvms[j].matches(versions[v])) 340 System.out.print( "!" ); 341 System.out.println( "matches " + versions[v].toString() ); 342 } 343 } 344 345 System.out.println("Test completed"); 346 } 347 */ 314 } 348 315 349 316 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/browser/BrowserAwareProxySelector.java
r348 r429 41 41 import java.io.File; 42 42 import java.io.IOException; 43 import java.net.InetSocketAddress;44 43 import java.net.MalformedURLException; 45 44 import java.net.Proxy; 46 import java.net.SocketAddress;47 45 import java.net.URI; 48 46 import java.net.URL; 49 import java.net.Proxy.Type;50 47 import java.util.ArrayList; 51 48 import java.util.Arrays; … … 53 50 import java.util.Map; 54 51 52 import net.sourceforge.jnlp.config.DeploymentConfiguration; 55 53 import net.sourceforge.jnlp.runtime.JNLPProxySelector; 56 54 import net.sourceforge.jnlp.runtime.JNLPRuntime; 57 55 import net.sourceforge.jnlp.runtime.PacEvaluator; 58 56 import net.sourceforge.jnlp.runtime.PacEvaluatorFactory; 57 import net.sourceforge.jnlp.util.logging.OutputController; 59 58 60 59 /** … … 78 77 private int browserProxyType = BROWSER_PROXY_TYPE_NONE; 79 78 private URL browserAutoConfigUrl; 79 /** Whether the http proxy should be used for http, https, ftp and socket protocols */ 80 80 private Boolean browserUseSameProxy; 81 81 private String browserHttpProxyHost; … … 93 93 * Create a new instance of this class, reading configuration fropm the browser 94 94 */ 95 public BrowserAwareProxySelector() { 96 super(); 95 public BrowserAwareProxySelector(DeploymentConfiguration config) { 96 super(config); 97 } 98 99 public void initialize() { 97 100 try { 98 101 initFromBrowserConfig(); 99 102 } catch (IOException e) { 100 if (JNLPRuntime.isDebug()) { 101 e.printStackTrace(); 102 } 103 System.err.println(R("RProxyFirefoxNotFound")); 103 OutputController.getLogger().log(e); 104 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RProxyFirefoxNotFound")); 104 105 browserProxyType = PROXY_TYPE_NONE; 105 106 } … … 111 112 private void initFromBrowserConfig() throws IOException { 112 113 113 File preferencesFile = FirefoxPreferencesFinder.find(); 114 115 FirefoxPreferencesParser parser = new FirefoxPreferencesParser(preferencesFile); 116 parser.parse(); 117 Map<String, String> prefs = parser.getPreferences(); 114 Map<String, String> prefs = parseBrowserPreferences(); 118 115 119 116 String type = prefs.get("network.proxy.type"); … … 130 127 } 131 128 } catch (MalformedURLException e) { 132 e.printStackTrace();129 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 133 130 } 134 131 … … 147 144 browserFtpProxyHost = prefs.get("network.proxy.ftp"); 148 145 browserFtpProxyPort = stringToPort(prefs.get("network.proxy.ftp_port")); 149 browserSocks4ProxyHost = prefs.get("network ing.proxy.socks");146 browserSocks4ProxyHost = prefs.get("network.proxy.socks"); 150 147 browserSocks4ProxyPort = stringToPort(prefs.get("network.proxy.socks_port")); 148 } 149 150 Map<String, String> parseBrowserPreferences() throws IOException { 151 File preferencesFile = FirefoxPreferencesFinder.find(); 152 FirefoxPreferencesParser parser = new FirefoxPreferencesParser(preferencesFile); 153 parser.parse(); 154 return parser.getPreferences(); 151 155 } 152 156 … … 167 171 168 172 /** 173 * <p> 169 174 * The main entry point for {@link BrowserAwareProxySelector}. Based on 170 175 * the browser settings, determines proxy information for a given URI. 176 * </p> 171 177 * <p> 172 178 * The appropriate proxy may be determined by reading static information 173 179 * from the browser's preferences file, or it may be computed dynamically, 174 180 * by, for example, running javascript code. 181 * </p> 175 182 */ 176 183 @Override … … 209 216 optionDescription = "Unknown"; 210 217 } 211 if (JNLPRuntime.isDebug()) { 212 System.err.println(R("RProxyFirefoxOptionNotImplemented", browserProxyType, optionDescription)); 213 } 218 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG,R("RProxyFirefoxOptionNotImplemented", browserProxyType, optionDescription)); 214 219 proxies.add(Proxy.NO_PROXY); 215 220 } 216 221 217 if (JNLPRuntime.isDebug()) { 218 System.out.println("Browser selected proxies: " + proxies.toString()); 219 } 222 OutputController.getLogger().log("Browser selected proxies: " + proxies.toString()); 220 223 221 224 return proxies; … … 237 240 proxies.addAll(getProxiesFromPacResult(proxiesString)); 238 241 } catch (MalformedURLException e) { 239 e.printStackTrace();242 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 240 243 proxies.add(Proxy.NO_PROXY); 241 244 } … … 249 252 */ 250 253 private List<Proxy> getFromBrowserConfiguration(URI uri) { 251 List<Proxy> proxies = new ArrayList<Proxy>(); 252 253 String scheme = uri.getScheme(); 254 255 if (browserUseSameProxy) { 256 SocketAddress sa = new InetSocketAddress(browserHttpProxyHost, browserHttpProxyPort); 257 Proxy proxy; 258 if (scheme.equals("socket")) { 259 proxy = new Proxy(Type.SOCKS, sa); 260 } else { 261 proxy = new Proxy(Type.HTTP, sa); 262 } 263 proxies.add(proxy); 264 } else if (scheme.equals("http")) { 265 SocketAddress sa = new InetSocketAddress(browserHttpProxyHost, browserHttpProxyPort); 266 proxies.add(new Proxy(Type.HTTP, sa)); 267 } else if (scheme.equals("https")) { 268 SocketAddress sa = new InetSocketAddress(browserHttpsProxyHost, browserHttpsProxyPort); 269 proxies.add(new Proxy(Type.HTTP, sa)); 270 } else if (scheme.equals("ftp")) { 271 SocketAddress sa = new InetSocketAddress(browserFtpProxyHost, browserFtpProxyPort); 272 proxies.add(new Proxy(Type.HTTP, sa)); 273 } else if (scheme.equals("socket")) { 274 SocketAddress sa = new InetSocketAddress(browserSocks4ProxyHost, browserSocks4ProxyPort); 275 proxies.add(new Proxy(Type.SOCKS, sa)); 276 } else { 277 proxies.add(Proxy.NO_PROXY); 278 } 279 280 return proxies; 254 return getFromArguments(uri, browserUseSameProxy, true, 255 browserHttpsProxyHost, browserHttpsProxyPort, 256 browserHttpProxyHost, browserHttpProxyPort, 257 browserFtpProxyHost, browserFtpProxyPort, 258 browserSocks4ProxyHost, browserSocks4ProxyPort); 281 259 } 282 260 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesFinder.java
r398 r429 48 48 import net.sourceforge.jnlp.runtime.JNLPRuntime; 49 49 import net.sourceforge.jnlp.config.Defaults; 50 import net.sourceforge.jnlp.util.logging.OutputController; 50 51 51 52 /** … … 74 75 } 75 76 76 if (JNLPRuntime.isDebug()) { 77 System.out.println("Using firefox's profiles file: " + profilesPath); 78 } 77 OutputController.getLogger().log("Using firefox's profiles file: " + profilesPath); 78 79 79 BufferedReader reader = new BufferedReader(new FileReader(profilesPath)); 80 80 … … 133 133 } else { 134 134 String fullPath = configPath + path + File.separator + "prefs.js"; 135 if (JNLPRuntime.isDebug()) { 136 System.out.println("Found preferences file: " + fullPath); 137 } 135 OutputController.getLogger().log("Found preferences file: " + fullPath); 138 136 return new File(fullPath); 139 137 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/browser/FirefoxPreferencesParser.java
r348 r429 46 46 47 47 import net.sourceforge.jnlp.runtime.JNLPRuntime; 48 import net.sourceforge.jnlp.util.logging.OutputController; 48 49 49 50 /** 51 * <p> 50 52 * A parser for Firefox's preferences file. It can 'parse' Firefox's 51 53 * preferences file and expose the prefrences in a simple to use format. 52 * < p>54 * </p> 53 55 * Sample usage: 54 * <pre> 56 * <pre><code> 55 57 * FirefoxPreferencesParser p = new FirefoxPreferencesParser(prefsFile); 56 58 * p.parse(); 57 59 * Map<String,String> prefs = p.getPreferences(); 58 60 * System.out.println("blink allowed: " + prefs.get("browser.blink_allowed")); 59 * </ pre>61 * </code></pre> 60 62 */ 61 63 public final class FirefoxPreferencesParser { … … 129 131 130 132 if (foundKey && foundValue) { 131 // System.out.println("added (\"" + key + "\", \"" + value + "\")");133 //ItwLogger.getLogger().printOutLn("added (\"" + key + "\", \"" + value + "\")"); 132 134 prefs.put(key, value); 133 135 } … … 139 141 reader.close(); 140 142 } 141 if (JNLPRuntime.isDebug()) { 142 System.out.println("Read " + prefs.size() + " entries from Firefox's preferences"); 143 } 143 OutputController.getLogger().log("Read " + prefs.size() + " entries from Firefox's preferences"); 144 144 } 145 145 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheDirectory.java
r348 r429 41 41 42 42 import net.sourceforge.jnlp.util.FileUtils; 43 import net.sourceforge.jnlp.util.logging.OutputController; 43 44 44 45 public final class CacheDirectory { … … 94 95 delete = false; 95 96 } 96 if (delete) 97 System.out.println("Delete -- " + root); 97 if (delete){ 98 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Delete -- " + root); 99 } 98 100 // root.delete(); 99 101 return true; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheEntry.java
r348 r429 17 17 package net.sourceforge.jnlp.cache; 18 18 19 import net.sourceforge.jnlp.util.logging.OutputController; 19 20 import static net.sourceforge.jnlp.runtime.Translator.R; 20 21 … … 27 28 28 29 /** 29 * Describes an entry in the cache. <p>30 * Describes an entry in the cache. 30 31 * 31 32 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 122 123 return false; 123 124 } catch (Exception ex) { 124 if (JNLPRuntime.isDebug()) 125 ex.printStackTrace(); 125 OutputController.getLogger().log(ex);; 126 126 127 127 return cached; // if can't connect return whether already in cache … … 149 149 return true; 150 150 } catch (Exception ex) { 151 if (JNLPRuntime.isDebug()) 152 ex.printStackTrace(); 151 OutputController.getLogger().log(ex); 153 152 154 153 return false; // should throw? -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java
r418 r429 54 54 import net.sourceforge.jnlp.runtime.JNLPRuntime; 55 55 import net.sourceforge.jnlp.util.FileUtils; 56 import net.sourceforge.jnlp.util.logging.OutputController; 56 57 import net.sourceforge.jnlp.util.PropertiesFile; 57 58 … … 60 61 * multiple jvm instances. 61 62 * 62 * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca)63 * @author <a href="mailto:Andrew%20Su%20<asu@redhat.com>">Andrew Su (asu@redhat.com</a>, <a href="mailto:Andrew%20Su%20<andrew.su@utoronto.ca>">andrew.su@utoronto.ca)</a> 63 64 * 64 65 */ 65 enum CacheLRUWrapper {66 public enum CacheLRUWrapper { 66 67 INSTANCE; 67 68 … … 73 74 /* location of cache directory */ 74 75 private final String setCachePath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR); 75 private finalString cacheDir = new File(setCachePath != null ? setCachePath : System.getProperty("java.io.tmpdir")).getPath();76 String cacheDir = new File(setCachePath != null ? setCachePath : System.getProperty("java.io.tmpdir")).getPath(); 76 77 77 78 /* … … 80 81 * accessed) followed by folder of item. value = path to file. 81 82 */ 82 private PropertiesFile cacheOrder = new PropertiesFile( 83 new File(cacheDir + File.separator + "recently_used")); 84 85 private CacheLRUWrapper(){ 83 PropertiesFile cacheOrder = new PropertiesFile( 84 new File(cacheDir + File.separator + CACHE_INDEX_FILE_NAME)); 85 public static final String CACHE_INDEX_FILE_NAME = "recently_used"; 86 87 private CacheLRUWrapper() { 86 88 File f = cacheOrder.getStoreFile(); 87 89 if (!f.exists()) { … … 90 92 FileUtils.createRestrictedFile(f, true); 91 93 } catch (IOException e) { 92 e.printStackTrace();94 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 93 95 } 94 96 } … … 98 100 * Returns an instance of the policy. 99 101 * 100 * @param propertiesFile 101 * @return 102 * @return an instance of the policy 102 103 */ 103 104 public static CacheLRUWrapper getInstance() { … … 114 115 */ 115 116 if (loaded && checkData()) { 116 if (JNLPRuntime.isDebug()) { 117 new LruCacheException().printStackTrace(); 118 } 119 System.out.println(R("CFakeCache")); 117 OutputController.getLogger().log(new LruCacheException()); 118 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CFakeCache")); 120 119 store(); 121 System.out.println(R("CFakedCache"));120 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CFakedCache")); 122 121 } 123 122 } … … 222 221 * @return List of Strings sorted by ascending order. 223 222 */ 223 @SuppressWarnings({"unchecked", "rawtypes"}) 224 //although Properties are pretending to be <object,Object> they are always <String,String> 225 //bug in jdk? 224 226 public synchronized List<Entry<String, String>> getLRUSortedEntries() { 225 ArrayList<Entry<String, String>> entries = new ArrayList(cacheOrder.entrySet());227 List<Entry<String, String>> entries = new ArrayList(cacheOrder.entrySet()); 226 228 // sort by keys in descending order. 227 229 Collections.sort(entries, new Comparator<Entry<String, String>>() { … … 246 248 } catch (OverlappingFileLockException e) { // if overlap we just increase the count. 247 249 } catch (Exception e) { // We didn't get a lock.. 248 e.printStackTrace();250 OutputController.getLogger().log(e); 249 251 } 250 252 if (fl != null) lockCount++; … … 264 266 } 265 267 } catch (IOException e) { 266 e.printStackTrace();268 OutputController.getLogger().log(e); 267 269 } 268 270 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheUtil.java
r418 r429 19 19 import static net.sourceforge.jnlp.runtime.Translator.R; 20 20 21 import java.io.*; 22 import java.net.*; 21 import java.io.BufferedInputStream; 22 import java.io.BufferedOutputStream; 23 import java.io.File; 24 import java.io.FileNotFoundException; 25 import java.io.FileOutputStream; 26 import java.io.FilePermission; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.OutputStream; 30 import java.net.MalformedURLException; 31 import java.net.URL; 32 import java.net.URLConnection; 23 33 import java.nio.channels.FileChannel; 24 34 import java.nio.channels.FileLock; 25 35 import java.nio.channels.OverlappingFileLockException; 36 import java.security.Permission; 26 37 import java.util.ArrayList; 27 38 import java.util.HashMap; … … 30 41 import java.util.Map.Entry; 31 42 import java.util.Set; 32 import java.security.*; 33 import javax.jnlp. *;34 35 import net.sourceforge.jnlp. *;43 44 import javax.jnlp.DownloadServiceListener; 45 46 import net.sourceforge.jnlp.Version; 36 47 import net.sourceforge.jnlp.config.DeploymentConfiguration; 37 import net.sourceforge.jnlp.runtime.*; 48 import net.sourceforge.jnlp.runtime.ApplicationInstance; 49 import net.sourceforge.jnlp.runtime.JNLPRuntime; 38 50 import net.sourceforge.jnlp.util.FileUtils; 51 import net.sourceforge.jnlp.util.logging.OutputController; 39 52 import net.sourceforge.jnlp.util.PropertiesFile; 53 import net.sourceforge.jnlp.util.UrlUtils; 40 54 41 55 /** 42 56 * Provides static methods to interact with the cache, download 43 * indicator, and other utility methods. <p>57 * indicator, and other utility methods. 44 58 * 45 59 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 55 69 /** 56 70 * Compares a URL using string compare of its protocol, host, 57 * port, path, query, and anchor. 71 * port, path, query, and anchor. This method avoids the host 58 72 * name lookup that URL.equals does for http: protocol URLs. 59 73 * It may not return the same value as the URL.equals method … … 73 87 } 74 88 try { 75 URL nu1 = ResourceTracker.normalizeUrl(u1, false);76 URL nu2 = ResourceTracker.normalizeUrl(u2, false);89 URL nu1 = UrlUtils.normalizeUrl(u1); 90 URL nu2 = UrlUtils.normalizeUrl(u2); 77 91 if (notNullUrlEquals(nu1, nu2)) { 78 92 return true; … … 98 112 /** 99 113 * Caches a resource and returns a URL for it in the cache; 100 * blocks until resource is cached. 114 * blocks until resource is cached. If the resource location is 101 115 * not cacheable (points to a local file, etc) then the original 102 * URL is returned. <p>116 * URL is returned. 103 117 * 104 118 * @param location location of the resource 105 * @param version the version, or null119 * @param version the version, or {@code null} 106 120 * @return either the location in the cache or the original location 107 121 */ … … 119 133 120 134 /** 121 * Compare strings that can be null.135 * Compare strings that can be {@code null}. 122 136 */ 123 137 private static boolean compare(String s1, String s2, boolean ignore) { … … 135 149 /** 136 150 * Returns the Permission object necessary to access the 137 * resource, or nullif no permission is needed.151 * resource, or {@code null} if no permission is needed. 138 152 */ 139 153 public static Permission getReadPermission(URL location, Version version) { … … 148 162 } catch (java.io.IOException ioe) { 149 163 // should try to figure out the permission 150 if (JNLPRuntime.isDebug()) 151 ioe.printStackTrace(); 164 OutputController.getLogger().log(ioe); 152 165 } 153 166 } … … 166 179 167 180 if (!okToClearCache()) { 168 System.err.println(R("CCannotClearCache"));181 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("CCannotClearCache")); 169 182 return false; 170 183 } … … 175 188 } 176 189 177 if (JNLPRuntime.isDebug()) { 178 System.err.println("Clearing cache directory: " + cacheDir); 179 } 190 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Clearing cache directory: " + cacheDir); 180 191 try { 181 192 cacheDir = cacheDir.getCanonicalFile(); 182 193 FileUtils.recursiveDelete(cacheDir, cacheDir); 194 cacheDir.mkdir(); 183 195 } catch (IOException e) { 184 196 throw new RuntimeException(e); … … 192 204 */ 193 205 private static boolean okToClearCache() { 194 File otherJavawsRunning = new File(JNLPRuntime.getConfiguration() 195 .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE));206 File otherJavawsRunning = new File(JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE)); 207 FileLock locking = null; 196 208 try { 197 209 if (otherJavawsRunning.isFile()) { … … 199 211 200 212 FileChannel channel = fis.getChannel(); 201 if (channel.tryLock() == null) { 202 if (JNLPRuntime.isDebug()) { 203 System.out.println("Other instances of netx are running"); 204 } 213 locking = channel.tryLock(); 214 if (locking == null) { 215 OutputController.getLogger().log("Other instances of netx are running"); 205 216 return false; 206 217 } 207 208 if (JNLPRuntime.isDebug()) { 209 System.out.println("No other instances of netx are running"); 210 } 218 OutputController.getLogger().log("No other instances of netx are running"); 211 219 return true; 212 220 213 221 } else { 214 if (JNLPRuntime.isDebug()) { 215 System.out.println("No instance file found"); 216 } 222 OutputController.getLogger().log("No instance file found"); 217 223 return true; 218 224 } 219 225 } catch (IOException e) { 220 226 return false; 227 } finally { 228 if (locking != null) { 229 try { 230 locking.release(); 231 } catch (IOException ex) { 232 OutputController.getLogger().log(ex); 233 } 234 } 221 235 } 222 236 } … … 227 241 * immediately. 228 242 * 229 * @param source the source URL243 * @param source the source {@link URL} 230 244 * @param version the versions to check for 231 * @param connection a connection to the URL, or null245 * @param connection a connection to the {@link URL}, or {@code null} 232 246 * @return whether the cache contains the version 233 247 * @throws IllegalArgumentException if the source is not cacheable … … 247 261 boolean result = entry.isCurrent(connection); 248 262 249 if (JNLPRuntime.isDebug()) 250 System.out.println("isCurrent: " + source + " = " + result); 263 OutputController.getLogger().log("isCurrent: " + source + " = " + result); 251 264 252 265 return result; 253 266 } catch (Exception ex) { 254 if (JNLPRuntime.isDebug()) 255 ex.printStackTrace(); 256 267 OutputController.getLogger().log(ex); 257 268 return isCached(source, version); // if can't connect return whether already in cache 258 269 } … … 275 286 boolean result = entry.isCached(); 276 287 277 if (JNLPRuntime.isDebug()) 278 System.out.println("isCached: " + source + " = " + result); 288 OutputController.getLogger().log("isCached: " + source + " = " + result); 279 289 280 290 return result; … … 305 315 * resource that matches the specified version will be returned. 306 316 * 307 * @param source the source URL317 * @param source the source {@link URL} 308 318 * @param version the version id of the local file 309 * @return the file location in the cache, or nullif no versions cached319 * @return the file location in the cache, or {@code null} if no versions cached 310 320 * @throws IllegalArgumentException if the source is not cacheable 311 321 */ … … 337 347 * 338 348 * @param urlPath Path of cache item within cache directory. 339 * @return File if we have searched before, nullotherwise.349 * @return File if we have searched before, {@code null} otherwise. 340 350 */ 341 351 private static File getCacheFileIfExist(File urlPath) { … … 365 375 int index = path.indexOf(File.separatorChar, len + 1); 366 376 return path.substring(index); 377 } 378 379 /** 380 * Returns the parent directory of the cached resource. 381 * @param filePath The path of the cached resource directory. 382 */ 383 public static String getCacheParentDirectory(String filePath) { 384 String path = filePath; 385 String tempPath = ""; 386 387 while(path.startsWith(cacheDir) && !path.equals(cacheDir)){ 388 tempPath = new File(path).getParent(); 389 390 if (tempPath.equals(cacheDir)) 391 break; 392 393 path = tempPath; 394 } 395 return path; 367 396 } 368 397 … … 394 423 lruHandler.addEntry(lruHandler.generateKey(cacheFile.getPath()), cacheFile.getPath()); 395 424 } catch (IOException ioe) { 396 ioe.printStackTrace();425 OutputController.getLogger().log(ioe); 397 426 } 398 427 … … 534 563 } 535 564 } catch (InterruptedException ex) { 536 if (JNLPRuntime.isDebug()) 537 ex.printStackTrace(); 565 OutputController.getLogger().log(ex); 538 566 } finally { 539 567 if (listener != null) … … 610 638 FileUtils.recursiveDelete(f, f); 611 639 } catch (IOException e1) { 612 e1.printStackTrace();640 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e1); 613 641 } 614 642 } … … 651 679 } catch (OverlappingFileLockException e) { 652 680 } catch (FileNotFoundException e) { 653 e.printStackTrace();681 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 654 682 } 655 683 } … … 670 698 propertiesLockPool.remove(storeFile.getPath()); 671 699 } catch (IOException e) { 672 e.printStackTrace();700 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 673 701 } 674 702 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java
r418 r429 30 30 import net.sourceforge.jnlp.runtime.*; 31 31 import net.sourceforge.jnlp.util.ImageResources; 32 import net.sourceforge.jnlp.util.ScreenFinder; 32 33 33 34 /** … … 63 64 /** shared constraint */ 64 65 static GridBagConstraints vertical; 66 static GridBagConstraints verticalNoClean; 65 67 static GridBagConstraints verticalIndent; 66 68 static { … … 71 73 vertical.anchor = GridBagConstraints.WEST; 72 74 75 verticalNoClean = new GridBagConstraints(); 76 verticalNoClean.weightx = 1.0; 77 73 78 verticalIndent = (GridBagConstraints) vertical.clone(); 74 79 verticalIndent.insets = new Insets(0, 10, 3, 0); … … 102 107 synchronized (frameMutex) { 103 108 if (frame == null) { 104 frame = new JFrame(downloading + "..."); 105 frame.setIconImages(ImageResources.INSTANCE.getApplicationImages()); 106 frame.getContentPane().setLayout(new GridBagLayout()); 109 frame=createDownloadIndicatorFrame(true); 107 110 } 108 111 … … 110 113 for (URL url : resources) { 111 114 result.addProgressPanel(url, null); 115 112 116 } 113 117 } … … 115 119 frame.getContentPane().add(result, vertical); 116 120 frame.pack(); 117 118 if (!frame.isVisible()) { 119 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 120 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration()); 121 Dimension screen = new Dimension(screenSize.width - insets.left, 122 screenSize.height - insets.top); 123 frame.setLocation(screen.width - frame.getWidth(), 124 screen.height - frame.getHeight()); 125 } 121 placeFrameToLowerRight(); 122 result.addComponentListener(new ComponentAdapter() { 123 @Override 124 public void componentResized(ComponentEvent e) { 125 placeFrameToLowerRight(); 126 } 127 }); 126 128 127 129 frame.setVisible(true); … … 129 131 return result; 130 132 } 133 } 134 135 public static JFrame createDownloadIndicatorFrame(boolean undecorated) throws HeadlessException { 136 JFrame f = new JFrame(downloading + "..."); 137 f.setUndecorated(undecorated); 138 f.setIconImages(ImageResources.INSTANCE.getApplicationImages()); 139 f.getContentPane().setLayout(new GridBagLayout()); 140 return f; 141 } 142 143 /** 144 * This places indicator to lower right corner of active monitor. 145 */ 146 private static void placeFrameToLowerRight() throws HeadlessException { 147 Rectangle bounds = ScreenFinder.getCurrentScreenSizeWithoutBounds(); 148 frame.setLocation(bounds.width+bounds.x - frame.getWidth(), 149 bounds.height+bounds.y - frame.getHeight()); 131 150 } 132 151 … … 164 183 */ 165 184 static class DownloadPanel extends JPanel implements DownloadServiceListener { 166 185 private final DownloadPanel self; 186 187 private static enum States{ 188 ONE_JAR, COLLAPSED, DETAILED; 189 } 190 191 private static final String DETAILS=R("ButShowDetails"); 192 private static final String HIDE_DETAILS=R("ButHideDetails"); 167 193 /** the download name */ 168 194 private String downloadName; 169 170 195 /** Downloading part: */ 171 196 private JLabel header = new JLabel(); 172 197 /** Show/hide detailsButton button: */ 198 private final JButton detailsButton; 199 private static final URL magnifyGlassUrl = ClassLoader.getSystemResource("net/sourceforge/jnlp/resources/showDownloadDetails.png"); 200 private static final URL redCrossUrl = ClassLoader.getSystemResource("net/sourceforge/jnlp/resources/hideDownloadDetails.png"); 201 private static final Icon magnifyGlassIcon = new ImageIcon(magnifyGlassUrl); 202 private static final Icon redCrossIcon = new ImageIcon(redCrossUrl); 203 /** used instead of detailsButton button in case of one jar*/ 204 private JLabel delimiter = new JLabel(""); 205 /** all already created progress bars*/ 206 private List<ProgressPanel> progressPanels = new ArrayList<ProgressPanel>(); 207 private States state=States.ONE_JAR; 208 private ProgressPanel mainProgressPanel; 209 173 210 /** list of URLs being downloaded */ 174 211 private List<URL> urls = new ArrayList<URL>(); … … 182 219 */ 183 220 protected DownloadPanel(String downloadName) { 221 self = this; 184 222 setLayout(new GridBagLayout()); 185 186 223 this.downloadName = downloadName; 187 this.add(header, vertical );224 this.add(header, verticalNoClean); 188 225 header.setFont(header.getFont().deriveFont(Font.BOLD)); 189 226 this.add(delimiter, vertical); 227 detailsButton = new JButton(magnifyGlassIcon); 228 int w = magnifyGlassIcon.getIconWidth(); 229 int h = magnifyGlassIcon.getIconHeight(); 230 detailsButton.setPreferredSize(new Dimension(w + 2, h + 2)); 231 detailsButton.addActionListener(new ActionListener() { 232 @Override 233 public void actionPerformed(ActionEvent e) { 234 if (state == States.DETAILED) { 235 state = States.COLLAPSED; 236 detailsButton.setToolTipText(DETAILS); 237 detailsButton.setIcon(magnifyGlassIcon); 238 for (ProgressPanel progressPanel : progressPanels) { 239 remove(progressPanel); 240 } 241 add(mainProgressPanel, verticalIndent); 242 recreateFrame(true); 243 } else { 244 state = States.DETAILED; 245 detailsButton.setToolTipText(HIDE_DETAILS); 246 detailsButton.setIcon(redCrossIcon); 247 remove(mainProgressPanel); 248 for (ProgressPanel progressPanel : progressPanels) { 249 add(progressPanel, verticalIndent); 250 } 251 recreateFrame(false); 252 } 253 } 254 255 public void recreateFrame(boolean undecorated) throws HeadlessException { 256 JFrame oldFrame = frame; 257 frame = createDownloadIndicatorFrame(undecorated); 258 frame.getContentPane().add(self, vertical); 259 synchronized (frameMutex) { 260 frame.pack(); 261 placeFrameToLowerRight(); 262 } 263 frame.setVisible(true); 264 oldFrame.dispose(); 265 } 266 }); 190 267 setOverallPercent(0); 191 268 } … … 197 274 if (!urls.contains(url)) { 198 275 ProgressPanel panel = new ProgressPanel(url, version); 199 200 add(panel, verticalIndent); 276 if (state != States.COLLAPSED) { 277 add(panel, verticalIndent); 278 } 279 progressPanels.add(panel); 280 urls.add(url); 281 panels.add(panel); 282 //download indicator does not know about added jars 283 //When only one jar is added to downlaod queue then its progress is 284 //shown, and there is no show detail button. 285 //When second one is added, then it already knows that there will 286 //be two or more jars, so it swap to collapsed state in count of two. 287 //no later, no sooner 288 if (panels.size() == 2){ 289 remove(panels.get(0)); 290 remove(panels.get(1)); 291 remove(delimiter); 292 add(detailsButton,vertical); 293 mainProgressPanel=new ProgressPanel(); 294 add(mainProgressPanel, verticalIndent); 295 state=States.COLLAPSED; 296 } 201 297 synchronized (frameMutex) { 202 298 frame.pack(); 203 } 204 205 urls.add(url); 206 panels.add(panel); 299 placeFrameToLowerRight(); 300 } 301 207 302 } 208 303 } … … 220 315 221 316 setOverallPercent(overallPercent); 222 223 317 ProgressPanel panel = panels.get(urls.indexOf(url)); 224 318 panel.setProgress(readSoFar, total); 225 319 panel.repaint(); 320 226 321 } 227 322 }; … … 231 326 /** 232 327 * Sets the overall percent completed. 328 * should be called via invokeLater 233 329 */ 234 330 public void setOverallPercent(int percent) { … … 237 333 // each update. 238 334 header.setText(downloading + " " + downloadName + ": " + percent + "% " + complete + "."); 335 Container c = header.getParent(); 336 //we need to adapt both panels and also frame to new length of header text 337 while (c != null) { 338 c.invalidate(); 339 c.validate(); 340 if (c instanceof Window){ 341 ((Window) c).pack(); 342 } 343 c=c.getParent(); 344 } 345 if (mainProgressPanel != null) { 346 mainProgressPanel.setProgress(percent, 100); 347 mainProgressPanel.repaint(); 348 } 239 349 } 240 350 … … 277 387 private long total; 278 388 private long readSoFar; 279 389 private Dimension size = new Dimension(80, 15); 390 391 ProgressPanel() { 392 bar.setMinimumSize(size); 393 bar.setPreferredSize(size); 394 bar.setOpaque(false); 395 396 setLayout(new GridBagLayout()); 397 398 GridBagConstraints gbc = new GridBagConstraints(); 399 styleGridBagConstraints(gbc); 400 add(bar, gbc); 401 } 402 280 403 ProgressPanel(URL url, String version) { 281 JLabel location = new JLabel(" " + url.getHost() + "/" + url.getFile()); 282 283 bar.setMinimumSize(new Dimension(80, 15)); 284 bar.setPreferredSize(new Dimension(80, 15)); 404 this(" " + url.getHost() + "/" + url.getFile(),version); 405 } 406 ProgressPanel(String caption, String version) { 407 JLabel location = new JLabel(caption); 408 409 bar.setMinimumSize(size); 410 bar.setPreferredSize(size); 285 411 bar.setOpaque(false); 286 412 … … 292 418 gbc.gridwidth = GridBagConstraints.RELATIVE; 293 419 add(bar, gbc); 294 420 421 styleGridBagConstraints(gbc); 422 add(location, gbc); 423 } 424 425 public void setProgress(long readSoFar, long total) { 426 this.readSoFar = readSoFar; 427 this.total = total; 428 } 429 430 public void paintComponent(Graphics g) { 431 super.paintComponent(g); 432 433 int x = bar.getX(); 434 int y = bar.getY(); 435 int h = bar.getHeight(); 436 int w = bar.getWidth(); 437 438 if (readSoFar <= 0 || total <= 0) { 439 // make barber pole 440 } else { 441 double progress = (double) readSoFar / (double) total; 442 int divide = (int) (w * progress); 443 444 g.setColor(Color.white); 445 g.fillRect(x, y, w, h); 446 g.setColor(Color.blue); 447 g.fillRect(x + 1, y + 1, divide - 1, h - 1); 448 } 449 } 450 451 private void styleGridBagConstraints(GridBagConstraints gbc) { 295 452 gbc.insets = new Insets(0, 3, 0, 0); 296 453 gbc.weightx = 1.0; … … 298 455 gbc.gridwidth = GridBagConstraints.REMAINDER; 299 456 gbc.anchor = GridBagConstraints.WEST; 300 add(location, gbc);301 }302 303 public void setProgress(long readSoFar, long total) {304 this.readSoFar = readSoFar;305 this.total = total;306 }307 308 public void paintComponent(Graphics g) {309 super.paintComponent(g);310 311 int x = bar.getX();312 int y = bar.getY();313 int h = bar.getHeight();314 int w = bar.getWidth();315 316 if (readSoFar <= 0 || total <= 0) {317 // make barber pole318 } else {319 double progress = (double) readSoFar / (double) total;320 int divide = (int) (w * progress);321 322 g.setColor(Color.white);323 g.fillRect(x, y, w, h);324 g.setColor(Color.blue);325 g.fillRect(x + 1, y + 1, divide - 1, h - 1);326 }327 457 } 328 458 }; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/DownloadIndicator.java
r348 r429 33 33 /** 34 34 * Return a download service listener that displays the progress 35 * of downloading resources. 36 * for URLs that are not included initially. <p>37 * 35 * of downloading resources. Update messages may be reported 36 * for URLs that are not included initially. 37 * <p> 38 38 * Progress messages are sent as if the DownloadServiceListener 39 * were listening to a DownloadService request. 39 * were listening to a DownloadService request. The listener 40 40 * will receive progress messages from time to time during the 41 * download. <p> 41 * download. 42 * </p> 42 43 * 43 44 * @param app JNLP application downloading the files, or null if not applicable -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/IllegalResourceDescriptorException.java
r418 r429 1 /* IllegalResourceDescriptorException.java 2 Copyright (C) 2012 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 1 38 package net.sourceforge.jnlp.cache; 2 39 … … 4 41 public class IllegalResourceDescriptorException extends IllegalArgumentException { 5 42 /** 6 * Constructs a <code>IllegalResourceDescriptorException</code>with the43 * Constructs a {@code IllegalResourceDescriptorException} with the 7 44 * specified detail message. 8 45 * @param msg the detail message. -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/Resource.java
r418 r429 17 17 package net.sourceforge.jnlp.cache; 18 18 19 import net.sourceforge.jnlp.util.logging.OutputController; 19 20 import java.io.*; 20 21 import java.net.*; … … 26 27 27 28 /** 29 * <p> 28 30 * Information about a single resource to download. 29 31 * This class tracks the downloading of various resources of a … … 31 33 * jnlp and extension files, jars, and jardiff files using the 32 34 * version based protocol or any file using the basic download 33 * protocol.<p> 34 * 35 * protocol. 36 * </p> 37 * <p> 35 38 * Resources can be put into download groups by specifying a part 36 39 * name for the resource. The resource tracker can also be 37 40 * configured to prefetch resources, which are downloaded in the 38 * order added to the media tracker.<p> 41 * order added to the media tracker. 42 * </p> 39 43 * 40 44 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 110 114 Resource resource = new Resource(location, requestVersion, updatePolicy); 111 115 116 //FIXME - url ignores port during its comparison 117 //this may affect test-suites 112 118 int index = resources.indexOf(resource); 113 119 if (index >= 0) { // return existing object … … 225 231 } 226 232 227 if (JNLPRuntime.isDebug()) 228 if (status != orig) { 229 System.out.print("Status: " + getStatusString(status)); 230 if ((status & ~orig) != 0) 231 System.out.print(" +(" + getStatusString(status & ~orig) + ")"); 232 if ((~status & orig) != 0) 233 System.out.print(" -(" + getStatusString(~status & orig) + ")"); 234 System.out.println(" @ " + location.getPath()); 233 if (status != orig) { 234 OutputController.getLogger().log("Status: " + getStatusString(status)); 235 if ((status & ~orig) != 0) { 236 OutputController.getLogger().log(" +(" + getStatusString(status & ~orig) + ")"); 235 237 } 238 if ((~status & orig) != 0) { 239 OutputController.getLogger().log(" -(" + getStatusString(~status & orig) + ")"); 240 } 241 OutputController.getLogger().log(" @ " + location.getPath()); 242 } 236 243 } 237 244 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/ResourceTracker.java
r418 r429 25 25 import java.io.InputStream; 26 26 import java.io.OutputStream; 27 import java.io.UnsupportedEncodingException;28 27 import java.net.HttpURLConnection; 28 import java.net.InetAddress; 29 29 import java.net.MalformedURLException; 30 30 import java.net.URL; 31 31 import java.net.URLConnection; 32 import java.net.URLDecoder; 33 import java.net.URLEncoder; 32 import java.net.UnknownHostException; 34 33 import java.security.AccessController; 35 34 import java.security.PrivilegedAction; 36 35 import java.util.ArrayList; 36 import java.util.HashMap; 37 37 import java.util.List; 38 import java.util.Map; 38 39 import java.util.concurrent.ConcurrentHashMap; 39 40 import java.util.jar.JarOutputStream; … … 47 48 import net.sourceforge.jnlp.event.DownloadListener; 48 49 import net.sourceforge.jnlp.runtime.JNLPRuntime; 50 import net.sourceforge.jnlp.util.HttpUtils; 51 import net.sourceforge.jnlp.util.logging.OutputController; 52 import net.sourceforge.jnlp.util.UrlUtils; 49 53 import net.sourceforge.jnlp.util.WeakList; 50 54 51 55 /** 52 56 * This class tracks the downloading of various resources of a 53 * JNLP file to local files in the cache. 57 * JNLP file to local files in the cache. It can be used to 54 58 * download icons, jnlp and extension files, jars, and jardiff 55 59 * files using the version based protocol or any file using the 56 60 * basic download protocol (jardiff and version not implemented 57 * yet). <p>58 * 61 * yet). 62 * <p> 59 63 * The resource tracker can be configured to prefetch resources, 60 64 * which are downloaded in the order added to the media 61 * tracker.<p> 62 * 65 * tracker. 66 * </p> 67 * <p> 63 68 * Multiple threads are used to download and cache resources that 64 69 * are actively being waited for (blocking a caller) or those that … … 68 73 * This allows the tracker to start downloading many items without 69 74 * using many system resources, but still quickly download items 70 * as needed.<p> 75 * as needed. 76 * </p> 71 77 * 72 78 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 112 118 private static final int STARTED = Resource.STARTED; 113 119 114 // normalization of url115 private static final char PATH_DELIMITER_MARK = '/';116 private static final String PATH_DELIMITER = "" + PATH_DELIMITER_MARK;117 private static final char QUERY_DELIMITER_MARK = '&';118 private static final String QUERY_DELIMITER = "" + QUERY_DELIMITER_MARK;119 private static final char QUERY_MARK = '?';120 private static final char HREF_MARK = '#';121 private static final String UTF8 = "utf-8";122 123 120 /** max threads */ 124 121 private static final int maxThreads = 5; 122 123 /** methods used to try individual URLs when choosing best*/ 124 private static final String[] requestMethods = {"HEAD", "GET"}; 125 125 126 126 /** running threads */ … … 187 187 throw new IllegalResourceDescriptorException("location==null"); 188 188 try { 189 location = normalizeUrl(location, JNLPRuntime.isDebug());189 location = UrlUtils.normalizeUrl(location); 190 190 } catch (Exception ex) { 191 System.err.println("Normalization of " + location.toString() + " have failed");192 ex.printStackTrace();191 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Normalization of " + location.toString() + " have failed"); 192 OutputController.getLogger().log(ex); 193 193 } 194 194 Resource resource = Resource.getResource(location, version, updatePolicy); … … 243 243 /** 244 244 * Check the cache for a resource, and initialize the resource 245 * as already downloaded if found. <p>245 * as already downloaded if found. 246 246 * 247 247 * @param updatePolicy whether to check for updates if already in cache … … 264 264 265 265 if (entry.isCached() && !updatePolicy.shouldUpdate(entry)) { 266 if (JNLPRuntime.isDebug()) 267 System.out.println("not updating: " + resource.location); 266 OutputController.getLogger().log("not updating: " + resource.location); 268 267 269 268 synchronized (resource) { … … 291 290 /** 292 291 * Adds the listener to the list of objects interested in 293 * receivind DownloadEvents. <p>292 * receivind DownloadEvents. 294 293 * 295 294 * @param listener the listener to add. … … 345 344 * Returns a URL pointing to the cached location of the 346 345 * resource, or the resource itself if it is a non-cacheable 347 * resource. <p>348 * 346 * resource. 347 * <p> 349 348 * If the resource has not downloaded yet, the method will block 350 * until it has been transferred to the cache.<p> 349 * until it has been transferred to the cache. 350 * </p> 351 351 * 352 352 * @param location the resource location … … 362 362 return f.toURL(); 363 363 } catch (MalformedURLException ex) { 364 if (JNLPRuntime.isDebug()) 365 ex.printStackTrace(); 364 OutputController.getLogger().log(ex); 366 365 } 367 366 … … 372 371 * Returns a file containing the downloaded resource. If the 373 372 * resource is non-cacheable then null is returned unless the 374 * resource is a local file (the original file is returned). <p>375 * 373 * resource is a local file (the original file is returned). 374 * <p> 376 375 * If the resource has not downloaded yet, the method will block 377 * until it has been transferred to the cache.<p> 376 * until it has been transferred to the cache. 377 * </p> 378 378 * 379 379 * @param location the resource location … … 395 395 396 396 if (location.getProtocol().equalsIgnoreCase("file")) { 397 File file = new File(location.getFile());397 File file = UrlUtils.decodeUrlAsFile(location); 398 398 if (file.exists()) 399 399 return file; … … 402 402 return null; 403 403 } catch (InterruptedException ex) { 404 if (JNLPRuntime.isDebug()) 405 ex.printStackTrace(); 406 404 OutputController.getLogger().log(ex); 407 405 return null; // need an error exception to throw 408 406 } 409 407 } 410 408 411 /** 412 * Returns an input stream that reads the contents of the 413 * resource. For non-cacheable resources, an InputStream that 414 * reads from the source location is returned. Otherwise the 415 * InputStream reads the cached resource.<p> 416 * 417 * This method will block while the resource is downloaded to 418 * the cache. 419 * 420 * @throws IOException if there was an error opening the stream 421 * @throws IllegalResourceDescriptorException if the resource is not being tracked 422 */ 423 public InputStream getInputStream(URL location) throws IOException { 424 try { 425 Resource resource = getResource(location); 426 if (!resource.isSet(DOWNLOADED | ERROR)) 427 waitForResource(location, 0); 428 429 if (resource.localFile != null) 430 return new FileInputStream(resource.localFile); 431 432 return resource.location.openStream(); 433 } catch (InterruptedException ex) { 434 throw new IOException("wait was interrupted"); 435 } 436 } 409 437 410 438 411 /** … … 559 532 /** 560 533 * Start a new download thread if there are not too many threads 561 * already running. <p>562 * 534 * already running. 535 * <p> 563 536 * Calls to this method should be synchronized on lock. 537 * </p> 564 538 */ 565 539 protected void startThread() { … … 567 541 threads++; 568 542 569 Thread thread = new Thread(new Downloader() );543 Thread thread = new Thread(new Downloader(), "DownloaderThread" + threads); 570 544 thread.start(); 571 545 } … … 573 547 574 548 /** 575 * A thread is ending, called by the thread itself. <p>576 * 549 * A thread is ending, called by the thread itself. 550 * <p> 577 551 * Calls to this method should be synchronized. 552 * </p> 578 553 */ 579 554 private void endThread() { … … 670 645 String contentEncoding = con.getContentEncoding(); 671 646 672 if (JNLPRuntime.isDebug()) { 673 System.err.println("Downloading" + resource.location + " using " + 647 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Downloading" + resource.location + " using " + 674 648 realLocation + " (encoding : " + contentEncoding + ")"); 675 676 }677 649 678 650 boolean packgz = "pack200-gzip".equals(contentEncoding) || … … 765 737 resource.fireDownloadEvent(); // fire DOWNLOADED 766 738 } catch (Exception ex) { 767 if (JNLPRuntime.isDebug()) 768 ex.printStackTrace(); 769 739 OutputController.getLogger().log(ex); 770 740 resource.changeStatus(0, ERROR); 771 741 synchronized (lock) { … … 783 753 */ 784 754 private void initializeResource(Resource resource) { 755 //verify connection 756 if(!JNLPRuntime.isOfflineForced()){ 757 JNLPRuntime.detectOnline(resource.getLocation()/*or doenloadLocation*/); 758 } 785 759 resource.fireDownloadEvent(); // fire CONNECTING 786 760 … … 790 764 try { 791 765 File localFile = CacheUtil.getCacheFile(resource.location, resource.downloadVersion); 792 793 // connect 794 URL finalLocation = findBestUrl(resource); 795 resource.setDownloadLocation(finalLocation); 796 URLConnection connection = finalLocation.openConnection(); // this won't change so should be okay unsynchronized 797 connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip"); 798 799 int size = connection.getContentLength(); 800 boolean current = CacheUtil.isCurrent(resource.location, resource.requestVersion, connection) && resource.getUpdatePolicy() != UpdatePolicy.FORCE; 801 if (!current) { 802 if (entry.isCached()) { 803 entry.markForDelete(); 804 entry.store(); 805 // Old entry will still exist. (but removed at cleanup) 806 localFile = CacheUtil.makeNewCacheFile(resource.location, resource.downloadVersion); 807 CacheEntry newEntry = new CacheEntry(resource.location, resource.requestVersion); 808 newEntry.lock(); 809 entry.unlock(); 810 entry = newEntry; 766 long size = 0; 767 boolean current = true; 768 //this can be null, as it is always filled in online mode, and never read in offline mode 769 URLConnection connection = null; 770 if (localFile != null) { 771 size = localFile.length(); 772 } else if (!JNLPRuntime.isOnline()) { 773 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "You are trying to get resource " + resource.getLocation().toExternalForm() + " but you are in offline mode, and it is not in cache. Attempting to continue, but you may expect failure"); 774 } 775 if (JNLPRuntime.isOnline()) { 776 // connect 777 URL finalLocation = findBestUrl(resource); 778 779 if (finalLocation == null) { 780 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Attempted to download " + resource.location + ", but failed to connect!"); 781 throw new NullPointerException("finalLocation == null"); // Caught below 782 } 783 784 resource.setDownloadLocation(finalLocation); 785 connection = finalLocation.openConnection(); // this won't change so should be okay unsynchronized 786 connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip"); 787 788 size = connection.getContentLength(); 789 current = CacheUtil.isCurrent(resource.location, resource.requestVersion, connection) && resource.getUpdatePolicy() != UpdatePolicy.FORCE; 790 if (!current) { 791 if (entry.isCached()) { 792 entry.markForDelete(); 793 entry.store(); 794 // Old entry will still exist. (but removed at cleanup) 795 localFile = CacheUtil.makeNewCacheFile(resource.location, resource.downloadVersion); 796 CacheEntry newEntry = new CacheEntry(resource.location, resource.requestVersion); 797 newEntry.lock(); 798 entry.unlock(); 799 entry = newEntry; 800 } 811 801 } 812 802 } … … 824 814 825 815 // update cache entry 826 if (!current )816 if (!current && JNLPRuntime.isOnline()) 827 817 entry.initialize(connection); 828 818 … … 839 829 ((HttpURLConnection) connection).disconnect(); 840 830 } catch (Exception ex) { 841 if (JNLPRuntime.isDebug()) 842 ex.printStackTrace(); 843 831 OutputController.getLogger().log(ex); 844 832 resource.changeStatus(0, ERROR); 845 833 synchronized (lock) { … … 851 839 } 852 840 } 853 854 /** 855 * Returns the best URL to use for downloading the resource 841 /** 842 * testing wrapper 843 * 844 * @param url 845 * @param requestProperties 846 * @param requestMethod 847 * @return 848 * @throws IOException 849 */ 850 static int getUrlResponseCode(URL url, Map<String, String> requestProperties, String requestMethod) throws IOException { 851 return getUrlResponseCodeWithRedirectonResult(url, requestProperties, requestMethod).result; 852 } 853 854 private static class CodeWithRedirect { 855 856 int result = HttpURLConnection.HTTP_OK; 857 URL URL; 858 859 public boolean shouldRedirect() { 860 return (result == 301 861 || result == 302 862 || result == 303/*?*/ 863 || result == 307 864 || result == 308); 865 } 866 867 public boolean isInvalid() { 868 return (result < 200 || result >= 300); 869 } 870 } 871 872 /** 873 * Connects to the given URL, and grabs a response code and redirecton if 874 * the URL uses the HTTP protocol, or returns an arbitrary valid HTTP 875 * response code. 876 * 877 * @return the response code if HTTP connection and redirection value, or 878 * HttpURLConnection.HTTP_OK and null if not. 879 * @throws IOException 880 */ 881 static CodeWithRedirect getUrlResponseCodeWithRedirectonResult(URL url, Map<String, String> requestProperties, String requestMethod) throws IOException { 882 CodeWithRedirect result = new CodeWithRedirect(); 883 URLConnection connection = url.openConnection(); 884 885 for (Map.Entry<String, String> property : requestProperties.entrySet()) { 886 connection.addRequestProperty(property.getKey(), property.getValue()); 887 } 888 889 if (connection instanceof HttpURLConnection) { 890 HttpURLConnection httpConnection = (HttpURLConnection) connection; 891 httpConnection.setRequestMethod(requestMethod); 892 893 int responseCode = httpConnection.getResponseCode(); 894 895 /* Fully consuming current request helps with connection re-use 896 * See http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html */ 897 HttpUtils.consumeAndCloseConnectionSilently(httpConnection); 898 899 result.result = responseCode; 900 } 901 902 Map<String, List<String>> header = connection.getHeaderFields(); 903 for (Map.Entry<String, List<String>> entry : header.entrySet()) { 904 OutputController.getLogger().log("Key : " + entry.getKey() + " ,Value : " + entry.getValue()); 905 } 906 /* 907 * Do this only on 301,302,303(?)307,308> 908 * Now setting value for all, and lets upper stack to handle it 909 */ 910 String possibleRedirect = connection.getHeaderField("Location"); 911 if (possibleRedirect != null && possibleRedirect.trim().length() > 0) { 912 result.URL = new URL(possibleRedirect); 913 } 914 915 return result; 916 917 } 918 919 920 /** 921 * Returns the 'best' valid URL for the given resource. 922 * This first adjusts the file name to take into account file versioning 923 * and packing, if possible. 856 924 * 857 925 * @param resource the resource 858 * @return a URL or null859 */ 860 privateURL findBestUrl(Resource resource) {926 * @return the best URL, or null if all failed to resolve 927 */ 928 URL findBestUrl(Resource resource) { 861 929 DownloadOptions options = downloadOptions.get(resource); 862 930 if (options == null) { … … 865 933 866 934 List<URL> urls = new ResourceUrlCreator(resource, options).getUrls(); 867 if (JNLPRuntime.isDebug()) { 868 System.err.println("All possible urls for " + 869 resource.toString() + " : " + urls); 870 } 871 URL bestUrl = null; 872 for (URL url : urls) { 873 try { 874 URLConnection connection = url.openConnection(); 875 connection.addRequestProperty("Accept-Encoding", "pack200-gzip, gzip"); 876 if (connection instanceof HttpURLConnection) { 877 HttpURLConnection con = (HttpURLConnection)connection; 878 int responseCode = con.getResponseCode(); 879 if (responseCode == -1 || responseCode < 200 || responseCode >= 300) { 880 continue; 881 } 882 } 883 if (JNLPRuntime.isDebug()) { 884 System.err.println("best url for " + resource.toString() + " is " + url.toString()); 885 } 886 bestUrl = url; 887 break; 888 } catch (IOException e) { 889 // continue 890 } 891 } 892 893 return bestUrl; 894 } 895 896 /** 897 * Pick the next resource to download or initialize. If there 935 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "All possible urls for " 936 + resource.toString() + " : " + urls); 937 938 for (String requestMethod : requestMethods) { 939 for (int i = 0; i < urls.size(); i++) { 940 URL url = urls.get(i); 941 try { 942 Map<String, String> requestProperties = new HashMap<String, String>(); 943 requestProperties.put("Accept-Encoding", "pack200-gzip, gzip"); 944 945 CodeWithRedirect response = getUrlResponseCodeWithRedirectonResult(url, requestProperties, requestMethod); 946 if (response.shouldRedirect()){ 947 if (response.URL == null) { 948 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Although " + resource.toString() + " got redirect " + response.result + " code for " + requestMethod + " request for " + url.toExternalForm() + " the target was null. Not following"); 949 } else { 950 OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "Resource " + resource.toString() + " got redirect " + response.result + " code for " + requestMethod + " request for " + url.toExternalForm() + " adding " + response.URL.toExternalForm()+" to list of possible urls"); 951 if (!JNLPRuntime.isAllowRedirect()){ 952 throw new RedirectionException("The resource " + url.toExternalForm() + " is being redirected (" + response.result + ") to " + response.URL.toExternalForm() + ". This is disabled by default. If you wont to allow it, run javaws with -allowredirect parameter."); 953 } 954 urls.add(response.URL); 955 } 956 } else if (response.isInvalid()) { 957 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "For " + resource.toString() + " the server returned " + response.result + " code for " + requestMethod + " request for " + url.toExternalForm()); 958 } else { 959 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "best url for " + resource.toString() + " is " + url.toString() + " by " + requestMethod); 960 return url; /* This is the best URL */ 961 } 962 } catch (IOException e) { 963 // continue to next candidate 964 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "While processing " + url.toString() + " by " + requestMethod + " for resource " + resource.toString() + " got " + e + ": "); 965 OutputController.getLogger().log(e); 966 } 967 } 968 } 969 970 /* No valid URL, return null */ 971 return null; 972 } 973 974 /** 975 * Pick the next resource to download or initialize. If there 898 976 * are no more resources requested then one is taken from a 899 * resource tracker with prefetch enabled. <p>900 * 977 * resource tracker with prefetch enabled. 978 * <p> 901 979 * The resource state is advanced before it is returned 902 * (CONNECT->CONNECTING).<p> 903 * 904 * Calls to this method should be synchronized on lock.<p> 905 * 906 * @return the resource to initialize or download, or null 980 * (CONNECT->CONNECTING). 981 * </p> 982 * <p> 983 * Calls to this method should be synchronized on lock. 984 * </p> 985 * 986 * @return the resource to initialize or download, or {@code null} 907 987 */ 908 988 private static Resource selectNextResource() { … … 942 1022 /** 943 1023 * Returns the next resource to be prefetched before 944 * requested.<p> 945 * 946 * Calls to this method should be synchronized on lock.<p> 1024 * requested. 1025 * <p> 1026 * Calls to this method should be synchronized on lock. 1027 * </p> 947 1028 */ 948 1029 private static Resource getPrefetch() { … … 990 1071 /** 991 1072 * Selects a resource from the source list that has the 992 * specified flag set. <p>993 * 1073 * specified flag set. 1074 * <p> 994 1075 * Calls to this method should be synchronized on lock and 995 * source list.<p> 1076 * source list. 1077 * </p> 996 1078 */ 997 1079 private static Resource selectByFlag(List<Resource> source, int flag, … … 1048 1130 * 1049 1131 * @param resources the resources to wait for 1050 * @param timeout the timeout, or 0to wait until completed1051 * @return s trueif the resources were downloaded or had errors,1052 * falseif the timeout was reached1132 * @param timeout the timeout, or {@code 0} to wait until completed 1133 * @return {@code true} if the resources were downloaded or had errors, 1134 * {@code false} if the timeout was reached 1053 1135 * @throws InterruptedException if another thread interrupted the wait 1054 1136 */ 1055 private boolean wait(Resource resources[], long timeout) throws InterruptedException {1137 private boolean wait(Resource[] resources, long timeout) throws InterruptedException { 1056 1138 long startTime = System.currentTimeMillis(); 1057 1139 … … 1094 1176 } 1095 1177 1178 private static class RedirectionException extends RuntimeException { 1179 1180 public RedirectionException(String string) { 1181 super(string); 1182 } 1183 1184 public RedirectionException(Throwable cause) { 1185 super(cause); 1186 } 1187 1188 } 1189 1096 1190 // inner classes 1097 1191 … … 1135 1229 1136 1230 } catch (Exception ex) { 1137 if (JNLPRuntime.isDebug()) 1138 ex.printStackTrace(); 1231 OutputController.getLogger().log(ex); 1139 1232 } 1140 1233 } … … 1143 1236 } 1144 1237 }; 1145 1146 private static String normalizeChunk(String base, boolean debug) throws UnsupportedEncodingException {1147 if (base == null) {1148 return base;1149 }1150 if ("".equals(base)) {1151 return base;1152 }1153 String result = base;1154 String ssE = URLDecoder.decode(base, UTF8);1155 // System.out.println("*" + base + "*");1156 // System.out.println("-" + ssE + "-");1157 if (base.equals(ssE)) {1158 result = URLEncoder.encode(base, UTF8);1159 if (debug) {1160 System.out.println(base + " chunk needs to be encoded => " + result);1161 }1162 } else {1163 if (debug) {1164 System.out.println(base + " chunk already encoded");1165 }1166 }1167 return result;1168 }1169 1170 public static URL normalizeUrl(URL u, boolean debug) throws MalformedURLException, UnsupportedEncodingException {1171 if (u == null) {1172 return null;1173 }1174 String protocol = u.getProtocol();1175 if (protocol == null || "file".equals(protocol)) {1176 return u;1177 }1178 String file = u.getPath();1179 if (file == null) {1180 return u;1181 }1182 String host = u.getHost();1183 String ref = u.getRef();1184 int port = u.getPort();1185 String query = u.getQuery();1186 String[] qq = {};1187 if (query != null) {1188 qq = query.split(QUERY_DELIMITER);1189 }1190 String[] ss = file.split(PATH_DELIMITER);1191 int normalized = 0;1192 if (debug) {1193 System.out.println("normalizing path " + file + " in " + u.toString());1194 }1195 for (int i = 0; i < ss.length; i++) {1196 String base = ss[i];1197 String r = normalizeChunk(base, debug);1198 if (!r.equals(ss[i])) {1199 normalized++;1200 }1201 ss[i] = r;1202 }1203 if (debug) {1204 System.out.println("normalizing query " + query + " in " + u.toString());1205 }1206 for (int i = 0; i < qq.length; i++) {1207 String base = qq[i];1208 String r = normalizeChunk(base, debug);1209 if (!r.equals(qq[i])) {1210 normalized++;1211 }1212 qq[i] = r;1213 }1214 if (normalized == 0) {1215 if (debug) {1216 System.out.println("Nothing was normalized in this url");1217 }1218 return u;1219 } else {1220 if (debug) {1221 System.out.println(normalized + " chunks normalized, rejoining url");1222 }1223 }1224 StringBuilder composed = new StringBuilder("");1225 for (int i = 0; i < ss.length; i++) {1226 String string = ss[i];1227 if (ss.length <= 1 || (string != null && !"".equals(string))) {1228 composed.append(PATH_DELIMITER_MARK).append(string);1229 }1230 }1231 String composed1 = composed.toString();1232 if (query != null && !query.trim().equals("")) {1233 composed.append(QUERY_MARK);1234 for (int i = 0; i < qq.length; i++) {1235 String string = qq[i];1236 if ((string != null && !"".equals(string))) {1237 composed.append(string);1238 if (i != qq.length - 1) {1239 composed.append(QUERY_DELIMITER_MARK);1240 }1241 }1242 }1243 }1244 String composed2 = composed.substring(composed1.length() - 1);1245 if (ref != null && !ref.trim().equals("")) {1246 composed.append(HREF_MARK).append(ref);1247 }1248 1249 URL result = new URL(protocol, host, port, composed.toString());1250 1251 if (debug) {1252 System.out.println("normalized `" + composed1 + "` and `" + composed2 + "` in " + result.toString());1253 }1254 return result;1255 1256 }1257 1238 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/ResourceUrlCreator.java
r348 r429 39 39 40 40 import java.net.MalformedURLException; 41 import java.net.URI; 42 import java.net.URISyntaxException; 41 43 import java.net.URL; 44 import java.net.URLDecoder; 45 import java.net.URLEncoder; 42 46 import java.util.LinkedList; 43 47 import java.util.List; 48 import java.io.UnsupportedEncodingException; 44 49 45 50 import net.sourceforge.jnlp.DownloadOptions; … … 59 64 * The Resources may not be downloadable from any of them. The returned order is the order 60 65 * the urls should be attempted in. 61 * @return 66 * @return a list of URLs that the resources might be downloadable from 62 67 */ 63 68 public List<URL> getUrls() { … … 90 95 } 91 96 92 url = getVersionedUrl UsingQuery(resource);97 url = getVersionedUrl(); 93 98 urls.add(url); 94 99 … … 103 108 * @param usePack whether the URL should point to the pack200 file 104 109 * @param useVersion whether the URL should be modified to include the version 105 * @return a URL for the resource or null if an appropr aite URL can not be found110 * @return a URL for the resource or null if an appropriate URL can not be found 106 111 */ 107 protectedURL getUrl(Resource resource, boolean usePack, boolean useVersion) {112 static URL getUrl(Resource resource, boolean usePack, boolean useVersion) { 108 113 if (!(usePack || useVersion)) { 109 114 throw new IllegalArgumentException("either pack200 or version required"); … … 117 122 String filename = location.substring(lastSlash + 1); 118 123 if (useVersion && resource.requestVersion != null) { 119 String parts[] = filename.split("\\.", 2); 120 String name = parts[0]; 121 String extension = parts[1]; 122 filename = name + "__V" + resource.requestVersion + "." + extension; 124 // With 'useVersion', j2-commons-cli.jar becomes, for example, j2-commons-cli__V1.0.jar 125 String parts[] = filename.split("\\.", -1 /* Keep blank strings*/); 126 127 StringBuilder sb = new StringBuilder(); 128 for (int i = 0; i < parts.length; i++) { 129 sb.append(parts[i]); 130 // Append __V<number> before last '.' 131 if (i == parts.length -2) { 132 sb.append("__V" + resource.requestVersion); 133 } 134 sb.append('.'); 135 } 136 sb.setLength(sb.length() - 1); // remove last '.' 137 138 filename = sb.toString(); 123 139 } 124 140 if (usePack) { … … 136 152 137 153 /** 138 * Returns the URL for a resource, relying on HTTP query for getting the 139 * right version 140 * 141 * @param resource the resource to get the url for 154 * Returns the URL for this resource, including the resource's version number in the query string 142 155 */ 143 protected URL getVersionedUrlUsingQuery(Resource resource) { 144 String actualLocation = resource.getLocation().getProtocol() + "://" 145 + resource.getLocation().getHost(); 146 if (resource.getLocation().getPort() != -1) { 147 actualLocation += ":" + resource.getLocation().getPort(); 156 protected URL getVersionedUrl() { 157 URL resourceUrl = resource.getLocation(); 158 String protocol = uriPartToString(resourceUrl.getProtocol()) + "://"; 159 String userInfo = uriPartToString(resourceUrl.getUserInfo()); 160 if (!userInfo.isEmpty()) { 161 userInfo += "@"; 148 162 } 149 actualLocation += resource.getLocation().getPath(); 150 if (resource.requestVersion != null 151 && resource.requestVersion.isVersionId()) { 152 actualLocation += "?version-id=" + resource.requestVersion; 163 String host = uriPartToString(resourceUrl.getHost()); 164 String port; 165 if (resourceUrl.getPort() == -1) { 166 port = ""; 167 } else { 168 port = ":" + String.valueOf(resourceUrl.getPort()); 153 169 } 154 URL versionedURL; 170 String path = uriPartToString(resourceUrl.getPath()); 171 String query = uriPartToString(resourceUrl.getQuery()); 172 if (!query.isEmpty()) { 173 query = "?" + query; 174 } 175 if (resource.requestVersion != null && resource.requestVersion.isVersionId()) { 176 if (!query.isEmpty()) { 177 query += "&"; 178 } else { 179 query = "?" + query; 180 } 181 query += "version-id=" + resource.requestVersion; 182 } 155 183 try { 156 versionedURL = new URL(actualLocation); 184 URL url = new URL(protocol + userInfo + host + port + path + query); 185 return url; 157 186 } catch (MalformedURLException e) { 158 return resource .getLocation();187 return resourceUrl; 159 188 } 160 return versionedURL; 189 } 190 191 private static String uriPartToString(String part) { 192 if (part == null) 193 return ""; 194 return part; 161 195 } 162 196 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/UpdatePolicy.java
r348 r429 19 19 /** 20 20 * A policy that determines when a resource should be checked for 21 * an updated version. <p>21 * an updated version. 22 22 * 23 23 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author -
trunk/icedtea-web/netx/net/sourceforge/jnlp/config/BasicValueValidators.java
r372 r429 38 38 package net.sourceforge.jnlp.config; 39 39 40 import java.io.File; 40 41 import static net.sourceforge.jnlp.runtime.Translator.R; 41 42 … … 88 89 * file may or may not exist 89 90 */ 90 private static class FilePathValidator implements ValueValidator { 91 91 //package private for testing purposes 92 static class FilePathValidator implements ValueValidator { 93 92 94 @Override 93 95 public void validate(Object value) throws IllegalArgumentException { … … 99 101 100 102 if (!(possibleValue instanceof String)) { 101 throw new IllegalArgumentException( );103 throw new IllegalArgumentException("Value should be string!"); 102 104 } 103 105 104 106 String possibleFile = (String) possibleValue; 105 if (Defaults.OS_DOS_LIKE) { 106 if (!(Character.isLetter(possibleFile.charAt(0)) && 107 possibleFile.charAt(1) == ':' && 108 (possibleFile.charAt(2) == File.separatorChar || 109 possibleFile.charAt(2) == '/'))) { 110 throw new IllegalArgumentException(); 111 } 112 } 113 else 114 if (!(possibleFile.startsWith("/"))) { 115 throw new IllegalArgumentException(); 116 } 117 118 } 119 120 @Override 121 public String getPossibleValues() { 122 return Defaults.OS_DOS_LIKE ? R("VVPossibleFileValuesDOS") : R("VVPossibleFileValues"); 107 108 boolean absolute = new File(possibleFile).isAbsolute(); 109 if (!absolute) { 110 throw new IllegalArgumentException("File must be absolute"); 111 } 112 113 } 114 115 @Override 116 public String getPossibleValues() { 117 return R("VVPossibleFileValues"); 123 118 } 124 119 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/config/Defaults.java
r397 r429 43 43 import java.util.HashMap; 44 44 import java.util.Map; 45 import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel; 45 46 46 47 import net.sourceforge.jnlp.ShortcutDesc; … … 51 52 */ 52 53 public class Defaults { 54 55 final static String SYSTEM_HOME = System.getProperty("java.home"); 56 final static String SYSTEM_SECURITY = SYSTEM_HOME + File.separator + "lib" + File.separator + "security"; 57 final static String USER_CONFIG_HOME; 58 public final static String USER_CACHE_HOME; 59 final static String USER_SECURITY; 60 final static String LOCKS_DIR = System.getProperty("java.io.tmpdir") + File.separator 61 + System.getProperty("user.name") + File.separator + "netx" + File.separator 62 + "locks"; 63 final static File userFile; 64 65 static { 66 String configHome = System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_CONFIG_DIR; 67 String cacheHome = System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_CACHE_DIR; 68 String XDG_CONFIG_HOME = System.getenv("XDG_CONFIG_HOME"); 69 String XDG_CACHE_HOME = System.getenv("XDG_CACHE_HOME"); 70 if (XDG_CONFIG_HOME != null) { 71 configHome = XDG_CONFIG_HOME + File.separator + DeploymentConfiguration.DEPLOYMENT_SUBDIR_DIR; 72 } 73 if (XDG_CACHE_HOME != null) { 74 cacheHome = XDG_CACHE_HOME + File.separator + DeploymentConfiguration.DEPLOYMENT_SUBDIR_DIR; 75 } 76 USER_CONFIG_HOME = configHome; 77 USER_CACHE_HOME = cacheHome; 78 USER_SECURITY = USER_CONFIG_HOME + File.separator + "security"; 79 userFile = new File(USER_CONFIG_HOME + File.separator + DeploymentConfiguration.DEPLOYMENT_PROPERTIES); 80 } 53 81 54 82 /** … … 63 91 */ 64 92 public static Map<String, Setting<String>> getDefaults() { 65 File userFile = new File(System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_DIR66 + File.separator + DeploymentConfiguration.DEPLOYMENT_PROPERTIES);67 68 93 SecurityManager sm = System.getSecurityManager(); 69 94 if (sm != null) { … … 71 96 } 72 97 73 final String SYSTEM_HOME = System.getProperty("java.home");74 final String SYSTEM_SECURITY = SYSTEM_HOME + File.separator + "lib" + File.separator + "security";75 76 final String USER_HOME = System.getProperty("user.home") + File.separator + DeploymentConfiguration.DEPLOYMENT_DIR;77 final String USER_SECURITY = USER_HOME + File.separator + "security";78 79 final String LOCKS_DIR = System.getProperty("java.io.tmpdir") + File.separator80 + System.getProperty("user.name") + File.separator + "netx" + File.separator81 + "locks";82 98 83 99 /* … … 97 113 DeploymentConfiguration.KEY_USER_CACHE_DIR, 98 114 BasicValueValidators.getFilePathValidator(), 99 USER_ HOME + File.separator + "cache"115 USER_CACHE_HOME + File.separator + "cache" 100 116 }, 101 117 { 102 118 DeploymentConfiguration.KEY_USER_PERSISTENCE_CACHE_DIR, 103 119 BasicValueValidators.getFilePathValidator(), 104 USER_ HOME + File.separator + "pcache"120 USER_CACHE_HOME + File.separator + "pcache" 105 121 }, 106 122 { … … 112 128 DeploymentConfiguration.KEY_USER_LOG_DIR, 113 129 BasicValueValidators.getFilePathValidator(), 114 USER_ HOME + File.separator + "log"130 USER_CONFIG_HOME + File.separator + "log" 115 131 }, 116 132 { 117 133 DeploymentConfiguration.KEY_USER_TMP_DIR, 118 134 BasicValueValidators.getFilePathValidator(), 119 USER_ HOME + File.separator + "tmp"135 USER_CACHE_HOME + File.separator + "tmp" 120 136 }, 121 137 { … … 329 345 DeploymentConfiguration.CONSOLE_DISABLE, 330 346 DeploymentConfiguration.CONSOLE_HIDE, 331 DeploymentConfiguration.CONSOLE_SHOW 347 DeploymentConfiguration.CONSOLE_SHOW, 348 DeploymentConfiguration.CONSOLE_SHOW_PLUGIN, 349 DeploymentConfiguration.CONSOLE_SHOW_JAVAWS 332 350 }), 333 351 DeploymentConfiguration.CONSOLE_HIDE 334 352 }, 335 /* tracing and logging */336 {337 DeploymentConfiguration.KEY_ENABLE_TRACING,338 BasicValueValidators.getBooleanValidator(),339 String.valueOf(false)340 },341 353 { 342 354 DeploymentConfiguration.KEY_ENABLE_LOGGING, 343 355 BasicValueValidators.getBooleanValidator(), 344 356 String.valueOf(false) 357 }, 358 { 359 DeploymentConfiguration.KEY_ENABLE_LOGGING_HEADERS, 360 BasicValueValidators.getBooleanValidator(), 361 String.valueOf(false) 362 }, 363 { 364 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOFILE, 365 BasicValueValidators.getBooleanValidator(), 366 String.valueOf(false) 367 }, 368 { 369 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSTREAMS, 370 BasicValueValidators.getBooleanValidator(), 371 String.valueOf(true) 372 }, 373 { 374 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSYSTEMLOG, 375 BasicValueValidators.getBooleanValidator(), 376 String.valueOf(true) 345 377 }, 346 378 /* JNLP association */ … … 386 418 BasicValueValidators.getRangedIntegerValidator(0, 10000), 387 419 String.valueOf(500) 420 }, 421 //JVM arguments for plugin 422 { 423 DeploymentConfiguration.KEY_PLUGIN_JVM_ARGUMENTS, 424 null, 425 null 426 }, 427 //unsigned applet security level 428 { 429 DeploymentConfiguration.KEY_SECURITY_LEVEL, 430 new SecurityValueValidator(), 431 null 432 }, 433 //JVM executable for itw 434 { 435 DeploymentConfiguration.KEY_JRE_DIR, 436 null, 437 null 438 }, 439 //enable manifest-attributes checks 440 { 441 DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, 442 BasicValueValidators.getBooleanValidator(), 443 String.valueOf(true) 388 444 } 389 445 }; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java
r348 r429 37 37 38 38 import javax.naming.ConfigurationException; 39 39 import javax.swing.JOptionPane; 40 41 import net.sourceforge.jnlp.cache.CacheLRUWrapper; 40 42 import net.sourceforge.jnlp.runtime.JNLPRuntime; 41 43 import net.sourceforge.jnlp.util.FileUtils; 44 import net.sourceforge.jnlp.util.logging.OutputController; 42 45 43 46 /** … … 49 52 public final class DeploymentConfiguration { 50 53 51 public static final String DEPLOYMENT_DIR = ".icedtea"; 52 public static final String DEPLOYMENT_CONFIG = "deployment.config"; 54 public static final String DEPLOYMENT_SUBDIR_DIR = "icedtea-web"; 55 public static final String DEPLOYMENT_CACHE_DIR = ".cache" + File.separator + DEPLOYMENT_SUBDIR_DIR; 56 public static final String DEPLOYMENT_CONFIG_DIR = ".config" + File.separator + DEPLOYMENT_SUBDIR_DIR; 57 public static final String DEPLOYMENT_CONFIG_FILE = "deployment.config"; 53 58 public static final String DEPLOYMENT_PROPERTIES = "deployment.properties"; 59 public static final String APPLET_TRUST_SETTINGS = ".appletTrustSettings"; 54 60 55 61 public static final String DEPLOYMENT_COMMENT = "Netx deployment configuration"; … … 60 66 public static final int JNLP_ASSOCIATION_REPLACE_ASK = 3; 61 67 62 /* 63 * FIXME these should be moved into JavaConsole, but there is a strange 64 * dependency in the build system. First all of netx is built. Then the 65 * plugin is built. So we cannot refer to plugin code in here :( 68 /** 69 * when set to as value of KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode", 70 * then console is not visible by default, but may be shown 66 71 */ 67 72 public static final String CONSOLE_HIDE = "HIDE"; 73 /** 74 * when set to as value of KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode", 75 * then console show for both javaws and plugin 76 */ 68 77 public static final String CONSOLE_SHOW = "SHOW"; 78 /** 79 * when set to as value of KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode", 80 * then console is not visible by default, nop data are passed to it (save memory and cpu) but can not be shown 81 */ 69 82 public static final String CONSOLE_DISABLE = "DISABLE"; 83 /** 84 * when set to as value of KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode", 85 * then console show for plugin 86 */ 87 public static final String CONSOLE_SHOW_PLUGIN = "SHOW_PLUGIN_ONLY"; 88 /** 89 * when set to as value of KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode", 90 * then console show for javaws 91 */ 92 public static final String CONSOLE_SHOW_JAVAWS = "SHOW_JAVAWS_ONLY"; 70 93 71 94 public static final String KEY_USER_CACHE_DIR = "deployment.user.cachedir"; … … 106 129 public static final String KEY_SECURITY_PROMPT_USER = "deployment.security.askgrantdialog.show"; 107 130 131 //enum of AppletSecurityLevel in result 132 public static final String KEY_SECURITY_LEVEL = "deployment.security.level"; 133 108 134 public static final String KEY_SECURITY_TRUSTED_POLICY = "deployment.security.trusted.policy"; 109 135 … … 120 146 * Networking 121 147 */ 148 149 /** the proxy type. possible values are {@code JNLPProxySelector.PROXY_TYPE_*} */ 122 150 public static final String KEY_PROXY_TYPE = "deployment.proxy.type"; 151 152 /** Boolean. If true, the http host/port should be used for https and ftp as well */ 123 153 public static final String KEY_PROXY_SAME = "deployment.proxy.same"; 154 124 155 public static final String KEY_PROXY_AUTO_CONFIG_URL = "deployment.proxy.auto.config.url"; 125 156 public static final String KEY_PROXY_BYPASS_LIST = "deployment.proxy.bypass.list"; … … 136 167 137 168 /* 138 * Tracing and Logging 139 */ 140 public static final String KEY_ENABLE_TRACING = "deployment.trace"; 141 public static final String KEY_ENABLE_LOGGING = "deployment.log"; 142 169 * Logging 170 */ 171 public static final String KEY_ENABLE_LOGGING = "deployment.log"; //same as verbose or ICEDTEAPLUGIN_DEBUG=true 172 public static final String KEY_ENABLE_LOGGING_HEADERS = "deployment.log.headers"; //will add header OutputContorll.getHeader To all messages 173 public static final String KEY_ENABLE_LOGGING_TOFILE = "deployment.log.file"; 174 public static final String KEY_ENABLE_LOGGING_TOSTREAMS = "deployment.log.stdstreams"; 175 public static final String KEY_ENABLE_LOGGING_TOSYSTEMLOG = "deployment.log.system"; 176 143 177 /* 144 * Console 178 * manifest check 179 */ 180 public static final String KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK = "deployment.manifest.attributes.check"; 181 182 /** 183 * Console initial status. 184 * One of CONSOLE_* values 185 * See declaration above: 186 * CONSOLE_HIDE = "HIDE"; 187 * CONSOLE_SHOW = "SHOW"; 188 * CONSOLE_DISABLE = "DISABLE"; 189 * CONSOLE_SHOW_PLUGIN = "SHOW_PLUGIN_ONLY"; 190 * CONSOLE_SHOW_JAVAWS = "SHOW_JAVAWS_ONLY"; 145 191 */ 146 192 public static final String KEY_CONSOLE_STARTUP_MODE = "deployment.console.startup.mode"; 193 194 147 195 148 196 /* … … 159 207 public static final String KEY_UPDATE_TIMEOUT = "deployment.javaws.update.timeout"; 160 208 209 /* 210 * JVM arguments for plugin 211 */ 212 public static final String KEY_PLUGIN_JVM_ARGUMENTS= "deployment.plugin.jvm.arguments"; 213 public static final String KEY_JRE_DIR= "deployment.jre.dir"; 214 private ConfigurationException loadingException = null; 215 216 public void setLoadingException(ConfigurationException ex) { 217 loadingException = ex; 218 } 219 220 public ConfigurationException getLoadingException() { 221 return loadingException; 222 } 223 224 public void resetToDefaults() { 225 currentConfiguration = Defaults.getDefaults(); 226 } 227 228 161 229 public enum ConfigType { 162 230 System, User … … 166 234 private boolean systemPropertiesMandatory = false; 167 235 168 /** The system's deployment.config file */236 /** The system's subdirResult deployment.config file */ 169 237 private File systemPropertiesFile = null; 170 /** The user's deployment.config file */238 /** The user's subdirResult deployment.config file */ 171 239 private File userPropertiesFile = null; 240 241 /*default user file*/ 242 public static final File USER_DEPLOYMENT_PROPERTIES_FILE = new File(Defaults.USER_CONFIG_HOME + File.separator + DEPLOYMENT_PROPERTIES); 172 243 173 244 /** the current deployment properties */ … … 186 257 * Generally, it will try to continue and ignore errors it finds (such as file not found). 187 258 * 188 * @throws DeploymentException if it encounters a fatal error.259 * @throws ConfigurationException if it encounters a fatal error. 189 260 */ 190 261 public void load() throws ConfigurationException { … … 192 263 } 193 264 265 public static File getAppletTrustUserSettingsPath() { 266 return new File(Defaults.USER_CONFIG_HOME + File.separator + APPLET_TRUST_SETTINGS); 267 } 268 269 public static File getAppletTrustGlobalSettingsPath() { 270 return new File(File.separator + "etc" + File.separator + ".java" + File.separator 271 + "deployment" + File.separator + APPLET_TRUST_SETTINGS); 272 273 } 274 194 275 /** 195 276 * Initialize this deployment configuration by reading configuration files. … … 198 279 * @param fixIssues If true, fix issues that are discovered when reading configuration by 199 280 * resorting to the default values 200 * @throws DeploymentException if it encounters a fatal error.281 * @throws ConfigurationException if it encounters a fatal error. 201 282 */ 202 283 public void load(boolean fixIssues) throws ConfigurationException { 203 284 // make sure no state leaks if security check fails later on 204 File userFile = new File(System.getProperty("user.home") + File.separator + DEPLOYMENT_DIR 205 + File.separator + DEPLOYMENT_PROPERTIES); 285 File userFile = new File(USER_DEPLOYMENT_PROPERTIES_FILE.getAbsolutePath()); 206 286 207 287 SecurityManager sm = System.getSecurityManager(); … … 210 290 } 211 291 292 File systemConfigFile = findSystemConfigFile(); 293 294 load(systemConfigFile, userFile, fixIssues); 295 } 296 297 void load(File systemConfigFile, File userFile, boolean fixIssues) throws ConfigurationException { 212 298 Map<String, Setting<String>> initialProperties = Defaults.getDefaults(); 213 299 … … 215 301 216 302 /* 217 * First, try to read the system's deployment.config file to find if303 * First, try to read the system's subdirResult deployment.config file to find if 218 304 * there is a system-level deployment.poperties file 219 305 */ 220 306 221 File systemConfigFile = findSystemConfigFile();222 307 if (systemConfigFile != null) { 223 308 if (loadSystemConfiguration(systemConfigFile)) { 224 if (JNLPRuntime.isDebug()) { 225 System.out.println("System level " + DEPLOYMENT_CONFIG + " is mandatory: " + systemPropertiesMandatory); 226 } 309 OutputController.getLogger().log("System level " + DEPLOYMENT_CONFIG_FILE + " is mandatory: " + systemPropertiesMandatory); 227 310 /* Second, read the System level deployment.properties file */ 228 311 systemProperties = loadProperties(ConfigType.System, systemPropertiesFile, … … 242 325 243 326 /* 244 * Third, read the user's deployment.properties file327 * Third, read the user's subdirResult deployment.properties file 245 328 */ 246 329 userPropertiesFile = userFile; … … 258 341 259 342 /** 343 * Copies the current configuration into the target 344 */ 345 public void copyTo(Properties target) { 346 Set<String> names = getAllPropertyNames(); 347 348 for (String name : names) { 349 String value = getProperty(name); 350 // for Properties, missing and null are identical 351 if (value != null) { 352 target.setProperty(name, value); 353 } 354 } 355 } 356 357 /** 260 358 * Get the value for the given key 261 359 * … … 347 445 Setting<String> s = initial.get(key); 348 446 if (!(s.getName().equals(key))) { 349 System.out.println(R("DCInternal", "key " + key + " does not match setting name " + s.getName()));447 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("DCInternal", "key " + key + " does not match setting name " + s.getName())); 350 448 } else if (!defaults.containsKey(key)) { 351 System.out.println(R("DCUnknownSettingWithName", key));449 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("DCUnknownSettingWithName", key)); 352 450 } else { 353 451 ValueValidator checker = defaults.get(key).getValidator(); … … 359 457 checker.validate(s.getValue()); 360 458 } catch (IllegalArgumentException e) { 361 System.out.println(R("DCIncorrectValue", key, s.getValue(), checker.getPossibleValues()));459 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("DCIncorrectValue", key, s.getValue(), checker.getPossibleValues())); 362 460 s.setValue(s.getDefaultValue()); 461 OutputController.getLogger().log(e); 363 462 } 364 463 } … … 371 470 private File findSystemConfigFile() { 372 471 File etcFile = new File(File.separator + "etc" + File.separator + ".java" + File.separator 373 + "deployment" + File.separator + DEPLOYMENT_CONFIG );472 + "deployment" + File.separator + DEPLOYMENT_CONFIG_FILE); 374 473 if (etcFile.isFile()) { 375 474 return etcFile; 376 475 } 377 476 378 File jreFile = new File(System.getProperty("java.home") + File.separator + "lib" 379 + File.separator + DEPLOYMENT_CONFIG); 477 String jrePath = null; 478 try { 479 Map<String, Setting<String>> tmpProperties = parsePropertiesFile(USER_DEPLOYMENT_PROPERTIES_FILE); 480 Setting<String> jreSetting = tmpProperties.get(KEY_JRE_DIR); 481 if (jreSetting != null) { 482 jrePath = jreSetting.getValue(); 483 } 484 } catch (Exception ex) { 485 OutputController.getLogger().log(ex); 486 } 487 488 File jreFile; 489 if (jrePath != null) { 490 jreFile = new File(jrePath + File.separator + "lib" 491 + File.separator + DEPLOYMENT_CONFIG_FILE); 492 } else { 493 jreFile = new File(System.getProperty("java.home") + File.separator + "lib" 494 + File.separator + DEPLOYMENT_CONFIG_FILE); 495 } 380 496 if (jreFile.isFile()) { 381 497 return jreFile; … … 389 505 * system-properties related variables 390 506 */ 391 private boolean loadSystemConfiguration(File configFile) { 392 393 if (JNLPRuntime.isDebug()) { 394 System.out.println("Loading system configuation from: " + configFile); 395 } 507 private boolean loadSystemConfiguration(File configFile) throws ConfigurationException { 508 509 OutputController.getLogger().log("Loading system configuation from: " + configFile); 396 510 397 511 Map<String, Setting<String>> systemConfiguration = new HashMap<String, Setting<String>>(); … … 399 513 systemConfiguration = parsePropertiesFile(configFile); 400 514 } catch (IOException e) { 401 if (JNLPRuntime.isDebug()) { 402 System.out.println("No System level " + DEPLOYMENT_PROPERTIES + " found."); 403 } 515 OutputController.getLogger().log("No System level " + DEPLOYMENT_CONFIG_FILE + " found."); 516 OutputController.getLogger().log(e); 404 517 return false; 405 518 } … … 409 522 * completely 410 523 */ 411 524 String urlString = null; 412 525 try { 413 String urlString = systemConfiguration.get("deployment.system.config").getValue(); 414 if (urlString == null) { 415 if (JNLPRuntime.isDebug()) { 416 System.out.println("No System level " + DEPLOYMENT_PROPERTIES + " found."); 417 } 526 Setting<String> urlSettings = systemConfiguration.get("deployment.system.config"); 527 if (urlSettings == null || urlSettings.getValue() == null) { 528 OutputController.getLogger().log("No System level " + DEPLOYMENT_PROPERTIES + " found in "+configFile.getAbsolutePath()); 418 529 return false; 419 530 } 531 urlString = urlSettings.getValue(); 532 Setting<String> mandatory = systemConfiguration.get("deployment.system.config.mandatory"); 533 systemPropertiesMandatory = Boolean.valueOf(mandatory == null ? null : mandatory.getValue()); //never null 534 OutputController.getLogger().log("System level settings " + DEPLOYMENT_PROPERTIES + " are mandatory:" + systemPropertiesMandatory); 420 535 URL url = new URL(urlString); 421 536 if (url.getProtocol().equals("file")) { 422 537 systemPropertiesFile = new File(url.getFile()); 423 if (JNLPRuntime.isDebug()) { 424 System.out.println("Using System level" + DEPLOYMENT_PROPERTIES + ": " 425 + systemPropertiesFile); 426 } 427 Setting<String> mandatory = systemConfiguration.get("deployment.system.config.mandatory"); 428 systemPropertiesMandatory = Boolean.valueOf(mandatory == null ? null : (String) mandatory.getValue()); 538 OutputController.getLogger().log("Using System level" + DEPLOYMENT_PROPERTIES + ": " + systemPropertiesFile); 429 539 return true; 430 540 } else { 431 if (JNLPRuntime.isDebug()) { 432 System.out.println("Remote + " + DEPLOYMENT_PROPERTIES + " not supported"); 433 } 541 OutputController.getLogger().log("Remote + " + DEPLOYMENT_PROPERTIES + " not supported: " + urlString + "in " + configFile.getAbsolutePath()); 434 542 return false; 435 543 } 436 544 } catch (MalformedURLException e) { 437 if (JNLPRuntime.isDebug()) { 438 System.out.println("Invalid url for " + DEPLOYMENT_PROPERTIES); 439 } 440 return false; 545 OutputController.getLogger().log("Invalid url for " + DEPLOYMENT_PROPERTIES+ ": " + urlString + "in " + configFile.getAbsolutePath()); 546 OutputController.getLogger().log(e); 547 if (systemPropertiesMandatory){ 548 ConfigurationException ce = new ConfigurationException("Invalid url to system properties, which are mandatory"); 549 ce.initCause(e); 550 throw ce; 551 } else { 552 return false; 553 } 441 554 } 442 555 } … … 454 567 throws ConfigurationException { 455 568 if (file == null || !file.isFile()) { 456 if (JNLPRuntime.isDebug()) { 457 System.out.println("No " + type.toString() + " level " + DEPLOYMENT_PROPERTIES + " found."); 458 } 569 OutputController.getLogger().log("No " + type.toString() + " level " + DEPLOYMENT_PROPERTIES + " found."); 459 570 if (!mandatory) { 460 571 return null; … … 464 575 } 465 576 466 if (JNLPRuntime.isDebug()) { 467 System.out.println("Loading " + type.toString() + " level properties from: " + file); 468 } 577 OutputController.getLogger().log("Loading " + type.toString() + " level properties from: " + file); 469 578 try { 470 579 return parsePropertiesFile(file); 471 580 } catch (IOException e) { 581 if (mandatory){ 582 ConfigurationException ce = new ConfigurationException("Exception during loading of " + file + " which is mandatory to read"); 583 ce.initCause(e); 584 throw ce; 585 } 586 OutputController.getLogger().log(e); 472 587 return null; 473 588 } … … 490 605 } 491 606 492 if (JNLPRuntime.isDebug()) { 493 System.out.println("Saving properties into " + userPropertiesFile.toString()); 494 } 607 OutputController.getLogger().log("Saving properties into " + userPropertiesFile.toString()); 495 608 Properties toSave = new Properties(); 496 609 497 610 for (String key : currentConfiguration.keySet()) { 498 611 String oldValue = unchangeableConfiguration.get(key) == null ? null 499 : (String)unchangeableConfiguration.get(key).getValue();500 String newValue = currentConfiguration.get(key) == null ? null : (String)currentConfiguration612 : unchangeableConfiguration.get(key).getValue(); 613 String newValue = currentConfiguration.get(key) == null ? null : currentConfiguration 501 614 .get(key).getValue(); 502 615 if (oldValue == null && newValue == null) { … … 533 646 * 534 647 * @param propertiesFile the file to read Properties from 535 * @param destination the map to which all the properties should be added536 648 * @throws IOException if an IO problem occurs 537 649 */ … … 608 720 @SuppressWarnings("unused") 609 721 private static void dumpConfiguration(Map<String, Setting<String>> config, PrintStream out) { 610 System.out.println("KEY: VALUE [Locked]");722 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "KEY: VALUE [Locked]"); 611 723 612 724 for (String key : config.keySet()) { … … 616 728 } 617 729 } 730 731 public static void move14AndOlderFilesTo15StructureCatched() { 732 try { 733 move14AndOlderFilesTo15Structure(); 734 } catch (Throwable t) { 735 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Critical error during converting old files to new. Continuing"); 736 OutputController.getLogger().log(t); 737 } 738 739 } 740 741 private static void move14AndOlderFilesTo15Structure() { 742 int errors = 0; 743 String PRE_15_DEPLOYMENT_DIR = ".icedtea"; 744 String LEGACY_USER_HOME = System.getProperty("user.home") + File.separator + PRE_15_DEPLOYMENT_DIR; 745 File configDir = new File(Defaults.USER_CONFIG_HOME); 746 File cacheDir = new File(Defaults.USER_CACHE_HOME); 747 File legacyUserDir = new File(LEGACY_USER_HOME); 748 if (legacyUserDir.exists()) { 749 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Legacy configuration and cache found. Those will be now transported to new locations"); 750 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Defaults.USER_CONFIG_HOME + " and " + Defaults.USER_CACHE_HOME); 751 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "You should not see this message next time you run icedtea-web!"); 752 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Your custom dirs will not be touched and will work"); 753 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "-----------------------------------------------"); 754 755 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Preparing new directories:"); 756 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, " " + Defaults.USER_CONFIG_HOME); 757 errors += resultToStd(configDir.mkdirs()); 758 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, " " + Defaults.USER_CACHE_HOME); 759 errors += resultToStd(cacheDir.mkdirs()); 760 761 String legacySecurity = LEGACY_USER_HOME + File.separator + "security"; 762 String currentSecurity = Defaults.USER_SECURITY; 763 errors += moveLegacyToCurrent(legacySecurity, currentSecurity); 764 765 String legacyCache = LEGACY_USER_HOME + File.separator + "cache"; 766 String currentCache = Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_CACHE_DIR).getDefaultValue(); 767 errors += moveLegacyToCurrent(legacyCache, currentCache); 768 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Adapting " + CacheLRUWrapper.CACHE_INDEX_FILE_NAME + " to new destination"); 769 //replace all legacyCache by currentCache in new recently_used 770 try { 771 File f = new File(currentCache, CacheLRUWrapper.CACHE_INDEX_FILE_NAME); 772 String s = FileUtils.loadFileAsString(f); 773 s = s.replace(legacyCache, currentCache); 774 FileUtils.saveFile(s, f); 775 } catch (IOException ex) { 776 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, ex); 777 errors++; 778 } 779 780 String legacyPcahceDir = LEGACY_USER_HOME + File.separator + "pcache"; 781 String currentPcacheDir = Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_PERSISTENCE_CACHE_DIR).getDefaultValue(); 782 errors += moveLegacyToCurrent(legacyPcahceDir, currentPcacheDir); 783 784 String legacyLogDir = LEGACY_USER_HOME + File.separator + "log"; 785 String currentLogDir = Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_LOG_DIR).getDefaultValue(); 786 errors += moveLegacyToCurrent(legacyLogDir, currentLogDir); 787 788 String legacyProperties = LEGACY_USER_HOME + File.separator + DEPLOYMENT_PROPERTIES; 789 String currentProperties = Defaults.USER_CONFIG_HOME + File.separator + DEPLOYMENT_PROPERTIES; 790 errors += moveLegacyToCurrent(legacyProperties, currentProperties); 791 792 String legacyPropertiesOld = LEGACY_USER_HOME + File.separator + DEPLOYMENT_PROPERTIES + ".old"; 793 String currentPropertiesOld = Defaults.USER_CONFIG_HOME + File.separator + DEPLOYMENT_PROPERTIES + ".old"; 794 errors += moveLegacyToCurrent(legacyPropertiesOld, currentPropertiesOld); 795 796 797 String legacyAppletTrust = LEGACY_USER_HOME + File.separator + APPLET_TRUST_SETTINGS; 798 String currentAppletTrust = getAppletTrustUserSettingsPath().getAbsolutePath(); 799 errors += moveLegacyToCurrent(legacyAppletTrust, currentAppletTrust); 800 801 String legacyTmp = LEGACY_USER_HOME + File.separator + "tmp"; 802 String currentTmp = Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_TMP_DIR).getDefaultValue(); 803 errors += moveLegacyToCurrent(legacyTmp, currentTmp); 804 805 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Removing now empty " + LEGACY_USER_HOME); 806 errors += resultToStd(legacyUserDir.delete()); 807 808 if (errors != 0) { 809 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "There occureed " + errors + " errors"); 810 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Please double check content of old data in " + LEGACY_USER_HOME + " with "); 811 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "new " + Defaults.USER_CONFIG_HOME + " and " + Defaults.USER_CACHE_HOME); 812 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "To disable this check again, please remove " + LEGACY_USER_HOME); 813 } 814 815 } else { 816 OutputController.getLogger().log("System is already following XDG .cache and .config specifications"); 817 try { 818 OutputController.getLogger().log("config: " + Defaults.USER_CONFIG_HOME + " file exists: " + configDir.exists()); 819 } catch (Exception ex) { 820 OutputController.getLogger().log(ex); 821 } 822 try { 823 OutputController.getLogger().log("cache: " + Defaults.USER_CACHE_HOME + " file exists:" + cacheDir.exists()); 824 } catch (Exception ex) { 825 OutputController.getLogger().log(ex); 826 } 827 } 828 //this call should endure even if (ever) will migration code be removed 829 DirectoryValidator.DirectoryCheckResults r = new DirectoryValidator().ensureDirs(); 830 if (!JNLPRuntime.isHeadless()) { 831 if (r.getFailures() > 0) { 832 JOptionPane.showMessageDialog(null, r.getMessage()); 833 } 834 } 835 836 } 837 838 private static int moveLegacyToCurrent(String legacy, String current) { 839 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Moving " + legacy + " to " + current); 840 File cf = new File(current); 841 File old = new File(legacy); 842 if (cf.exists()) { 843 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Warning! Destination " + current + " exists!"); 844 } 845 if (old.exists()) { 846 boolean moved = old.renameTo(cf); 847 return resultToStd(moved); 848 } else { 849 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "Source " + legacy + " do not exists, nothing to do"); 850 return 0; 851 } 852 853 } 854 855 private static int resultToStd(boolean securityMove) { 856 if (securityMove) { 857 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "OK"); 858 return 0; 859 } else { 860 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "ERROR"); 861 return 1; 862 } 863 } 618 864 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/config/Setting.java
r348 r429 68 68 * recognized setting, use null. 69 69 * @param value the initial value of this setting 70 * @param source the origin of the value (a file, or perhaps " <internal>")70 * @param source the origin of the value (a file, or perhaps "{@code <internal>}") 71 71 */ 72 72 public Setting(String name, String description, boolean locked, -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/AboutPanel.java
r348 r429 23 23 import java.awt.GridBagConstraints; 24 24 import java.awt.GridBagLayout; 25 import java.awt.event.ActionEvent; 26 import java.awt.event.ActionListener; 25 27 26 28 import javax.swing.Box; 29 import javax.swing.JButton; 27 30 import javax.swing.JLabel; 28 31 32 import net.sourceforge.jnlp.about.AboutDialog; 29 33 import net.sourceforge.jnlp.runtime.Translator; 30 34 … … 44 48 JLabel logo = new JLabel(); 45 49 JLabel aboutLabel = new JLabel("<html>" + Translator.R("CPAboutInfo") + "</html>"); 46 50 JButton aboutButton = new JButton(Translator.R("AboutDialogueTabAbout")); 51 aboutButton.addActionListener(new ActionListener() { 52 @Override 53 public void actionPerformed(ActionEvent e) { 54 AboutDialog.display(); 55 } 56 }); 47 57 c.fill = GridBagConstraints.BOTH; 48 58 c.gridy = 0; … … 54 64 c.weightx = 1; 55 65 add(aboutLabel, c); 56 66 c.fill = GridBagConstraints.NONE; 67 c.weighty = 0; 68 c.weightx = 0; 69 c.gridy++; 70 c.gridx=1; 71 add(aboutButton, c); 57 72 /* Keep all the elements at the top of the panel (Extra padding) */ 73 c.fill = GridBagConstraints.BOTH; 58 74 Component filler = Box.createRigidArea(new Dimension(1, 1)); 59 75 c.weighty = 1; 60 76 c.gridy++; 61 77 add(filler, c); 78 79 80 62 81 } 63 82 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java
r418 r429 33 33 import net.sourceforge.jnlp.runtime.Translator; 34 34 import net.sourceforge.jnlp.util.ImageResources; 35 import net.sourceforge.jnlp.util.ScreenFinder; 35 36 36 37 /** 37 38 * This dialog provides a means for user to edit more of the proxy settings. 38 39 * 39 * @author Andrew Su <asu@redhat.com, andrew.su@utoronto.ca>40 * @author Andrew Su <asu@redhat.com, andrew.su@utoronto.ca> 40 41 * 41 42 */ … … 107 108 */ 108 109 private void centerDialog() { 109 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 110 Dimension dialogSize = getSize(); 111 112 setLocation((screen.width - dialogSize.width) / 2, (screen.height - dialogSize.height) / 2); 110 ScreenFinder.centerWindowsToCurrentScreen(this); 113 111 } 114 112 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsPane.java
r348 r429 241 241 * Make the button panel. 242 242 * 243 * @return 243 * @return the button panel created 244 * @see JPanel 244 245 */ 245 246 private JPanel createButtonPanel() { -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/CachePane.java
r348 r429 1 1 /* CachePane.java -- Displays the specified folder and allows modification to its content. 2 Copyright (C) 201 0Red Hat2 Copyright (C) 2013 Red Hat 3 3 4 4 This program is free software; you can redistribute it and/or modify … … 20 20 import java.awt.BorderLayout; 21 21 import java.awt.Component; 22 import java.awt.Cursor; 22 23 import java.awt.Dimension; 24 import java.awt.EventQueue; 23 25 import java.awt.FlowLayout; 24 26 import java.awt.GridBagConstraints; 25 27 import java.awt.GridBagLayout; 26 28 import java.awt.GridLayout; 29 import java.awt.SystemColor; 30 import java.awt.Toolkit; 27 31 import java.awt.event.ActionEvent; 28 32 import java.awt.event.ActionListener; 33 import java.awt.event.WindowEvent; 29 34 import java.io.File; 30 35 import java.io.FileNotFoundException; … … 32 37 import java.nio.channels.FileLock; 33 38 import java.text.DateFormat; 34 import java.text.ParseException; 35 import java.text.SimpleDateFormat; 39 import java.text.NumberFormat; 36 40 import java.util.ArrayList; 37 41 import java.util.Comparator; 42 import java.util.Date; 38 43 import java.util.Enumeration; 39 44 import java.util.List; … … 42 47 import javax.swing.JComponent; 43 48 import javax.swing.JDialog; 49 import javax.swing.JOptionPane; 44 50 import javax.swing.JPanel; 45 51 import javax.swing.JScrollPane; 46 52 import javax.swing.JTable; 47 53 import javax.swing.ListSelectionModel; 48 import javax.swing.table.DefaultTableModel; 54 import javax.swing.event.ListSelectionEvent; 55 import javax.swing.event.ListSelectionListener; 56 import javax.swing.table.DefaultTableCellRenderer; 57 import javax.swing.table.TableModel; 49 58 import javax.swing.table.TableRowSorter; 50 59 51 60 import net.sourceforge.jnlp.cache.CacheDirectory; 61 import net.sourceforge.jnlp.cache.CacheLRUWrapper; 62 import net.sourceforge.jnlp.cache.CacheUtil; 52 63 import net.sourceforge.jnlp.cache.DirectoryNode; 53 64 import net.sourceforge.jnlp.config.DeploymentConfiguration; … … 55 66 import net.sourceforge.jnlp.util.FileUtils; 56 67 import net.sourceforge.jnlp.util.PropertiesFile; 68 import net.sourceforge.jnlp.util.logging.OutputController; 69 import net.sourceforge.jnlp.util.ui.NonEditableTableModel; 57 70 58 71 public class CachePane extends JPanel { 59 60 72 JDialog parent; 61 73 DeploymentConfiguration config; … … 63 75 private JComponent defaultFocusComponent; 64 76 DirectoryNode root; 65 String[] columns = { Translator.R("CVCPColName"), 77 String[] columns = { 78 Translator.R("CVCPColName"), 66 79 Translator.R("CVCPColPath"), 67 80 Translator.R("CVCPColType"), … … 70 83 Translator.R("CVCPColLastModified") }; 71 84 JTable cacheTable; 85 private JButton deleteButton, refreshButton, doneButton, cleanAll; 72 86 73 87 /** … … 94 108 c.fill = GridBagConstraints.BOTH; 95 109 96 DefaultTableModel model = new DefaultTableModel(columns, 0) { 97 public boolean isCellEditable(int row, int column) { 98 return false; 99 } 100 }; 110 TableModel model = new NonEditableTableModel(columns, 0); 101 111 102 112 cacheTable = new JTable(model); 103 113 cacheTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 114 cacheTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 115 @Override 116 final public void valueChanged(ListSelectionEvent listSelectionEvent) { 117 // If no row has been selected, disable the delete button, else enable it 118 if (cacheTable.getSelectionModel().isSelectionEmpty()) { 119 deleteButton.setEnabled(false); 120 } 121 else { 122 deleteButton.setEnabled(true); 123 } 124 } 125 }); 104 126 cacheTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN); 105 127 cacheTable.setPreferredScrollableViewportSize(new Dimension(600, 200)); … … 107 129 JScrollPane scrollPane = new JScrollPane(cacheTable); 108 130 109 populateTable(); 110 111 TableRowSorter<DefaultTableModel> tableSorter = new TableRowSorter<DefaultTableModel>(model); 112 tableSorter.setComparator(4, new Comparator<Long>() { // Comparator for size column. 113 @Override 114 public int compare(Long o1, Long o2) { 115 return o1.compareTo(o2); 116 } 117 }); 118 tableSorter.setComparator(5, new Comparator<String>() { // Comparator for date column. 119 @Override 120 public int compare(String o1, String o2) { 121 DateFormat format = new SimpleDateFormat("MM/dd/yyyy"); 122 try { 123 Long time1 = format.parse(o1).getTime(); 124 Long time2 = format.parse(o2).getTime(); 125 return time1.compareTo(time2); 126 } catch (ParseException e) { 127 return 0; 128 } 129 } 130 }); 131 TableRowSorter<TableModel> tableSorter = new TableRowSorter<TableModel>(model); 132 final Comparator<Comparable<?>> comparator = new Comparator<Comparable<?>>() { // General purpose Comparator 133 @Override 134 @SuppressWarnings("unchecked") 135 public final int compare(final Comparable a, final Comparable b) { 136 return a.compareTo(b); 137 } 138 }; 139 tableSorter.setComparator(1, comparator); // Comparator for path column. 140 tableSorter.setComparator(4, comparator); // Comparator for size column. 141 tableSorter.setComparator(5, comparator); // Comparator for modified column. 131 142 cacheTable.setRowSorter(tableSorter); 143 final DefaultTableCellRenderer tableCellRenderer = new DefaultTableCellRenderer() { 144 @Override 145 public final Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { 146 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 147 148 switch (column) { 149 case 1: // Path column 150 // Render absolute path 151 super.setText(((File)value).getAbsolutePath()); 152 break; 153 case 4: // Size column 154 // Render size formatted to default locale's number format 155 super.setText(NumberFormat.getInstance().format(value)); 156 break; 157 case 5: // last modified column 158 // Render modify date formatted to default locale's date format 159 super.setText(DateFormat.getDateInstance().format(value)); 160 } 161 162 return this; 163 } 164 }; 165 // TableCellRenderer for path column 166 cacheTable.getColumn(this.columns[1]).setCellRenderer(tableCellRenderer); 167 // TableCellRenderer for size column 168 cacheTable.getColumn(this.columns[4]).setCellRenderer(tableCellRenderer); 169 // TableCellRenderer for last modified column 170 cacheTable.getColumn(this.columns[5]).setCellRenderer(tableCellRenderer); 132 171 133 172 c.weightx = 1; … … 138 177 this.add(topPanel, BorderLayout.CENTER); 139 178 this.add(createButtonPanel(), BorderLayout.SOUTH); 140 141 179 } 142 180 … … 153 191 List<JButton> buttons = new ArrayList<JButton>(); 154 192 155 JButtondeleteButton = new JButton(Translator.R("CVCPButDelete"));193 this.deleteButton = new JButton(Translator.R("CVCPButDelete")); 156 194 deleteButton.addActionListener(new ActionListener() { 157 195 @Override 158 196 public void actionPerformed(ActionEvent e) { 159 FileLock fl = null; 160 File netxRunningFile = new File(config.getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE)); 161 if (!netxRunningFile.exists()) { 197 disableButtons(); 198 // Delete on AWT thread after this action has been performed 199 // in order to allow the cache viewer to update itself 200 invokeLaterDelete(); 201 } 202 }); 203 deleteButton.setEnabled(false); 204 buttons.add(deleteButton); 205 206 this.cleanAll = new JButton(Translator.R("CVCPCleanCache")); 207 cleanAll.addActionListener(new ActionListener() { 208 209 @Override 210 public void actionPerformed(ActionEvent e) { 211 disableButtons(); 212 // Delete on AWT thread after this action has been performed 213 // in order to allow the cache viewer to update itself 214 invokeLaterDeleteAll(); 215 } 216 }); 217 buttons.add(cleanAll); 218 219 this.refreshButton = new JButton(Translator.R("CVCPButRefresh")); 220 refreshButton.addActionListener(new ActionListener() { 221 @Override 222 public void actionPerformed(ActionEvent e) { 223 disableButtons(); 224 // Populate cacheTable on AWT thread after this action event has been performed 225 invokeLaterPopulateTable(); 226 } 227 }); 228 refreshButton.setEnabled(false); 229 buttons.add(refreshButton); 230 231 this.doneButton = new JButton(Translator.R("ButDone")); 232 doneButton.addActionListener(new ActionListener() { 233 @Override 234 public void actionPerformed(ActionEvent e) { 235 Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent( 236 new WindowEvent(parent, WindowEvent.WINDOW_CLOSING)); 237 } 238 }); 239 240 int maxWidth = 0; 241 int maxHeight = 0; 242 for (JButton button : buttons) { 243 maxWidth = Math.max(button.getMinimumSize().width, maxWidth); 244 maxHeight = Math.max(button.getMinimumSize().height, maxHeight); 245 } 246 247 int wantedWidth = maxWidth + 10; 248 int wantedHeight = maxHeight; 249 for (JButton button : buttons) { 250 button.setPreferredSize(new Dimension(wantedWidth, wantedHeight)); 251 leftPanel.add(button); 252 } 253 254 doneButton.setPreferredSize(new Dimension(wantedWidth, wantedHeight)); 255 doneButton.setEnabled(false); 256 rightPanel.add(doneButton); 257 buttonPanel.add(leftPanel); 258 buttonPanel.add(rightPanel); 259 260 return buttonPanel; 261 } 262 263 /** 264 * Posts an event to the event queue to delete the currently selected 265 * resource in {@link CachePane#cacheTable} after the {@code CachePane} and 266 * {@link CacheViewer} have been instantiated and painted. 267 * @see CachePane#cacheTable 268 */ 269 private void invokeLaterDelete() { 270 EventQueue.invokeLater(new Runnable() { 271 @Override 272 public void run() { 273 try { 274 FileLock fl = null; 275 File netxRunningFile = new File(config.getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE)); 276 if (!netxRunningFile.exists()) { 277 try { 278 FileUtils.createParentDir(netxRunningFile); 279 FileUtils.createRestrictedFile(netxRunningFile, true); 280 } catch (IOException e1) { 281 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e1); 282 } 283 } 284 162 285 try { 163 FileUtils.createParentDir(netxRunningFile); 164 FileUtils.createRestrictedFile(netxRunningFile, true); 165 } catch (IOException e1) { 166 e1.printStackTrace(); 167 } 168 } 169 170 try { 171 fl = FileUtils.getFileLock(netxRunningFile.getPath(), false, false); 172 } catch (FileNotFoundException e1) { 173 } 174 175 int row = cacheTable.getSelectedRow(); 176 try { 177 if (fl == null) return; 178 if (row == -1 || row > cacheTable.getRowCount() - 1) 179 return; 180 int modelRow = cacheTable.convertRowIndexToModel(row); 181 DirectoryNode fileNode = ((DirectoryNode) cacheTable.getModel().getValueAt(modelRow, 0)); 182 if (fileNode.getFile().delete()) { 183 updateRecentlyUsed(fileNode.getFile()); 184 fileNode.getParent().removeChild(fileNode); 185 FileUtils.deleteWithErrMesg(fileNode.getInfoFile()); 186 ((DefaultTableModel) cacheTable.getModel()).removeRow(modelRow); 187 cacheTable.getSelectionModel().setSelectionInterval(row, row); 188 CacheDirectory.cleanParent(fileNode); 286 fl = FileUtils.getFileLock(netxRunningFile.getPath(), false, false); 287 } catch (FileNotFoundException e1) { 288 } 289 290 int row = cacheTable.getSelectedRow(); 291 try { 292 if (fl == null) { 293 JOptionPane.showMessageDialog(parent, Translator.R("CCannotClearCache")); 294 return; 295 } 296 int modelRow = cacheTable.convertRowIndexToModel(row); 297 DirectoryNode fileNode = ((DirectoryNode) cacheTable.getModel().getValueAt(modelRow, 0)); 298 if (fileNode.getFile().delete()) { 299 updateRecentlyUsed(fileNode.getFile()); 300 fileNode.getParent().removeChild(fileNode); 301 FileUtils.deleteWithErrMesg(fileNode.getInfoFile()); 302 ((NonEditableTableModel) cacheTable.getModel()).removeRow(modelRow); 303 cacheTable.getSelectionModel().clearSelection(); 304 CacheDirectory.cleanParent(fileNode); 305 } 306 } catch (Exception exception) { 307 // ignore 308 } 309 310 if (fl != null) { 311 try { 312 fl.release(); 313 fl.channel().close(); 314 } catch (IOException e1) { 315 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e1); 316 } 189 317 } 190 318 } catch (Exception exception) { 191 //ignore 192 } 193 194 if (fl != null) { 195 try { 196 fl.release(); 197 fl.channel().close(); 198 } catch (IOException e1) { 199 e1.printStackTrace(); 200 } 319 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, exception); 320 } finally { 321 restoreDisabled(); 201 322 } 202 323 } 203 324 204 325 private void updateRecentlyUsed(File f) { 205 File recentlyUsedFile = new File(location + File.separator + "recently_used");326 File recentlyUsedFile = new File(location + File.separator + CacheLRUWrapper.CACHE_INDEX_FILE_NAME); 206 327 PropertiesFile pf = new PropertiesFile(recentlyUsedFile); 207 328 pf.load(); … … 216 337 } 217 338 }); 218 buttons.add(deleteButton); 219 220 JButton refreshButton = new JButton(Translator.R("CVCPButRefresh")); 221 refreshButton.addActionListener(new ActionListener() { 222 @Override 223 public void actionPerformed(ActionEvent e) { 224 populateTable(); 225 } 226 }); 227 buttons.add(refreshButton); 228 229 JButton doneButton = new JButton(Translator.R("ButDone")); 230 doneButton.addActionListener(new ActionListener() { 231 @Override 232 public void actionPerformed(ActionEvent e) { 233 parent.dispose(); 234 } 235 }); 236 237 int maxWidth = 0; 238 int maxHeight = 0; 239 for (JButton button : buttons) { 240 maxWidth = Math.max(button.getMinimumSize().width, maxWidth); 241 maxHeight = Math.max(button.getMinimumSize().height, maxHeight); 242 } 243 244 int wantedWidth = maxWidth + 10; 245 int wantedHeight = maxHeight; 246 for (JButton button : buttons) { 247 button.setPreferredSize(new Dimension(wantedWidth, wantedHeight)); 248 leftPanel.add(button); 249 } 250 251 doneButton.setPreferredSize(new Dimension(wantedWidth, wantedHeight)); 252 rightPanel.add(doneButton); 253 buttonPanel.add(leftPanel); 254 buttonPanel.add(rightPanel); 255 256 return buttonPanel; 339 } 340 341 private void invokeLaterDeleteAll() { 342 EventQueue.invokeLater(new Runnable() { 343 344 @Override 345 public void run() { 346 try { 347 visualCleanCache(parent); 348 populateTable(); 349 } catch (Exception exception) { 350 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, exception); 351 } finally { 352 restoreDisabled(); 353 } 354 } 355 }); 356 } 357 358 /** 359 * Posts an event to the event queue to populate the 360 * {@link CachePane#cacheTable} after the {@code CachePane} and 361 * {@link CacheViewer} have been instantiated and painted. 362 * @see CachePane#populateTable 363 */ 364 final void invokeLaterPopulateTable() { 365 EventQueue.invokeLater(new Runnable() { 366 @Override 367 public void run() { 368 try { 369 populateTable(); 370 // Disable cacheTable when no data to display, so no events are generated 371 if (cacheTable.getModel().getRowCount() == 0) { 372 cacheTable.setEnabled(false); 373 cacheTable.setBackground(SystemColor.control); 374 // No data in cacheTable, so nothing to delete 375 deleteButton.setEnabled(false); 376 } else { 377 cacheTable.setEnabled(true); 378 cacheTable.setBackground(SystemColor.text); 379 } 380 } catch (Exception exception) { 381 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, exception); 382 } finally { 383 refreshButton.setEnabled(true); 384 doneButton.setEnabled(true); 385 cleanAll.setEnabled(true); 386 } 387 } 388 }); 257 389 } 258 390 … … 262 394 */ 263 395 private void populateTable() { 264 ((DefaultTableModel) cacheTable.getModel()).setRowCount(0); //Clears the table 265 for (Object[] v : generateData(root)) 266 ((DefaultTableModel) cacheTable.getModel()).addRow(v); 396 try { 397 // Populating the cacheTable may take a while, so indicate busy by cursor 398 parent.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 399 400 NonEditableTableModel tableModel; 401 (tableModel = (NonEditableTableModel)cacheTable.getModel()).setRowCount(0); //Clears the table 402 for (Object[] v : generateData(root)) { 403 tableModel.addRow(v); 404 } 405 } catch (Exception exception) { 406 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, exception); 407 } finally { 408 // Reset cursor 409 parent.getContentPane().setCursor(Cursor.getDefaultCursor()); 410 } 267 411 } 268 412 … … 282 426 for (DirectoryNode domain : type.getChildren()) { 283 427 for (DirectoryNode leaf : CacheDirectory.getLeafData(domain)) { 284 Object[] o = { leaf, 285 leaf.getFile().getAbsolutePath(), 286 type, 287 domain, 288 leaf.getFile().length(), 289 new SimpleDateFormat("MM/dd/yyyy").format(leaf.getFile().lastModified()) }; 428 final File f = leaf.getFile(); 429 Object[] o = { 430 leaf, 431 f.getParentFile(), 432 type, 433 domain, 434 f.length(), 435 new Date(f.lastModified()) 436 }; 290 437 data.add(o); 291 438 } … … 305 452 } 306 453 } 454 455 public void disableButtons() { 456 // may take a while, so indicate busy by cursor 457 parent.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 458 // Disable dialog and buttons while operating 459 deleteButton.setEnabled(false); 460 refreshButton.setEnabled(false); 461 doneButton.setEnabled(false); 462 cleanAll.setEnabled(false); 463 } 464 465 public void restoreDisabled() { 466 cleanAll.setEnabled(true); 467 // If nothing selected then keep deleteButton disabled 468 if (!cacheTable.getSelectionModel().isSelectionEmpty()) { 469 deleteButton.setEnabled(true); 470 } 471 // Enable buttons 472 refreshButton.setEnabled(true); 473 doneButton.setEnabled(true); 474 // If cacheTable is empty disable it and set background 475 // color to indicate being disabled 476 if (cacheTable.getModel().getRowCount() == 0) { 477 cacheTable.setEnabled(false); 478 cacheTable.setBackground(SystemColor.control); 479 } 480 // Reset cursor 481 parent.getContentPane().setCursor(Cursor.getDefaultCursor()); 482 } 483 484 public static void visualCleanCache(Component parent) { 485 try { 486 boolean success = CacheUtil.clearCache(); 487 if (!success) { 488 JOptionPane.showMessageDialog(parent, Translator.R("CCannotClearCache")); 489 } 490 } catch (Exception ex) { 491 JOptionPane.showMessageDialog(parent, Translator.R("CCannotClearCache")); 492 } 493 } 307 494 } 495 496 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java
r418 r429 1 1 /* CacheViewer.java -- Display the GUI for viewing and deleting cache files. 2 Copyright (C) 201 0Red Hat2 Copyright (C) 2013 Red Hat 3 3 4 4 This program is free software; you can redistribute it and/or modify … … 23 23 import java.awt.GridBagConstraints; 24 24 import java.awt.GridBagLayout; 25 import java.awt.KeyEventDispatcher; 26 import java.awt.KeyboardFocusManager; 25 27 import java.awt.Toolkit; 28 import java.awt.event.KeyEvent; 26 29 import java.awt.event.WindowAdapter; 27 30 import java.awt.event.WindowEvent; … … 32 35 import net.sourceforge.jnlp.runtime.Translator; 33 36 import net.sourceforge.jnlp.util.ImageResources; 37 import net.sourceforge.jnlp.util.ScreenFinder; 34 38 35 39 /** … … 53 57 public CacheViewer(DeploymentConfiguration config) { 54 58 super((Frame) null, dialogTitle, true); // Don't need a parent. 59 this.config = config; 60 if (config == null) { 61 throw new IllegalArgumentException("config: " + config); 62 } 55 63 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 56 this.config = config;57 64 58 65 /* Prepare for adding components to dialog box */ … … 70 77 71 78 pack(); 79 this.topPanel.invokeLaterPopulateTable(); 72 80 73 81 /* Set focus to default button when first activated */ … … 75 83 private boolean gotFocus = false; 76 84 85 @Override 77 86 public void windowGainedFocus(WindowEvent we) { 78 87 // Once window gets focus, set initial focus … … 84 93 }; 85 94 addWindowFocusListener(adapter); 95 96 // Add a KeyEventDispatcher to dispatch events when this CacheViewer has focus 97 final CacheViewer cacheViewer = this; 98 KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() { 99 /** 100 * Dispatches mainly the {@code KeyEvent.VK_ESCAPE} key event to 101 * close the {@code CacheViewer} dialog. 102 * @return {@code true} after an {@link KeyEvent#VK_ESCAPE 103 * VK_ESCAPE} has been processed, otherwise {@code false} 104 * @see KeyEventDispatcher 105 */ 106 public boolean dispatchKeyEvent(final KeyEvent keyEvent) { 107 // Check if Esc key has been pressed 108 if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE && 109 keyEvent.getID() == KeyEvent.KEY_PRESSED) { 110 // Exclude this key event from further processing 111 keyEvent.consume(); 112 // Remove this low-level KeyEventDispatcher 113 KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this); 114 // Post close event to CacheViewer dialog 115 Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent( 116 new WindowEvent(cacheViewer, WindowEvent.WINDOW_CLOSING)); 117 return true; 118 } 119 return false; 120 } 121 }); 86 122 87 123 initialized = true; … … 114 150 */ 115 151 private void centerDialog() { 116 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 117 Dimension dialogSize = getSize(); 118 119 setLocation((screen.width - dialogSize.width) / 2, (screen.height - dialogSize.height) / 2); 152 ScreenFinder.centerWindowsToCurrentScreen(this); 120 153 } 121 154 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java
r348 r429 32 32 import net.sourceforge.jnlp.config.DeploymentConfiguration; 33 33 import net.sourceforge.jnlp.config.Setting; 34 import net.sourceforge.jnlp.runtime.JNLPRuntime; 35 import net.sourceforge.jnlp.util.logging.OutputController; 34 36 35 37 /** … … 43 45 * that specific command. For example, see {@link #handleListCommand(List)} 44 46 * and {@link #printListHelp()}. 45 * < p>47 * </p> 46 48 * Sample usage: 47 * <pre> 49 * <pre><code> 48 50 * CommandLine cli = new CommandLine(); 49 51 * // the string array represents input using the command line … … 54 56 * // bad! 55 57 * } 56 * </ pre>58 * </code></pre> 57 59 * 58 * @author Omair Majid (omajid@redhat.com)60 * @author <a href="mailto:Omair%20Majid%20<omajid@redhat.com>">Omair Majid</a> 59 61 */ 60 62 public class CommandLine { … … 81 83 config.load(false); 82 84 } catch (ConfigurationException e) { 83 System.out.println(R("RConfigurationFatal")); 85 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("RConfigurationFatal")); 86 OutputController.getLogger().log(e); 84 87 } 85 88 } … … 92 95 */ 93 96 public int handleHelpCommand(List<String> args) { 94 System.out.println(R("Usage"));95 System.out.println(" " + PROGRAM_NAME + " "97 OutputController.getLogger().printOutLn(R("Usage")); 98 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " " 96 99 + allCommands.toString().replace(',', '|').replaceAll(" ", "") + " [help]"); 97 System.out.println(R("CLHelpDescription", PROGRAM_NAME));100 OutputController.getLogger().printOutLn(R("CLHelpDescription", PROGRAM_NAME)); 98 101 return SUCCESS; 99 102 } … … 103 106 */ 104 107 public void printListHelp() { 105 System.out.println(R("Usage"));106 System.out.println(" " + PROGRAM_NAME + " list [--details]");107 System.out.println(R("CLListDescription"));108 OutputController.getLogger().printOutLn(R("Usage")); 109 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " list [--details]"); 110 OutputController.getLogger().printOutLn(R("CLListDescription")); 108 111 } 109 112 … … 135 138 for (String key : all.keySet()) { 136 139 Setting<String> value = all.get(key); 137 System.out.println(key + ": " + value.getValue());140 OutputController.getLogger().printOutLn(key + ": " + value.getValue()); 138 141 if (verbose) { 139 System.out.println("\t" + R("CLDescription", value.getDescription()));142 OutputController.getLogger().printOutLn("\t" + R("CLDescription", value.getDescription())); 140 143 } 141 144 } … … 147 150 */ 148 151 public void printGetHelp() { 149 System.out.println(R("Usage"));150 System.out.println(" " + PROGRAM_NAME + " get property-name");151 System.out.println(R("CLGetDescription"));152 OutputController.getLogger().printOutLn(R("Usage")); 153 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " get property-name"); 154 OutputController.getLogger().printOutLn(R("CLGetDescription")); 152 155 } 153 156 … … 176 179 if (all.containsKey(key)) { 177 180 value = all.get(key).getValue(); 178 System.out.println(value);179 return SUCCESS; 180 } else { 181 System.out.println(R("CLUnknownProperty", key));181 OutputController.getLogger().printOutLn(value); 182 return SUCCESS; 183 } else { 184 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLUnknownProperty", key)); 182 185 return ERROR; 183 186 } … … 188 191 */ 189 192 public void printSetHelp() { 190 System.out.println(R("Usage"));191 System.out.println(" " + PROGRAM_NAME + " set property-name value");192 System.out.println(R("CLSetDescription"));193 OutputController.getLogger().printOutLn(R("Usage")); 194 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " set property-name value"); 195 OutputController.getLogger().printOutLn(R("CLSetDescription")); 193 196 } 194 197 … … 220 223 old.getValidator().validate(value); 221 224 } catch (IllegalArgumentException e) { 222 System.out.println(R("CLIncorrectValue", old.getName(), value, old.getValidator().getPossibleValues())); 225 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, R("CLIncorrectValue", old.getName(), value, old.getValidator().getPossibleValues())); 226 OutputController.getLogger().log(e); 223 227 return ERROR; 224 228 } … … 226 230 config.setProperty(key, value); 227 231 } else { 228 System.out.println(R("CLWarningUnknownProperty", key));232 OutputController.getLogger().printOutLn(R("CLWarningUnknownProperty", key)); 229 233 config.setProperty(key, value); 230 234 } … … 233 237 config.save(); 234 238 } catch (IOException e) { 235 e.printStackTrace();239 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 236 240 return ERROR; 237 241 } … … 244 248 */ 245 249 public void printResetHelp() { 246 System.out.println(R("Usage"));247 System.out.println(" " + PROGRAM_NAME + " reset [all|property-name]");248 System.out.println(R("CLResetDescription"));250 OutputController.getLogger().printOutLn(R("Usage")); 251 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " reset [all|property-name]"); 252 OutputController.getLogger().printOutLn(R("CLResetDescription")); 249 253 } 250 254 … … 276 280 Map<String, Setting<String>> all = config.getRaw(); 277 281 if (!resetAll && !all.containsKey(key)) { 278 System.out.println(R("CLUnknownProperty", key));282 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLUnknownProperty", key)); 279 283 return ERROR; 280 284 } … … 293 297 config.save(); 294 298 } catch (IOException e) { 295 e.printStackTrace();299 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 296 300 return ERROR; 297 301 } … … 304 308 */ 305 309 public void printInfoHelp() { 306 System.out.println(R("Usage"));307 System.out.println(" " + PROGRAM_NAME + " info property-name");308 System.out.println(R("CLInfoDescription"));310 OutputController.getLogger().printOutLn(R("Usage")); 311 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " info property-name"); 312 OutputController.getLogger().printOutLn(R("CLInfoDescription")); 309 313 } 310 314 … … 332 336 Setting<String> value = all.get(key); 333 337 if (value == null) { 334 System.out.println(R("CLNoInfo"));335 return ERROR; 336 } else { 337 System.out.println(R("CLDescription", value.getDescription()));338 System.out.println(R("CLValue", value.getValue()));338 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLNoInfo")); 339 return ERROR; 340 } else { 341 OutputController.getLogger().printOutLn(R("CLDescription", value.getDescription())); 342 OutputController.getLogger().printOutLn(R("CLValue", value.getValue())); 339 343 if (value.getValidator() != null) { 340 System.out.println("\t" + R("VVPossibleValues", value.getValidator().getPossibleValues()));344 OutputController.getLogger().printOutLn("\t" + R("VVPossibleValues", value.getValidator().getPossibleValues())); 341 345 } 342 System.out.println(R("CLValueSource", value.getSource()));346 OutputController.getLogger().printOutLn(R("CLValueSource", value.getSource())); 343 347 return SUCCESS; 344 348 } … … 349 353 */ 350 354 public void printCheckHelp() { 351 System.out.println(R("Usage"));352 System.out.println(" " + PROGRAM_NAME + " check");353 System.out.println(R("CLCheckDescription"));355 OutputController.getLogger().printOutLn(R("Usage")); 356 OutputController.getLogger().printOutLn(" " + PROGRAM_NAME + " check"); 357 OutputController.getLogger().printOutLn(R("CLCheckDescription")); 354 358 } 355 359 … … 379 383 boolean allValid = true; 380 384 for (Setting<String> setting : validator.getIncorrectSetting()) { 381 System.out.println(R("CLIncorrectValue", setting.getName(), setting.getValue(), setting.getValidator().getPossibleValues()));385 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLIncorrectValue", setting.getName(), setting.getValue(), setting.getValidator().getPossibleValues())); 382 386 allValid = false; 383 387 } 384 388 385 389 for (Setting<String> setting : validator.getUnrecognizedSetting()) { 386 System.out.println(R("CLUnknownProperty", setting.getName()));390 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLUnknownProperty", setting.getName())); 387 391 allValid = false; 388 392 } 389 393 390 394 if (allValid) { 391 System.out.println(R("CLNoIssuesFound"));395 OutputController.getLogger().printOutLn(R("CLNoIssuesFound")); 392 396 return SUCCESS; 393 397 } else { … … 438 442 val = handleCheckCommand(arguments); 439 443 } else if (allCommands.contains(command)) { 440 System.out.println("INTERNAL ERROR: " + command + " should have been implemented");444 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "INTERNAL ERROR: " + command + " should have been implemented"); 441 445 val = ERROR; 442 446 } else { 443 System.out.println(R("CLUnknownCommand", command));447 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("CLUnknownCommand", command)); 444 448 handleHelpCommand(new ArrayList<String>()); 445 449 val = ERROR; … … 454 458 */ 455 459 public static void main(String[] args) throws Exception { 460 DeploymentConfiguration.move14AndOlderFilesTo15StructureCatched(); 456 461 if (args.length == 0) { 457 462 ControlPanel.main(new String[] {}); … … 460 465 int result = cli.handle(args); 461 466 462 // instead of returning, use System.exit() so we can pass back467 // instead of returning, use JNLPRuntime.exit() so we can pass back 463 468 // error codes indicating success or failure. Otherwise using 464 469 // this program for scripting will become much more challenging 465 System.exit(result);470 JNLPRuntime.exit(result); 466 471 } 467 472 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
r418 r429 42 42 import javax.swing.JLabel; 43 43 import javax.swing.JList; 44 import javax.swing.JOptionPane; 44 45 import javax.swing.JPanel; 45 46 import javax.swing.JScrollPane; … … 53 54 54 55 import net.sourceforge.jnlp.config.DeploymentConfiguration; 56 import net.sourceforge.jnlp.controlpanel.JVMPanel.JvmValidationResult; 55 57 import net.sourceforge.jnlp.runtime.Translator; 56 58 import net.sourceforge.jnlp.security.KeyStores; 57 59 import net.sourceforge.jnlp.security.viewer.CertificatePane; 58 60 import net.sourceforge.jnlp.util.ImageResources; 61 import net.sourceforge.jnlp.util.logging.OutputController; 59 62 60 63 /** … … 66 69 */ 67 70 public class ControlPanel extends JFrame { 71 private JVMPanel jvmPanel; 68 72 69 73 /** … … 117 121 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 118 122 pack(); 119 setMinimumSize(getPreferredSize());120 123 } 121 124 122 125 private JPanel createTopPanel() { 123 Font currentFont = null;126 Font currentFont; 124 127 JLabel about = new JLabel(R("CPMainDescriptionShort")); 125 128 currentFont = about.getFont(); … … 147 150 image.setIcon(new ImageIcon(ImageIO.read(imgUrl))); 148 151 } catch (IOException e) { 149 e.printStackTrace();152 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 150 153 } 151 154 … … 157 160 return topPanel; 158 161 } 162 163 private int validateJdk() { 164 String s = ControlPanel.this.config.getProperty(DeploymentConfiguration.KEY_JRE_DIR); 165 JvmValidationResult validationResult = JVMPanel.validateJvm(s); 166 if (validationResult.id == JvmValidationResult.STATE.NOT_DIR 167 || validationResult.id == JvmValidationResult.STATE.NOT_VALID_DIR 168 || validationResult.id == JvmValidationResult.STATE.NOT_VALID_JDK) { 169 return JOptionPane.showConfirmDialog(ControlPanel.this, 170 "<html>"+Translator.R("CPJVMNotokMessage1", s)+"<br/>" 171 + validationResult.formattedText+"<br/>" 172 + Translator.R("CPJVMNotokMessage2", DeploymentConfiguration.KEY_JRE_DIR, DeploymentConfiguration.USER_DEPLOYMENT_PROPERTIES_FILE)+"</html>", 173 Translator.R("CPJVMconfirmInvalidJdkTitle"),JOptionPane.OK_CANCEL_OPTION); 174 } 175 return JOptionPane.OK_OPTION; 176 } 159 177 160 178 /** … … 173 191 public void actionPerformed(ActionEvent e) { 174 192 ControlPanel.this.saveConfiguration(); 193 int validationResult = validateJdk(); 194 if (validationResult!= JOptionPane.OK_OPTION){ 195 return; 196 } 175 197 ControlPanel.this.dispose(); 176 198 } … … 183 205 public void actionPerformed(ActionEvent e) { 184 206 ControlPanel.this.saveConfiguration(); 207 int validationResult = validateJdk(); 208 if (validationResult != JOptionPane.OK_OPTION) { 209 int i = JOptionPane.showConfirmDialog(ControlPanel.this, 210 Translator.R("CPJVMconfirmReset"), 211 Translator.R("CPJVMconfirmReset"), JOptionPane.OK_CANCEL_OPTION); 212 if (i == JOptionPane.OK_OPTION) { 213 jvmPanel.resetTestFieldArgumentsExec(); 214 } 215 } 185 216 } 186 217 }); … … 219 250 */ 220 251 private JPanel createMainSettingsPanel() { 221 252 jvmPanel = (JVMPanel) createJVMSettingsPanel(); 222 253 SettingsPanel[] panels = new SettingsPanel[] { new SettingsPanel(Translator.R("CPTabAbout"), createAboutPanel()), 223 254 new SettingsPanel(Translator.R("CPTabCache"), createCacheSettingsPanel()), … … 227 258 new SettingsPanel(Translator.R("CPTabDebugging"), createDebugSettingsPanel()), 228 259 new SettingsPanel(Translator.R("CPTabDesktopIntegration"), createDesktopSettingsPanel()), 260 new SettingsPanel(Translator.R("CPTabJVMSettings"),jvmPanel), 229 261 new SettingsPanel(Translator.R("CPTabNetwork"), createNetworkSettingsPanel()), 230 262 // TODO: This is commented out since this is not implemented yet 231 263 // new SettingsPanel(Translator.R("CPTabRuntimes"), createRuntimesSettingsPanel()), 232 new SettingsPanel(Translator.R("CPTabSecurity"), createSecuritySettingsPanel()), }; 264 new SettingsPanel(Translator.R("CPTabSecurity"), createSecuritySettingsPanel()), 265 //todo refactor to work with tmp file and apply as asu designed it 266 new SettingsPanel(Translator.R("CPTabPolicy"), createPolicySettingsPanel()), 267 new SettingsPanel(Translator.R("APPEXTSECControlPanelExtendedAppletSecurityTitle"), new UnsignedAppletsTrustingListPanel(DeploymentConfiguration.getAppletTrustGlobalSettingsPath(), DeploymentConfiguration.getAppletTrustUserSettingsPath(), this.config)) 268 }; 233 269 234 270 // Add panels. … … 241 277 JPanel p = panel.getPanel(); 242 278 Dimension d = p.getMinimumSize(); 243 if (d.height > height) 279 if (d.height > height) { 244 280 height = d.height; 245 if (d.width > width) 281 } 282 if (d.width > width) { 246 283 width = d.width; 284 } 247 285 } 248 286 Dimension dim = new Dimension(width, height); … … 265 303 }); 266 304 JScrollPane settingsListScrollPane = new JScrollPane(settingsList); 267 settingsListScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ NEVER);305 settingsListScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 268 306 269 307 final JPanel settingsDetailPanel = new JPanel(); … … 320 358 } 321 359 360 private JPanel createPolicySettingsPanel() { 361 return new PolicyPanel(this, this.config); 362 } 363 364 private JPanel createJVMSettingsPanel() { 365 return new JVMPanel(this.config); 366 } 367 322 368 /** 323 369 * This is a placeholder panel. 324 370 * 325 * @return 371 * @return a placeholder panel 372 * @see JPanel 326 373 */ 327 374 private JPanel createNotImplementedPanel() { … … 343 390 notImplementedPanel.add(label); 344 391 } catch (IOException e) { 345 e.printStackTrace();392 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 346 393 } 347 394 return notImplementedPanel; … … 355 402 config.save(); 356 403 } catch (IOException e) { 357 e.printStackTrace(); 404 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 405 JOptionPane.showMessageDialog(this, e); 358 406 } 359 407 } 360 408 361 409 public static void main(String[] args) throws Exception { 410 DeploymentConfiguration.move14AndOlderFilesTo15StructureCatched(); 362 411 final DeploymentConfiguration config = new DeploymentConfiguration(); 363 412 try { … … 370 419 // if configuration is not loaded, we will get NullPointerExceptions 371 420 // everywhere 372 e.printStackTrace();421 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 373 422 } 374 423 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java
r348 r429 24 24 import java.awt.GridBagConstraints; 25 25 import java.awt.GridBagLayout; 26 import java.awt.event.ActionEvent; 27 import java.awt.event.ActionListener; 26 28 import java.awt.event.ItemEvent; 27 29 import java.awt.event.ItemListener; 28 29 30 import javax.swing.Box; 31 import javax.swing.JButton; 30 32 import javax.swing.JCheckBox; 31 33 import javax.swing.JComboBox; 32 34 import javax.swing.JLabel; 33 35 import javax.swing.JPanel; 34 36 import javax.swing.JTextField; 37 import javax.swing.event.DocumentEvent; 38 import javax.swing.event.DocumentListener; 39 import net.sourceforge.jnlp.config.Defaults; 35 40 import net.sourceforge.jnlp.config.DeploymentConfiguration; 36 41 import net.sourceforge.jnlp.runtime.Translator; 42 import net.sourceforge.jnlp.util.logging.LogConfig; 37 43 38 44 /** … … 44 50 public class DebuggingPanel extends NamedBorderPanel implements ItemListener { 45 51 46 /** List of properties used by this panel */ 47 public static String[] properties = { "deployment.trace", // Debugging 48 "deployment.log", // Debugging 49 "deployment.console.startup.mode", // Java Console 52 /** List of properties used by checkboxes in this panel */ 53 public static String[] properties = { 54 DeploymentConfiguration.KEY_ENABLE_LOGGING, 55 DeploymentConfiguration.KEY_ENABLE_LOGGING_HEADERS, 56 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOFILE, 57 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSTREAMS, 58 DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSYSTEMLOG 59 50 60 }; 51 private DeploymentConfiguration config; 61 62 private DeploymentConfiguration config; 52 63 53 64 /** … … 71 82 GridBagConstraints c = new GridBagConstraints(); 72 83 73 JLabel debuggingDescription = new JLabel("<html>" + Translator.R("CPDebuggingDescription") + "<hr /><br /></html>"); 74 75 JCheckBox[] debuggingOptions = { new JCheckBox(Translator.R("DPEnableTracing")), 76 new JCheckBox(Translator.R("DPEnableLogging")), }; 77 78 ComboItem[] javaConsoleItems = { new ComboItem(Translator.R("DPDisable"), "DISABLE"), 79 new ComboItem(Translator.R("DPHide"), "HIDE"), 80 new ComboItem(Translator.R("DPShow"), "SHOW"), }; 84 85 final JLabel debuggingDescription = new JLabel("<html>" + Translator.R("CPDebuggingDescription") + "<hr /><br /></html>"); 86 final JLabel logsDestinationTitle = new JLabel(Translator.R("CPFilesLogsDestDir")+": "); 87 final JTextField logsDestination = new JTextField(config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR)); 88 logsDestination.getDocument().addDocumentListener(new DocumentListener() { 89 90 91 @Override 92 public void insertUpdate(DocumentEvent e) { 93 save(); 94 } 95 96 @Override 97 public void removeUpdate(DocumentEvent e) { 98 save(); 99 } 100 101 @Override 102 public void changedUpdate(DocumentEvent e) { 103 save(); 104 105 } 106 107 private void save() { 108 config.setProperty(DeploymentConfiguration.KEY_USER_LOG_DIR, logsDestination.getText()); 109 } 110 }); 111 final JButton logsDestinationReset = new JButton(Translator.R("CPFilesLogsDestDirResert")); 112 logsDestinationReset.addActionListener(new ActionListener() { 113 114 @Override 115 public void actionPerformed(ActionEvent e) { 116 logsDestination.setText(Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_LOG_DIR).getDefaultValue()); 117 } 118 }); 119 120 JCheckBox[] debuggingOptions = { 121 new JCheckBox(Translator.R("DPEnableLogging")), 122 new JCheckBox(Translator.R("DPEnableHeaders")), 123 new JCheckBox(Translator.R("DPEnableFile")), 124 new JCheckBox(Translator.R("DPEnableStds")), 125 new JCheckBox(Translator.R("DPEnableSyslog")) 126 }; 127 String[] hints = { 128 (Translator.R("DPEnableLoggingHint")), 129 (Translator.R("DPEnableHeadersHint")), 130 (Translator.R("DPEnableFileHint", LogConfig.getLogConfig().getIcedteaLogDir())), 131 (Translator.R("DPEnableStdsHint")), 132 (Translator.R("DPEnableSyslogHint")) 133 }; 134 135 ComboItem[] javaConsoleItems = { new ComboItem(Translator.R("DPDisable"), DeploymentConfiguration.CONSOLE_DISABLE), 136 new ComboItem(Translator.R("DPHide"), DeploymentConfiguration.CONSOLE_HIDE), 137 new ComboItem(Translator.R("DPShow"), DeploymentConfiguration.CONSOLE_SHOW), 138 new ComboItem(Translator.R("DPShowPluginOnly"), DeploymentConfiguration.CONSOLE_SHOW_PLUGIN), 139 new ComboItem(Translator.R("DPShowJavawsOnly"), DeploymentConfiguration.CONSOLE_SHOW_JAVAWS) }; 81 140 82 141 JLabel consoleLabel = new JLabel(Translator.R("DPJavaConsole")); 83 142 JComboBox consoleComboBox = new JComboBox(); 84 consoleComboBox.setActionCommand( "deployment.console.startup.mode"); // The property this comboBox affects.143 consoleComboBox.setActionCommand(DeploymentConfiguration.KEY_CONSOLE_STARTUP_MODE); // The property this comboBox affects. 85 144 86 145 JPanel consolePanel = new JPanel(); … … 99 158 */ 100 159 for (int i = 0; i < properties.length; i++) { 101 try { 102 String s = config.getProperty(properties[i]); 103 c.gridy = i + 1; 104 105 switch (i) { 106 case 0: 107 case 1: 108 debuggingOptions[i].setSelected(Boolean.parseBoolean(s)); 109 debuggingOptions[i].setActionCommand(properties[i]); 110 debuggingOptions[i].addItemListener(this); 111 add(debuggingOptions[i], c); 112 break; 113 case 2: 114 for (int j = 0; j < javaConsoleItems.length; j++) { 115 consoleComboBox.addItem(javaConsoleItems[j]); 116 if (config.getProperty("deployment.console.startup.mode").equals(javaConsoleItems[j].getValue())) 117 consoleComboBox.setSelectedIndex(j); 118 } 119 consoleComboBox.addItemListener(this); 120 add(consolePanel, c); 121 } 122 123 } catch (Exception e) { 124 debuggingOptions[i] = null; 160 String s = config.getProperty(properties[i]); 161 c.gridy++; 162 if (i == 2) { 163 JLabel space = new JLabel("<html>" + Translator.R("CPDebuggingPossibilites") + ":</html>"); 164 add(space, c); 165 c.gridy++; 166 } 167 168 debuggingOptions[i].setSelected(Boolean.parseBoolean(s)); 169 debuggingOptions[i].setActionCommand(properties[i]); 170 debuggingOptions[i].setToolTipText(hints[i]); 171 debuggingOptions[i].addItemListener(this); 172 add(debuggingOptions[i], c); 173 174 if (i == 2) { 175 c.gridx++; 176 add(logsDestinationTitle, c); 177 c.gridx++; 178 add(logsDestination, c); 179 c.gridx++; 180 add(logsDestinationReset, c); 181 c.gridx-=3; 125 182 } 126 183 } 127 184 185 186 for (int j = 0; j < javaConsoleItems.length; j++) { 187 consoleComboBox.addItem(javaConsoleItems[j]); 188 if (config.getProperty(DeploymentConfiguration.KEY_CONSOLE_STARTUP_MODE).equals(javaConsoleItems[j].getValue())) { 189 consoleComboBox.setSelectedIndex(j); 190 } 191 } 192 c.gridy++; 193 consoleComboBox.addItemListener(this); 194 add(consolePanel, c); 195 128 196 // pack the bottom so that it doesn't change size if resized. 129 197 Component filler = Box.createRigidArea(new Dimension(1, 1)); … … 134 202 135 203 @Override 204 @SuppressWarnings("unchecked") 136 205 public void itemStateChanged(ItemEvent e) { 137 206 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java
r348 r429 73 73 for (int j = 0; j < items.length; j++) { 74 74 shortcutComboOptions.addItem(items[j]); 75 if (config.getProperty("deployment.javaws.shortcut").equals(items[j].getValue())) 75 if (config.getProperty("deployment.javaws.shortcut").equals(items[j].getValue())) { 76 76 shortcutComboOptions.setSelectedIndex(j); 77 } 77 78 } 78 79 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/DocumentAdapter.java
r348 r429 24 24 25 25 import net.sourceforge.jnlp.config.DeploymentConfiguration; 26 import net.sourceforge.jnlp.util.logging.OutputController; 26 27 27 28 /** … … 95 96 } 96 97 } catch (BadLocationException e1) { 97 // TODO Auto-generated catch block 98 e1.printStackTrace(); 98 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e1); 99 99 } 100 100 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java
r418 r429 110 110 @Override 111 111 public void actionPerformed(ActionEvent e) { 112 JFileChooser fileChooser = new JFileChooser( );112 JFileChooser fileChooser = new JFileChooser(location.getText()); 113 113 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 114 114 fileChooser.setFileHidingEnabled(false); 115 if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { 115 fileChooser.setAcceptAllFileFilterUsed(false); 116 fileChooser.setDialogTitle(Translator.R("TIFPLocationLabel")); 117 if (fileChooser.showDialog(null, Translator.R("TIFPFileChooserChooseButton")) == JFileChooser.APPROVE_OPTION) { 116 118 // Check if we have permission to write to that location. 117 119 String result = fileChooser.getSelectedFile().getAbsolutePath(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/resources/Messages.properties
r418 r429 13 13 ButProceed=Proceed 14 14 ButRun=Run 15 ButSandbox=Sandbox 15 16 ButApply=Apply 16 17 ButDone=Done 17 18 ButShowDetails=Show Details 18 19 ButHideDetails=Hide Details 20 ButYes=Yes 21 ButNo=No 22 23 CertWarnRunTip=Trust this applet and run with full permissions 24 CertWarnSandboxTip=Do not trust this applet and run with restricted permissions 25 CertWarnCancelTip=Do not run this applet 26 CertWarnPolicyTip=Advanced sandbox settings 27 CertWarnPolicyEditorItem=Launch PolicyEditor 19 28 20 29 AFileOnTheMachine=a file on the machine … … 22 31 Usage=Usage: 23 32 Error=Error 33 Warning=Warning 24 34 25 35 Continue=Do you want to continue? … … 33 43 Value=Value 34 44 Version=Version 45 46 # about dialogue 47 AboutDialogueTabAbout=About 48 AboutDialogueTabAuthors=Authors 49 AboutDialogueTabChangelog=Changelog 50 AboutDialogueTabNews=News 51 AboutDialogueTabGPLv2=GPLv2 52 53 # missing permissions dialogue 54 MissingPermissionsMainTitle=Application <span color='red'> {0} </span> \ 55 from <span color='red'> {1} </span> is missing the permissions attribute. \ 56 Applications without this attribute should not be trusted. Do you wish to allow this application to run? 57 MissingPermissionsInfo=For more information you can visit:<br/>\ 58 <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/manifest.html#permissions"> \ 59 JAR File Manifest Attributes</a> <br/> \ 60 and<br/> <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html"> \ 61 Preventing the repurposing of Applications</a> 62 63 # missing Application-Library-Allowable-Codebase dialogue 64 ALACAMissingMainTitle=The application <span color='red'> {0} </span> \ 65 from <span color='red'> {1} </span> uses resources from the following remote locations: \ 66 {2} \ 67 Are you sure you want to run this application? 68 ALACAMissingInfo=For more information see:<br/>\ 69 <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/manifest.html#app_library"> \ 70 JAR File Manifest Attributes</a> <br/> \ 71 and<br/> <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html"> \ 72 Preventing the Repurposing of an Application</a> 73 74 # matching Application-Library-Allowable-Codebase dialogue 75 ALACAMatchingMainTitle=The application <span color='red'> {0} </span> \ 76 from <span color='red'> {1} </span> uses resources from the following remote locations:<br/>{2} <br/> \ 77 Are you sure you want to run this application? 78 ALACAMatchingInfo=For more information you can visit:<br/>\ 79 <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/manifest.html#app_library"> \ 80 JAR File Manifest Attributes</a> <br/> \ 81 and<br/> <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html"> \ 82 Preventing the Repurposing of an Application</a> 35 83 36 84 # LS - Severity … … 52 100 53 101 LThreadInterrupted=Thread interrupted while waiting for file to launch. 54 LThreadInterruptedInfo= 102 LThreadInterruptedInfo=This can lead to deadlock or yield other damage during execution. Please restart your application/browser. 55 103 LCouldNotLaunch=Could not launch JNLP file. 56 LCouldNotLaunchInfo= 104 LCouldNotLaunchInfo=The application has not been initialized, for more information execute javaws/browser from the command line and send a bug report. 57 105 LCantRead=Could not read or parse the JNLP file. 58 LCantReadInfo= 106 LCantReadInfo=You can try to download this file manually and send it as bug report to IcedTea-Web team. 59 107 LNullLocation=Could not determine .jnlp file location. 60 108 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. … … 70 118 LNoInstallersInfo=JNLP installer files are not yet supported. 71 119 LInitApplet=Could not initialize applet. 72 LInitAppletInfo= 120 LInitAppletInfo=For more information click "more information button". 73 121 LInitApplication=Could not initialize application. 74 LInitApplicationInfo= 122 LInitApplicationInfo=The application has not been initialized, for more information execute javaws from the command line. 75 123 LNotLaunchable=Not a launchable JNLP file. 76 124 LNotLaunchableInfo=File must be a JNLP application, applet, or installer type. … … 79 127 LUnsignedJarWithSecurity=Cannot grant permissions to unsigned jars. 80 128 LUnsignedJarWithSecurityInfo=Application requested security permissions, but jars are not signed. 129 LSignedJNLPAppDifferentCerts=The JNLP application is not fully signed by a single cert. 130 LSignedJNLPAppDifferentCertsInfo=The JNLP application has its components individually signed, however there must be a common signer to all entries. 131 LUnsignedApplet=The applet was unsigned. 132 LUnsignedAppletPolicyDenied=The applet was unsigned, and the security policy prevented it from running. 133 LUnsignedAppletUserDenied=The applet was unsigned, and was not trusted. 134 LPartiallySignedApplet=The applet was partially signed. 135 LPartiallySignedAppletUserDenied=The applet was partially signed, and the user did not trust it. 81 136 LSignedAppJarUsingUnsignedJar=Signed application using unsigned jars. 82 137 LSignedAppJarUsingUnsignedJarInfo=The main application jar is signed, but some of the jars it is using aren't. 138 LRunInSandboxError=Run in Sandbox call performed too late. 139 LRunInSandboxErrorInfo=The classloader was notified to run the applet sandboxed, but security settings were already initialized. 83 140 LSignedJNLPFileDidNotMatch=The signed JNLP file did not match the launching JNLP file. 84 141 LNoSecInstance=Error: No security instance for {0}. The application may have trouble continuing 85 142 LCertFoundIn={0} found in cacerts ({1}) 143 LSingleInstanceExists=Another instance of this applet already exists and only one may be run at the same time. 86 144 87 145 JNotApplet=File is not an applet. … … 94 152 LCancelOnUserRequest=Canceled on user request. 95 153 LFatalVerification=A fatal error occurred while trying to verify jars. 96 LFatalVerificationInfo= 154 LFatalVerificationInfo=An exception has been thrown in class JarCertVerifier. Being unable to read the cacerts or trusted.certs files could be a possible cause for this exception. 97 155 98 156 LNotVerifiedDialog=Not all jars could be verified. … … 100 158 101 159 # Parser 102 PInvalidRoot=Root node is not a jnlp node103 PNoResources=No resources section defined160 PInvalidRoot=Root element is not a jnlp element. 161 PNoResources=No resources element specified. 104 162 PUntrustedNative=nativelib element cannot be specified unless a trusted environment is requested. 105 163 PExtensionHasJ2SE=j2se element cannot be specified in a component extension file. 106 164 PInnerJ2SE=j2se element cannot be specified within a j2se element. 107 PTwoMains=Duplicate main JAR defined in a resources element (there can be only one)108 PNativeHasMain= Cannot specify main attribute on native JARs.109 PNoInfoElement=No information section defined.165 PTwoMains=Duplicate main attribute specified on a resources element (there can be only one) 166 PNativeHasMain=main attribute cannot be specified on a nativelib element. 167 PNoInfoElement=No information element specified. 110 168 PMissingTitle=title 111 169 PMissingVendor=vendor 112 PMissingElement=The {0} section has not been defined for your locale nor does a default value exist in the JNLP file.113 PTwoDescriptions=Duplicate description of kind {0}114 PSharing= Element "sharing-allowed"is illegal in a standard JNLP file115 PTwoSecurity=Only one security element allowed per JNLP File.116 PEmptySecurity= Security element specified but does not contain a permissions element.117 PTwoDescriptors=Only one application descriptor element allowed per JNLPFile.170 PMissingElement=The {0} section has not been specified for your locale nor does a default value exist in the JNLP file. 171 PTwoDescriptions=Duplicate description elements of kind {0} are illegal. 172 PSharing=sharing-allowed element is illegal in a standard JNLP file 173 PTwoSecurity=Only one security element allowed per JNLP file. 174 PEmptySecurity=security element specified but does not contain a permissions element. 175 PTwoDescriptors=Only one application-desc element allowed per JNLP file. 118 176 PTwoDesktops=Only one desktop element allowed 119 177 PTwoMenus=Only one menu element allowed … … 133 191 # Runtime 134 192 BLaunchAbout=Launching about window... 193 BLaunchAboutFailure=Was not able to launch About window 135 194 BNeedsFile=Must specify a .jnlp file 136 195 RNoAboutJnlp=Unable to find about.jnlp … … 139 198 BBadParam=Incorrect parameter format {0} (should be name=value) 140 199 BNoDir=Directory {0} does not exist. 200 BNoCodeOrObjectApplet=Applet tag must specify a 'code' or 'object' attribute. 141 201 RNoResource=Missing Resource: {0} 142 202 RShutdown=This exception to prevent shutdown of JVM, but the process has been terminated. … … 145 205 RCantCreateFile=Cant create file {0} 146 206 RCantDeleteFile=Cant delete file {0} 207 RCantOpenFile=Could not open file {0} 208 RCantWriteFile=Could not write to file {0} 209 RFileReadOnly=Opening file in read-only mode 210 RExpectedFile=Expected {0} to be a file but it was not 147 211 RRemoveRPermFailed=Removing read permission on file {0} failed 148 212 RRemoveWPermFailed=Removing write permissions on file {0} failed … … 158 222 RNestedJarExtration=Unable to extract nested jar. 159 223 RUnexpected=Unexpected {0} at {1} 160 RConfigurationError=Fatal error while reading the configuration 224 RConfigurationError=Fatal error while reading the configuration, continuing with empty. Please fix 161 225 RConfigurationFatal=ERROR: a fatal error has occurred while loading configuration. Perhaps a global configuration was required but could not be found 226 RFailingToDefault=Failing to default configuration 162 227 RPRoxyPacNotSupported=Using Proxy Auto Config (PAC) files is not supported. 163 228 RProxyFirefoxNotFound=Unable to use Firefox's proxy settings. Using "DIRECT" as proxy type. … … 166 231 RBrowserLocationPromptMessage=Specify Browser Location 167 232 RBrowserLocationPromptMessageWithReason=Specify Browser Location (the browser command "{0}" is invalid). 233 BAboutITW=The IcedTea-Web project provides a Free Software web browser plugin running applets written in the Java programming language and an implementation of Java Web Start, originally based on the NetX project. Visit the IcedTea-Web homepage: http://icedtea.classpath.org/wiki/IcedTea-Web . Use "man javaws" or "javaws -help" for more information. 234 BFileInfoAuthors=Names and email addresses of contributors to this project can be found in the file AUTHORS in the IcedTea-Web root directory. 235 BFileInfoCopying=The full GPLv2 license of this project can be found in the file COPYING in the IcedTea-Web root directory. 236 BFileInfoNews=News about releases of this project can be found in the file NEWS in the IcedTea-Web root directory. 168 237 169 238 # Boot options, message should be shorter than this ----------------> … … 174 243 BOParam = Adds an applet parameter before launching. 175 244 BOProperty = Sets a system property before launching. 176 BOUpdate = Update check if seconds since last checked.245 BOUpdate = Check for updates. 177 246 BOLicense = Display the GPL license and exit. 178 247 BOVerbose = Enable verbose output. 179 248 BOAbout = Shows a sample application. 249 BOVersion = Print the IcedTea-Web version and exit. 180 250 BONosecurity= Disables the secure runtime environment. 181 251 BONoupdate = Disables checking for updates. … … 183 253 BOStrict = Enables strict checking of JNLP file format. 184 254 BOViewer = Shows the trusted certificate viewer. 255 BOXml = Uses a strict XML parser to parse the JNLP file. 256 BOredirect = Follows HTTP redirects. 185 257 BXnofork = Do not create another JVM. 186 258 BXclearcache= Clean the JNLP application cache. 259 BXignoreheaders= Skip jar header verification. 187 260 BOHelp = Print this message and exit. 188 261 … … 193 266 CComplete=Complete 194 267 CChooseCache=Choose a cache directory... 195 CChooseCacheInfo=Net xneeds a location for storing cache files.268 CChooseCacheInfo=NetX needs a location for storing cache files. 196 269 CChooseCacheDir=Cache directory 197 CCannotClearCache=Can not clear cache at this time270 CCannotClearCache=Can not clear the cache at this time. Try later. If the problem persists, try closing your browser(s) & JNLP applications. At the end you can try to kill all java applications. \\\n You can clear cache by javaws -Xclearcache or via itw-settings Cache -> View files -> Purge 198 271 CFakeCache=Cache is corrupt. Fixing. 199 CFakedCache=Cache is corrupt and has been fixed. It is strongly recommended that you run 'javaws -Xclearcache' and rerun your application as soon as possible.272 CFakedCache=Cache was corrupt and has been fixed. It is strongly recommended that you run 'javaws -Xclearcache' and rerun your application as soon as possible. You can also use via itw-settings Cache -> View files -> Purge 200 273 201 274 # Security … … 203 276 SFileWriteAccess=The application has requested write access to {0}. Do you want to allow this action? 204 277 SDesktopShortcut=The application has requested permission to create a desktop launcher. Do you want to allow this action? 205 SSigUnverified=The application's digital signature cannot be verified. Do you want to run the application? 206 SSigVerified=The application's digital signature has been verified. Do you want to run the application? 207 SSignatureError=The application's digital signature has an error. Do you want to run the application? 278 SSigUnverified=The application's digital signature cannot be verified. Do you want to run the application? It will be granted unrestricted access to your computer. 279 SSigVerified=The application's digital signature has been verified. Do you want to run the application? It will be granted unrestricted access to your computer. 280 SSignatureError=The application's digital signature has an error. Do you want to run the application? It will be granted unrestricted access to your computer. 208 281 SUntrustedSource=The digital signature could not be verified by a trusted source. Only run if you trust the origin of the application. 209 SWarnFullPermissionsIgnorePolicy=The code executed will be given full permissions, ignoring any java policies you may have.282 SWarnFullPermissionsIgnorePolicy=The code executed will be given full permissions, ignoring any Java policies you may have. 210 283 STrustedSource=The digital signature has been validated by a trusted source. 211 284 SClipboardReadAccess=The application has requested read-only access to the system clipboard. Do you want to allow this action? … … 217 290 SAlwaysTrustPublisher=Always trust content from this publisher 218 291 SHttpsUnverified=The website's HTTPS certificate cannot be verified. 219 SNotAllSignedSummary=Only parts of this application code are signed. 220 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. 221 SNotAllSignedQuestion=Do you wish to proceed and run this application anyway? 292 SRememberOption=<b>Remember this option?</b> 293 SRememberAppletOnly=For applet 294 SRememberCodebase=For site <u>{0}</u> 295 SUnsignedSummary=An unsigned Java application wants to run 296 SUnsignedDetail=An unsigned application from the following location wants to run:<br/> <u>{0}</u><br/>The page which made the request was:<br/> <u>{1}</u><br/><br/><b>It is recommended you only run applications from sites you trust.</b> 297 SUnsignedAllowedBefore=<font color="green">You have accepted this applet previously.</font> 298 SUnsignedRejectedBefore=<font color="red">You have rejected this applet previously.</font> 299 SUnsignedQuestion=Allow the applet to run? 300 SPartiallySignedSummary=Only parts of this application code are signed. 301 SPartiallySignedDetail=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. 302 SPartiallySignedQuestion=Do you wish to proceed and run this application anyway? 222 303 SAuthenticationPrompt=The {0} server at {1} is requesting authentication. It says "{2}" 223 304 SJNLPFileIsNotSigned=This application contains a digital signature in which the launching JNLP file is not signed. 305 SAppletTitle=Applet title: {0} 306 STrustedOnlyAttributeFailure=This application specifies Trusted-only as True in its Manifest. {0} and requests permission level: {1}. This is not allowed. 307 STOAsignedMsgFully = The applet is fully signed 308 STOAsignedMsgAndSandbox = The applet is fully signed and sandboxed 309 STOAsignedMsgPartiall = The applet is not fully signed 310 STempPermNoFile=No file access 311 STempPermNoNetwork=No network access 312 STempPermNoExec=No command execution 313 STempNoFileOrNetwork=No file or network access 314 STempNoExecOrNetwork=No command execution or network access 315 STempNoFileOrExec=No file access or command execution 316 STempNoFileOrNetworkOrExec=No file access, network access, or command execution 317 STempAllMedia=All media 318 STempSoundOnly=Play audio 319 STempClipboardOnly=Access clipboard 320 STempPrintOnly=Print documents 321 STempAllFileAndPropertyAccess=All file and properties access 322 STempReadLocalFilesAndProperties=Read-only local files and properties 323 STempReflectionOnly=Java Reflection only 224 324 225 325 # Security - used for the More Information dialog … … 227 327 SBadExtendedKeyUsage=Resources contain entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing. 228 328 SBadNetscapeCertType=Resources contain entries whose signer certificate's NetscapeCertType extension doesn't allow code signing. 229 SHasUnsignedEntry=Resources contain unsigned entries which have not been integrity-checked.230 329 SHasExpiredCert=The digital signature has expired. 231 330 SHasExpiringCert=Resources contain entries whose signer certificate will expire within six months. … … 233 332 SUntrustedCertificate=The digital signature was generated with an untrusted certificate. 234 333 STrustedCertificate=The digital signature was generated with a trusted certificate. 235 SCNMisMatch=The expected hostname for this certificate is: "{0}"< BR>The address being connected to is: "{1}"236 SRunWithoutRestrictions=This application will be run without the security restrictions normally provided by java.334 SCNMisMatch=The expected hostname for this certificate is: "{0}"<br/>The address being connected to is: "{1}" 335 SRunWithoutRestrictions=This application will be run without the security restrictions normally provided by Java. 237 336 SCertificateDetails=Certificate Details 238 337 … … 264 363 CVSystem=System 265 364 266 # KeyStores: see KeyStores.java365 # KeyStores: see KeyStores.java 267 366 KS=KeyStore 268 367 KSCerts=Trusted Certificates 269 368 KSJsseCerts=Trusted JSSE Certificates 270 369 KSCaCerts=Trusted Root CA Certificates 271 KSJsseCaCerts=Trusted JSSE Root CA Certificates ,370 KSJsseCaCerts=Trusted JSSE Root CA Certificates 272 371 KSClientCerts=Client Authentication Certificates 273 372 … … 277 376 DCSourceInternal=<internal> 278 377 DCUnknownSettingWithName=Property "{0}" is unknown. 378 DCmaindircheckNotexists=After all attempts, your configuration directory {0} do not exists. 379 DCmaindircheckNotdir=Your configuration directory {0} is not directory. 380 DCmaindircheckRwproblem=Your configuration directory {0} can not be read/written properly. 279 381 280 382 # Value Validator messages. Messages should follow "Possible values ..." 281 383 VVPossibleValues=Possible values {0} 282 384 VVPossibleBooleanValues=are {0} or {1} 283 VVPossibleFileValues=include the absolute location of a file - it must begin with a / 284 VVPossibleFileValuesDOS=include the absolute location of a file - it must begin with a drive letter 385 VVPossibleFileValues=include an absolute path to a file or directory 285 386 VVPossibleRangedIntegerValues=are in range {0} to {1} (inclusive) 286 387 VVPossibleUrlValues=include any valid url (eg http://icedtea.classpath.org/hg/) … … 291 392 292 393 # Control Panel - Tab Descriptions 293 CPAboutDescription=View version information about Iced tea Control Panel.394 CPAboutDescription=View version information about IcedTea Control Panel. 294 395 CPNetworkSettingsDescription=Configure network settings, including how IcedTea-Web connects to the internet and whether to use any proxies. 295 396 CPTempInternetFilesDescription=Java stores application data for faster execution the next time you run it. … … 299 400 CPDebuggingDescription=Enable options here to help with debugging 300 401 CPDesktopIntegrationDescription=Set whether or not to allow creation of desktop shortcut. 402 CPJVMPluginArguments=Set JVM arguments for plugin. 403 CPJVMitwExec=Set JVM for IcedTea-Web \u2014 working best with OpenJDK 404 CPJVMitwExecValidation=Validate JVM for IcedTea-Web 405 CPJVMPluginSelectExec=Browse for JVM for IcedTea-Web 406 CPJVMnone=No validation result for 407 CPJVMvalidated=Validation result for 408 CPJVMvalueNotSet=Value is not set. Hardcoded JVM will be used. 409 CPJVMnotLaunched=Error, process was not launched, see console output for more info. 410 CPJVMnoSuccess=Error, process have not ended successfully, see output for details, but your java is not set correctly. 411 CPJVMopenJdkFound=Excellent, OpenJDK detected 412 CPJVMoracleFound=Great, Oracle java detected 413 CPJVMibmFound=Good, IBM java detected 414 CPJVMgijFound=Warning, gij detected 415 CPJVMstrangeProcess=Your path had an executable process, but it was not recognized. Verify the Java version in the console output. 416 CPJVMnotDir=Error, The path you chose is not a directory. 417 CPJVMisDir=Ok, the path you chose is a directory. 418 CPJVMnoJava=Error, the directory you chose does not contain bin/java. 419 CPJVMjava=Ok, the directory you chose contains bin/java. 420 CPJVMnoRtJar=Error, the directory you chose does not contain lib/rt.jar 421 CPJVMrtJar=Ok, the directory you chose contains lib/rt.jar. 422 CPJVMPluginAllowTTValidation=Validate JRE immediately 423 CPJVMNotokMessage1=You have entered invalid JDK value <u>({0})</u> with following error message: 424 CPJVMNotokMessage2=You might be seeing this message because: <blockquote> * Some validity tests have not been passed<br/> * Non-OpenJDK is detected</blockquote>With invalid JDK IcedTea-Web will probably not be able to start.<br/>You will have to modify or remove <u>{0}</u> property in your configuration file <u>{1}</u>. <br/>You should try to search for OpenJDK in your system or be sure you know what you are doing. 425 CPJVMconfirmInvalidJdkTitle=Confirm invalid JDK 426 CPJVMconfirmReset=Reset to default? 427 CPPolicyDetail=View or edit your user-level Java Policy File. This allows you to grant or deny runtime permissions to applets regardless of the standard security sandboxing rules. 428 CPPolicyTooltip=Open {0} in policy editor 429 CPPolicyEditorNotFound=Could not find a system policy file editor. Check that policytool is on your PATH. 301 430 302 431 # Control Panel - Buttons … … 306 435 CPButView=View... 307 436 CPButCertificates=Certificates... 437 CPButSimpleEditor=Simple editor 438 CPButAdvancedEditor=Advanced editor 308 439 309 440 # Control Panel - Headers 310 CPHead=IcedTea Web Control Panel 311 CPHeadAbout=About 312 CPHeadNetworkSettings=Network Proxy Settings 313 CPHeadTempInternetFiles=Temporary Internet Files 314 CPHeadJRESettings=Java Runtime Environment Settings 315 CPHeadCertificates=Certificates 316 CPHeadDebugging=Debugging Settings 317 CPHeadDesktopIntegration=Desktop Integrations 318 CPHeadSecurity=Security Settings 441 CPHead=IcedTea-Web Control Panel 442 CPHeadAbout=\u00a0About\u00a0IcedTea-Web\u00a0 443 CPHeadNetworkSettings=\u00a0Network\u00a0Proxy\u00a0Settings\u00a0 444 CPHeadTempInternetFiles=\u00a0Temporary\u00a0Internet\u00a0Files\u00a0 445 CPHeadJRESettings=\u00a0Java\u00a0Runtime\u00a0Environment\u00a0Settings\u00a0 446 CPHeadCertificates=\u00a0Certificates\u00a0 447 CPHeadDebugging=\u00a0Debugging\u00a0Settings\u00a0 448 CPHeadDesktopIntegration=\u00a0Desktop\u00a0Integrations\u00a0 449 CPHeadSecurity=\u00a0Security\u00a0Settings\u00a0 450 CPHeadJVMSettings=\u00a0JVM\u00a0Settings\u00a0 451 CPHeadPolicy=\u00a0Custom\u00a0Policy\u00a0Settings\u00a0 319 452 320 453 # Control Panel - Tabs … … 328 461 CPTabRuntimes=Runtimes 329 462 CPTabSecurity=Security 463 CPTabJVMSettings=JVM Settings 464 CPTabPolicy=Policy Settings 330 465 331 466 # Control Panel - AboutPanel 332 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/>467 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 limited to OpenJDK.<br/> 333 468 334 469 # Control Panel - AdvancedProxySettings … … 348 483 349 484 # Control Panel - DebugginPanel 350 DPEnableTracing=Enable tracing 351 DPEnableLogging=Enable logging 485 CPDebuggingPossibilites=Logging outputs 486 DPEnableLogging=Enable debugging 487 DPEnableLoggingHint=When this switch is on, then also debug messages are logged. Same as -verbose or ICEDTEAPLUGIN_DEBUG=true 488 DPEnableHeaders=Enable headers 489 DPEnableHeadersHint=When this switch is on, each logged message have header with additional information like user, place in code and time 490 DPEnableFile=Enable logging to file 491 CPFilesLogsDestDir=File logs directory 492 CPFilesLogsDestDirResert=Reset to default 493 DPEnableFileHint=output messages will be saved to file in your {0} directory 494 DPEnableStds=Enable logging to standard outputs 495 DPEnableStdsHint=messages will be printed to standard outputs 496 DPEnableSyslog=Enable logging to system logs 497 DPEnableSyslogHint=output messages will be saved to system logs 352 498 DPDisable=Disable 353 499 DPHide=Hide on startup 354 500 DPShow=Show on startup 501 DPShowPluginOnly=Show on plugin startup 502 DPShowJavawsOnly=Show on javaws startup 355 503 DPJavaConsole=Java Console 504 DPJavaConsoleDisabledHint=Java console is disabled. Use itweb-settings to configure it out of disabled to any show or hide value. 505 506 # PolicyEditor 507 PEUsage=policyeditor [-file policyfile] 508 PEHelpFlag=Print this message and exit 509 PEFileFlag=Specify a policyfile path to open 510 PECodebaseFlag=Specify (a) codebase URL(s) to add and/or focus in the editor 511 PETitle=Policy Editor 512 PEReadProps=Read system properties 513 PEReadPropsDetail=Allow applets to read system properties such as your username and home directory location 514 PEWriteProps=Write system properties 515 PEWritePropsDetail=Allow applets to (over)write system properties 516 PEReadFiles=Read from local files 517 PEReadFilesDetail=Allow applets to read from files in your home directory 518 PEWriteFiles=Write to local files 519 PEWriteFilesDetail=Allow applets to write to files in your home directory 520 PEDeleteFiles=Delete local files 521 PEDeleteFilesDetail=Allow applets to delete files in your home directory 522 PEReadSystemFiles=Read all system files 523 PEReadSystemFilesDetail=Allow applets read-only access to all locations on your computer 524 PEWriteSystemFiles=Write all system files 525 PEWriteSystemFilesDetail=Allow applets write-only access to all locations on your computer 526 PEReadTempFiles=Read from temp files 527 PEReadTempFilesDetail=Allow applets to read from your temporary files directory 528 PEWriteTempFiles=Write to temp files 529 PEWriteTempFilesDetail=Allow applets to write to your temporary files directory 530 PEDeleteTempFiles=Delete temp files 531 PEDeleteTempFilesDetail=Allow applets to delete files in your temporary files directory 532 PEAWTPermission=Window System Access 533 PEAWTPermissionDetail=Allow applets all AWT windowing system access 534 PEClipboard=Access clipboard 535 PEClipboardDetail=Allow applets to read from and write to your clipboard 536 PENetwork=Access the network 537 PENetworkDetail=Allow applets to establish any network connections 538 PEPrint=Print documents 539 PEPrintDetail=Allow applets to queue print jobs 540 PEPlayAudio=Play sounds 541 PEPlayAudioDetail=Allow applets to play sounds, but not record 542 PERecordAudio=Record audio 543 PERecordAudioDetail=Allow applets to record audio, but not play back 544 PEReflection=Java reflection 545 PEReflectionDetail=Allow applets to access the Java Reflection API 546 PEClassLoader=Get ClassLoader 547 PEClassLoaderDetail=Allow applets to access the system classloader (often used with Reflection) 548 PEClassInPackage=Access other packages 549 PEClassInPackageDetail=Allow applets to access classes from other applet packages (often used with Reflection) 550 PEDeclaredMembers=Access private class data 551 PEDeclaredMembersDetail=Allow applets to access normally hidden data from other Java classes (often used with Reflection) 552 PEAccessThreads=Modify threads 553 PEAccessThreadsDetail=Allow applets to start, stop, and otherwise manage threads 554 PEAccessThreadGroups=Modify threadgroups 555 PEAccessThreadGroupsDetail=Allow applets to start, stop, and otherwise manage thread groups 556 PEExec=Execute commands 557 PEExecDetail=Allow applets to execute system commands 558 PEGetEnv=Get environment variables 559 PEGetEnvDetail=Allow applets to read system environment variables 560 PECouldNotOpen=Unable to open policy file 561 PECouldNotSave=Unable to save policy file 562 PEAddCodebase=Add new Codebase 563 PERemoveCodebase=Remove 564 PECodebasePrompt=Enter a new codebase 565 PEGlobalSettings=All Applets 566 PESaveChanges=Save changes before exiting? 567 PEChangesSaved=Changes saved 568 PECheckboxLabel=Permissions 569 PECodebaseLabel=Codebases 570 PEFileMenu=File 571 PEOpenMenuItem=Open... 572 PESaveMenuItem=Save 573 PESaveAsMenuItem=Save As... 574 PEExitMenuItem=Exit 575 PEViewMenu=View 576 PECustomPermissionsItem=Custom Permissions... 577 PEFileModified=File Modification Warning 578 PEFileModifiedDetail=The policy file at {0} has been modified since it was opened. Reload and re-edit before saving? 579 PEGAccesUnowenedCode = Execute unowned code 580 PEGMediaAccess = Media access 581 PEGrightClick = right click to fold/unfold 582 PEGReadFileSystem = Read to system 583 PEGWriteFileSystem = Write to system 584 585 586 # Policy Editor CustomPolicyViewer 587 PECPTitle=Custom Policy Viewer 588 PECPListLabel=Other policies for {0} 589 PECPAddButton=Add 590 PECPRemoveButton=Remove 591 PECPCloseButton=Close 592 PECPType=type 593 PECPTarget=target 594 PECPActions=actions 595 PECPPrompt=Enter a custom permission. Do not include \"permission\" or punctuation marks. 596 597 # PolicyEditor key mnemonics. See KeyEvent.VK_* 598 # N 599 PEAddCodebaseMnemonic=78 600 # R 601 PERemoveCodebaseMnemonic=82 602 # A 603 PEOkButtonMnemonic=65 604 # C 605 PECancelButtonMnemonic=67 606 # F 607 PEFileMenuMnemonic=70 608 # I 609 PEViewMenuMnemonic=73 610 # O 611 PEOpenMenuItemMnemonic=79 612 # S 613 PESaveMenuItemMnemonic=83 614 # A 615 PESaveAsMenuItemMnemonic=65 616 # X 617 PEExitMenuItemMnemonic=88 618 # U 619 PECustomPermissionsItemMnemonic=85 620 621 #conole itself labels 622 CONSOLErungc = Run GC 623 CONSOLErunFinalizers = Run Finalizers 624 CONSOLErunningFinalizers = Running finalization.... 625 CONSOLEmemoryInfo = Memory Info 626 CONSOLEsystemProperties = System Properties 627 CONSOLEclassLoaders = Available Classloaders 628 CONSOLEthreadList = Thread List 629 CONSOLEthread = Thread 630 CONSOLEnoClassLoaders = No Classloader info exists in system 631 CONSOLEmemoryMax = Max Memory 632 CONSOLEmemoryTotal = Total Memory 633 CONSOLEmemoryFree = Free Memory 634 CONSOLEClean=Clear 635 636 # console output pane labels 637 COPsortCopyAllDate=sort copy all by date 638 COPshowHeaders=Show headers: 639 COPuser=user 640 COPorigin=origin 641 COPlevel=level 642 COPdate=date 643 COPthread1=thread 1 644 COPthread2=thread 2 645 COPShowMessages=Show messages 646 COPstdOut=std. Out 647 COPstdErr=std. Err 648 COPjava=java 649 COPplugin=plugin 650 COPpreInit=pre-init 651 COPpluginOnly=plugin only 652 COPSortBy=Sort by 653 COPregex=Regular expression filter 654 COPAsArrived=As arrived (no sort) 655 COPcode=code 656 COPmessage=message 657 COPSearch=Search 658 COPautoRefresh=auto refresh 659 COPrefresh=refresh 660 COPApply=Apply 661 COPmark=mark 662 COPCopyAllPlain=Copy all (plain) 663 COPCopyAllRich=Copy all (rich) 664 COPnext=next>>> 665 COPprevious=<<<previous 666 COPcaseSensitive=case sensitive 667 COPincomplete=incomplete 668 COPhighlight=highlight 669 COPwordWrap=word wrap 670 COPdebug=debug 671 COPinfo=info 672 COPpostInit=post-init 673 COPcomplete=complete 674 COPmatch=match 675 COPnot=not 676 COPrevert=revert 677 COPitw=IcedTea-Web 678 COPclientApp=Client app. 356 679 357 680 # Control Panel - DesktopShortcutPanel … … 379 702 380 703 # Control Panel - SecurityGeneralPanel 381 SGPAllowUserGrantSigned=Allow users to grant permissions to signed content 382 SGPAllowUserGrantUntrust=Allow users to grant permissions to content from an untrusted authority 704 SGPAllowUserGrantSigned=Allow users to grant permissions to signed content 705 SGPAllowUserGrantUntrust=Allow users to grant permissions to content from an untrusted authority 383 706 SGPUseBrowserKeystore=Use certificates and keys in browser keystore (Unsupported) 384 707 SGPUsePersonalCertOneMatch=Use personal certificate automatically if only one matches server request (Unsupported) 385 SGPWarnCertHostMismatch=Warn if site certificate does not match hostname 708 SGPWarnCertHostMismatch=Warn if site certificate does not match hostname 386 709 SGPShowValid=Show site certificate even if it is valid (Unsupported) 387 SGPShowSandboxWarning=Show sandbox warning banner 388 SGPAllowUserAcceptJNLPSecurityRequests=Allow user to accept JNLP security requests 710 SGPShowSandboxWarning=Show sandbox warning banner 711 SGPAllowUserAcceptJNLPSecurityRequests=Allow user to accept JNLP security requests 389 712 SGPCheckCertRevocationList=Check certificates for revocation using Certificate Revocation Lists (CRLs) (Unsupported) 390 713 SGPEnableOnlineCertValidate=Enable online certificate validation (Unsupported) … … 398 721 # Control Panel - TemporaryInternetFilesPanel 399 722 TIFPEnableCache=Keep temporary files on my computer 400 TIFPLocation= Location723 TIFPLocation=\u00a0Location\u00a0 401 724 TIFPLocationLabel=Select the location where temporary files are kept 402 725 TIFPChange=Change 403 TIFPDiskSpace= Disk space726 TIFPDiskSpace=\u00a0Disk\u00a0space\u00a0 404 727 TIFPCompressionLevel=Select the compression level for JAR files 405 728 TIFPNone=None 406 729 TIFPMax=Max 407 TIFPCacheSize=Set the amount of disk space for storing temporary files 730 TIFPCacheSize=Set the amount of disk space for storing temporary files (MB) 408 731 TIFPDeleteFiles=Delete files 409 732 TIFPViewFiles=View files... 733 TIFPFileChooserChooseButton=Choose 410 734 411 735 # Control Panel - Cache Viewer … … 413 737 CVCPButRefresh=Refresh 414 738 CVCPButDelete=Delete 739 CVCPCleanCache=Purge 740 CVCPCleanCacheTip=Some errors may be caused by old files in your cache. Before submitting the bug, you may clear cache and try to run application again. \\\n You can clear cache by javaws -Xclearcache or via itw-settings Cache -> View files -> Purge 415 741 CVCPColLastModified=Last Modified 416 742 CVCPColSize=Size (Bytes) … … 438 764 CLGetDescription=Shows the value for property-name 439 765 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 440 CLResetDescription=Resets the value for property-name to it\'s default value 766 CLResetDescription=Resets the value for property-name to it\'s default value.\nall resets all properties recognized by IcedTea-Web to their default value. 441 767 CLInfoDescription=Shows more information about the given property 442 CLCheckDescription=Shows any properties that have been defined but are not recognized by IcedTea Web 443 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 768 CLCheckDescription=Shows any properties that have been defined but are not recognized by IcedTea-Web 769 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 770 771 # splash screen related 772 SPLASHerror = Click here for details. An exception has occurred. 773 SPLASH_ERROR = ERROR 774 SPLASHtitle = Title 775 SPLASHvendor = Vendor 776 SPLASHhomepage = Homepage 777 SPLASHdescription = Description 778 SPLASHClose= Close 779 SPLASHclosewAndCopyException = Close and copy the stack trace to clipboard 780 SPLASHexOccured = An exception has occurred... 781 SPLASHHome = Home 782 SPLASHcantCopyEx = Can not copy exception 783 SPLASHnoExRecorded = No exception recorded 784 SPLASHmainL1 = For even more information you can visit {0} and follow the steps described there on how to obtain necessary information to file bug 785 SPLASHurl = http://icedtea.classpath.org/wiki/IcedTea-Web#Filing_bugs 786 SPLASHurlLooks = http://icedtea.classpath.org/wiki/IcedTea-Web 787 SPLASHmainL3 = No further information available, try to launch the browser from the command line and examine the output. 788 SPLASHcloseAndCopyShorter = Close and copy to clipboard 789 SPLASHmainL4 = The folloing exception has occured. For more information, try to launch the browser from the command line and examine the output. 790 SPLASHmainL2 = Additional information may be available in the console or logs. Even more information is available if debugging is enabled. 791 SPLASHexWas = Exception was: 792 SPLASHcfl = Can't follow link to 793 SPLASHvendorsInfo = Information from vendor of your application 794 SPLASHanotherInfo = Another available info 795 SPLASHdefaultHomepage = Unspecified homepage, verify source rather 796 SPLASHerrorInInformation = Error during loading of information element, verify source rather 797 SPLASHmissingInformation = Information element is missing, verify source rather 798 SPLASHchainWas = This is the list of exceptions that occurred launching your applet. Please note, those exceptions can originate from multiple applets. For a helpful bug report, be sure to run only one applet. 799 800 CBCheckFile = The application is a local file. Codebase validation is disabled. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 801 CBCheckNoEntry = This application does not specify a Codebase in its manifest. Please verify with the applet's vendor. Continuing. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 802 CBCheckUnsignedPass = Codebase matches codebase manifest attribute, but application is unsigned. Continuing. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 803 CBCheckUnsignedFail= The application's codebase does NOT match the codebase specified in its manifest, but the application is unsigned. Continuing. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 804 CBCheckOkSignedOk = Codebase matches codebase manifest attribute, and application is signed. Continuing. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 805 CBCheckSignedAppletDontMatchException = Signed applets are not allowed to run when their actual Codebase does not match the Codebase specified in their manifest. Expected: {0}. Actual: {1}. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 806 CBCheckSignedFail = Application Codebase does NOT match the Codebase specified in the application's manifest, and this application is signed. You are strongly discouraged from running this application. See: http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/no_redeploy.html for details. 807 808 APPEXTSECappletSecurityLevelExtraHighId=Disable running of all Java applets 809 APPEXTSECappletSecurityLevelVeryHighId=Very High Security 810 APPEXTSECappletSecurityLevelHighId=High Security 811 APPEXTSECappletSecurityLevelLowId=Low Security 812 APPEXTSECappletSecurityLevelExtraHighExplanation=No applet will be run 813 APPEXTSECappletSecurityLevelVeryHighExplanation=No unsigned applets will be run 814 APPEXTSECappletSecurityLevelHighExplanation=User will be prompted for each unsigned applet 815 APPEXTSECappletSecurityLevelLowExplanation=All, even unsigned, applets will be run 816 APPEXTSECunsignedAppletActionAlways=Always trust this (matching) applet(s) 817 APPEXTSECunsignedAppletActionNever=Never trust this (matching) applet(s) 818 APPEXTSECunsignedAppletActionYes=This applet was visited and allowed 819 APPEXTSecunsignedAppletActionSandbox=This applet was visited and allowed to run with restricted privileges 820 APPEXTSECunsignedAppletActionNo=This applet was visited and denied 821 APPEXTSECControlPanelExtendedAppletSecurityTitle=Extended applet security 822 APPEXTSECguiTableModelTableColumnAction=Action 823 APPEXTSECguiTableModelTableColumnDateOfAction=Date of action 824 APPEXTSECguiTableModelTableColumnDocumentBase=Document-base 825 APPEXTSECguiTableModelTableColumnCodeBase=Code-base 826 APPEXTSECguiTableModelTableColumnArchives=Archives 827 APPEXTSECguiPanelAppletInfoHederPart1={0} {1} 828 APPEXTSECguiPanelAppletInfoHederPart2={0} from {1} 829 APPEXTSECguiPanelConfirmDeletionOf=Are you sure you want to delete following {0} items 830 APPEXTSECguiPanelHelpButton=Help 831 APPEXTSECguiPanelSecurityLevel=Security Level 832 APPEXTSECguiPanelGlobalBehaviourCaption=Settings of global behavior for applets 833 APPEXTSECguiPanelDeleteMenuSelected=selected 834 APPEXTSECguiPanelDeleteMenuAllA=all allowed (A) 835 APPEXTSECguiPanelDeleteMenuAllN=all forbidden (N) 836 APPEXTSECguiPanelDeleteMenuAlly=all approved (y) 837 APPEXTSECguiPanelDeleteMenuAlln=all rejected (n) 838 APPEXTSECguiPanelDeleteMenuAllAll=absolute all 839 APPEXTSECguiPanelDeleteButton=Delete 840 APPEXTSECguiPanelDeleteButtonToolTip=You can press delete key during browsing the table. It will act as delete selected 841 APPEXTSECguiPanelTestUrlButton=Test url 842 APPEXTSECguiPanelAddRowButton=Add new row 843 APPEXTSECguiPanelValidateTableButton=Validate table 844 APPEXTSECguiPanelAskeforeActionBox=Ask me before action 845 APPEXTSECguiPanelShowRegExesBox=Show full regular expressions 846 APPEXTSECguiPanelInverSelection=Invert selection 847 APPEXTSECguiPanelMoveRowUp=Move row up 848 APPEXTSECguiPanelMoveRowDown=Move row down 849 APPEXTSECguiPanelCustomDefs=User definitions 850 APPEXTSECguiPanelGlobalDefs=System definitions 851 APPEXTSECguiPanelDocTest=Type document base URL 852 APPEXTSECguiPanelCodeTest=Type code base URL 853 APPEXTSECguiPanelNoMatch=Nothing matched 854 APPEXTSECguiPanelMatchingNote=Please note, that only first matched result will be considered as result. 855 APPEXTSECguiPanelMatched=Matched 856 APPEXTSECguiPanelMatchingError=Error during matching: {0} 857 APPEXTSECguiPanelCanNotValidate=Can not validate, can not create tmp file - {0} 858 APPEXTSECguiPanelEmptyDoc=All document-bases must be full 859 APPEXTSECguiPanelEmptyCode=All code-bases must be full 860 APPEXTSECguiPanelTableValid=Table looks valid 861 APPEXTSECguiPanelTableInvalid=Invalid with following error: {0} 862 APPEXTSECguiPanelShowOnlyPermanent=Show only permanent records 863 APPEXTSECguiPanelShowOnlyTemporal=Show only previously temporarily decided records 864 APPEXTSECguiPanelShowAll=Show all records 865 APPEXTSECguiPanelShowOnlyPermanentA=Show only allowed permanent records 866 APPEXTSECguiPanelShowOnlyPermanentN=Show only forbidden permanent records 867 APPEXTSECguiPanelShowOnlyTemporalY=Show previously allowed applets records 868 APPEXTSECguiPanelShowOnlyTemporalN=Show previously denied applets records 869 APPEXTSEChelpHomeDialogue=Dialogue 870 APPEXTSEChelp=<body> \ 871 <h1>Help for Extended applet security - itw-settings, files and structures, dialogue</h1> \ 872 <p> \ 873 Extended Applet Security refers to security features for unsigned applets. Traditionally, only signed applets required user confirmation and unsigned applets ran automatically. This is represented by the 'low security' setting. Unsigned applets must be allowed or disallowed individually on 'high security' (the default), and additionally do not run at all on 'very high security'. In theory, unsigned applets can safely run automatically. In practice, however, any vulnerability in the Java security sandbox will prevent this from being true. \ 874 </p> \ 875 <p> \ 876 To do so it uses the <b>Security Level</b> main settings switch rules in the tables of <b>Custom definitions</b> and <b>Global definitions</b><br/> \ 877 You can read much more about development of (and help us to improve!) this feature at <a href="http://icedtea.classpath.org/wiki/Extended_Applets_Security">dedicated IcedTea-Web page</a> \ 878 </p> \ 879 <A name="level"><h2>Security Level</h2></A> \ 880 <p> \ 881 Its a main switch for "extended applet security". Its value is commonly stored in usrs_home/.icedtea/deployment.properties, but can be enforced via global settings in /etc/.java/deployment/deployment.properties or JAVA_HOME/lib/deployment.properties under the key <b>deployment.security.level</b><br/> \ 882 <li/><b>Disable running of all Java applets</b> - stored as <i>DENY_ALL</i> - No applet will be run<br/> \ 883 <blockquote cite="" > \ 884 No applet will be allowed to run. However the Java virtual machine will always be executed (and an error screen with reason appear instead of applets). To disable Java completely you can uninstall IcedTea-Web or disable it in your browser (if supported). The tables with records are of course ignored. \ 885 </blockquote> \ 886 <li/><b>Very High Security</b> - stored as <i>DENY_UNSIGNED</i> - No unsigned applets will be run<br/> \ 887 <blockquote cite="" > \ 888 No applet <b>unsigned</b> will be allowed to run (and an error screen with reason will appear instead of such applets). The tables with records are of course again ignored. \ 889 </blockquote> \ 890 <li/><b>High Security</b> - stored as <i>ASK_UNSIGNED</i> - User will be prompted for each unsigned applet<br/> \ 891 <blockquote cite="" > \ 892 All <b>unsigned</b> applets will be tested against the tables below if they should be allowed or forbidden to run. If they are not matched in the table then the user is prompted and the decision is stored in <a href="#table">tables</a> below. If the user denies the applet, an error screen with reason appears and the applet does not run. If the user allows applets to run, the user can choose to save this decision and whether to allow just one applet or a whole group of applets (see <a href="#dialogue"><b>Dialogue</b> paragraph </a>below). \ 893 <br/>This is default behavior. \ 894 </blockquote> \ 895 <li/><b>Low Security</b> - stored as <i>ALLOW_UNSIGNED</i> - All, even unsigned, applets will be run<br/> \ 896 <blockquote cite="" > \ 897 All applets <b>even unsigned</b> will be allowed to run. User will not be warned and the tables with records are of course again ignored. \ 898 </blockquote> \ 899 You need to press <b>ok</b> or <b>apply</b> button to make the changes take effect. \ 900 </p> \ 901 \ 902 \ 903 <h2><A name="table">Table with recorded actions</A></h2> \ 904 <p> \ 905 <h4>Custom x Global table</h4> \ 906 After each action in <b>High Security</b> dialogue the record is added to, or updated in, the table or configuration file. Commonly in users file - home/.icedtea/.appletTrustSettings - "Custom definition" panel.<br/> \ 907 But superuser can specify default behavior in /etc/.java/deployment/ .appletTrustSettings - "Global definition" panel.<br/> \ 908 <h4>"Syntax"</h4> \ 909 <li/><b>Action</b> - Desired behavior when applet is matched<br/> \ 910 <blockquote cite="" > \ 911 <li/><b>Always trust this applet</b> - This unsigned applet will always be run in High Security Security Level. It is stored as <i>A</i> in .appletTrustSettings<br/> \ 912 <li/><b>Never trust this applet</b> - This unsigned applet will never be run in High Security Security Level. It is stored as <i>N</i> in .appletTrustSettings<br/> \ 913 <li/><b>Visited and allowed</b> - When the user is asked about this applet again, a note that this applet was already trusted in past will be displayed. It is stored as <i>y</i> in .appletTrustSettings<br/> \ 914 <li/><b>Visited and denied</b> - When user will be asked about this applet again, he will see information that this applet was already denied in past. It is stored as <i>n</i> in .appletTrustSettings<br/> \ 915 </blockquote> \ 916 <li/><b>Date</b> - date of last action on this item (read only item)<br/> \ 917 <li/><b>Document base</b> - is the page from which the applet was requested. It is actually a regular expression to match a specific URL. See about regular expressions and their usage <a href="#regexes">lower</a><br/> \ 918 <li/><b>Code base</b> - is the URL where an applets code came from. It is actually a regular expression to match a specific URL. See about regular expressions and their usage <a href="#regexes">lower</a><br/> \ 919 <li/><b>Archives</b> - coma separated list of archives with applet's code. Can be empty if source code are just classes or group of applets is allowed<br/> \ 920 <br/> \ 921 When you change a value in the table, its effect is immediate. \ 922 <h4>Controls of tables</h4> \ 923 <p> \ 924 <li/><b>Delete</b> - deletes items as specified in combo box on side<br/> \ 925 <blockquote cite="" > \ 926 <li/><b>selected</b> - removes all selected items. Key <b>Del</b> does the same. Default behavior. <b>Multiple selections</b> allowed. Selection can be inverted by button even more on side<br/> \ 927 <li/><b>all allowed (A)</b> - removes all permanently trusted records<br/> \ 928 <li/><b>all forbidden (N)</b> - removes all permanently forbidden records<br/> \ 929 <li/><b>all approved (y)</b> - removes all previously (temporarily) trusted records<br/> \ 930 <li/><b>all rejected (n)</b> - removes all previously (temporarily) denied records<br/> \ 931 <li/><b>all</b> - will clear the table<br/> \ 932 <br/> \ 933 <b>Ask me before action</b> - switch to ask before each deletion (in bulk) or not to ask. Asking dialogue can be pretty long, so if you do not see the buttons, just press <b>Esc</b> \ 934 </blockquote> \ 935 <li/><b>Show full regular expressions</b> - Disable or Enable filtering of quotation marks \Q\E in code/document base columns. About regular expressions see more <a href="#regexes">lower</a><br/> \ 936 <br/> \ 937 <li/>Filtering in table(s)<br/> \ 938 <blockquote cite="" > \ 939 <li/><b>Show only permanent records</b> - Shows only permanently allowed <b>(A)</b> or denied <b>(N)</b> records. Default behavior<br/> \ 940 <li/><b>Show only temporarily decided records</b> - Shows only once allowed <b>(y)</b> or denied <b>(n)</b> informative records.<br/> \ 941 <li/><b>Show only permanently allowed records</b> - Shows only permanently allowed <b>(A)</b> records<br/> \ 942 <li/><b>Show only permanently denied records</b> - Shows only permanently denied <b>(N)</b> records<br/> \ 943 <li/><b>Show only temporarily allowed records</b> - Shows only once allowed <b>(y)</b> informative records.<br/> \ 944 <li/><b>Show only temporarily denied records</b> - Shows only once denied <b>(n)</b> informative records.<br/> \ 945 </blockquote> \ 946 </p> \ 947 <li/><b>Add new row</b> - will add new, exemplary filled, row with current date and empty archives <br/> \ 948 <li/><b>Validate table</b> - will test if table can save, load, and if each value is valid:<br/> \ 949 <blockquote cite="" > \ 950 <li/><b>Action</b> - is one of A,N,y,n<br/> \ 951 <li/><b>Date</b> - is valid date<br/> \ 952 <li/><b>Code base and document base</b> - are valid <a href="#regexes">regular expressions</a> or empty<br/> \ 953 <li/><b>Archives</b> - coma separated list of archives or empty<br/> \ 954 </blockquote> \ 955 <li/><b>Test url</b> - In two dialogues (in two steps) will let you enter document base and codebase, and then try to match them against all records. All matching items are returned! Last values are remembered> \ 956 <li/><b>Move row down/up</b><br/> \ 957 <blockquote cite="" > \ 958 Order of rows is important. First matched result is returned (permanent have priority). So you can prioritize your matches using these buttons. <br/> \ 959 For example, if you \Qhttp://blogs.com/\E.* regular expression to allow all applets on http://blogs.com, then it must be AFTER your \Qhttp://blogs.com/evilJohn\E.* regular expression forbidding all applets from blog of hacker evilJohn. \ 960 </blockquote> \ 961 </p> \ 962 <p> \ 963 <h2><A name="dialogue">Dialogue</A></h2> \ 964 If <a href="#level"><b>High Security</b></a> is set, and a new unsigned applet is hit then the dialogue is shown asking you to allow it or deny it. You can also <b>choose</b> if you want to allow or deny this applet <b>every-time</b> (A or N) you encounter it or for <b>just one run</b> (y,n).<br/> \ 965 You can also select to trust or deny (again temporarily or permanently) <b>all</b> the applets from <b>same, exact, codebase</b>. If you are visiting one page, which has various applets on various documents then this is a choice for you.<br/> \ 966 If you decide not to allow remembering your decision, then just a temporary record is made. If you revisit a page, a small green or red label will inform you about your last decision.<br/> \ 967 Once you select <b>remember</b> your decision, the dialog will <b>never appear again</b>. But you can <b>edit</b> your decision in <b>itw-settings application <a href="#table">table</a></b> (packed with IcedTea-Web). If you change your decision to temporary one (n,y) or delete its row, the dialogue will appear again. Of course you can switch also from Always to Never or vice versa. \ 968 <br/> \ 969 The dialogue always mentions the page on which an applet is displayed, and the URL from which it comes. There is also a hint, if you have ever visited this applet saying if you have allowed or rejected it in the past <br/> \ 970 <blockquote cite="" > \ 971 <h3>Controls</h3> \ 972 <blockquote cite="" > \ 973 <li/><b>Remember this option</b> - If set, then dialogue will never be shown for this applet or page again. \ 974 <blockquote cite="" > \ 975 <li/><b>For applet</b> - Exact applet will be allowed or denied \ 976 <li/><b>For site</b> - All applets from this place will be allowed or denied \ 977 </blockquote> \ 978 <li/><b>Proceed</b> - Applets, as selected above will be allowed \ 979 <li/><b>Cancel</b> - Applets, as selected above will be forbidden \ 980 </blockquote> \ 981 Be aware to "proceed" + "Remember this option" + "For site" on pages you do not know! It can make you vulnerable! \ 982 </blockquote> \ 983 </p> \ 984 <p> \ 985 <h2><A name="regexes">Regular expressions</A></h2> \ 986 IcedTea-Web extended applet security - uses a powerful matching engine to match exact (sets of) applets. Base stone is <b>Quotation</b> of URL \Q\E and <b>wildchars</b> llike .* or .? or more.<br/> \ 987 This was designed to suits the need to block or allow exact pages. The best is to show some examples:<br/> \ 988 N 12.12.2012 .* \Qhttp://blogs.com/evilJohn\E.* <br/> \ 989 N 12.12.2012 \Qhttp://blogs.com/goodJohn/evilApplet.html\E.* \Qhttp://blogs.com/goodJohn/\E goodJohnsArchive.jar <br/> \ 990 A 12.12.2012 \Qhttp://blogs.com/\E.* \Qhttp://blogs.com/\E.* <br/> \ 991 N 12.12.2012 .* \Qhttp://adds.com\E.* <br/> \ 992 Y 12.12.2012 .* \Qhttp://www.walter-fendt.de/ph14_jar/\E <br/> \ 993 <br/> \ 994 <i>So this table, created 12.12.2012:<br/></i> \ 995 <li/>Forbid all stuff which have some code on http://blogs.com/evilJohn pages<br/> \ 996 <li/>Forbidding also one exact applet from http://blogs.com/goodJohn/ with archive goodJohnsArchive.jar<br/> \ 997 <li/>Allowing all (other) applets from http://blogs.com/ but only when displayed also on http://blogs.com/<br/> \ 998 <li/>Forbidding all applets with code saved on http://adds.com (except on http://blogs.com/ - to have forbidden http://adds.com also on http://blogs.com/, this (http://adds.com) record must be above blogs record)<br/> \ 999 <li/>And finally allowing all nice physical applets on walter-fendt's pages <br/> \ 1000 <br/> \ 1001 Note - the date saved in .appletTrustSettings has a not so nice format, but I left this for now...<br/> \ 1002 <br/> \ 1003 All information about full regular expression syntax can be found on <a href="http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html">http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html</a> \ 1004 </p> \ 1005 <h2>Conclusion</h2> \ 1006 <p> \ 1007 Stay tuned to our homepage at <a href="http://icedtea.classpath.org/wiki/IcedTea-Web">http://icedtea.classpath.org/wiki/IcedTea-Web</a>!<br/> \ 1008 If you encounter any bug, feel free to file it in our <a href="http://icedtea.classpath.org/bugzilla/">bugzilla</a> ... According to <a href="http://icedtea.classpath.org/wiki/IcedTea-Web#Filing_bugs">http://icedtea.classpath.org/wiki/IcedTea-Web#Filing_bugs</a><br/> \ 1009 <br/> \ 1010 Safe browsing from your IcedTea-Web team... \ 1011 </p> \ 1012 </body> \ -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java
r348 r429 20 20 import java.applet.*; 21 21 import javax.sound.sampled.*; 22 import net.sourceforge.jnlp.util.logging.OutputController; 22 23 23 24 // based on Deane Richan's AppletAudioClip … … 48 49 clip.open(stream); 49 50 } catch (Exception ex) { 50 System.err.println("Error loading sound:" + location.toString()); 51 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Error loading sound:" + location.toString()); 52 OutputController.getLogger().log(ex); 51 53 clip = null; 52 54 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java
r418 r429 17 17 package net.sourceforge.jnlp.runtime; 18 18 19 import net.sourceforge.jnlp.util.logging.OutputController; 19 20 import java.applet.*; 20 21 import java.awt.*; … … 28 29 29 30 import net.sourceforge.jnlp.*; 31 import net.sourceforge.jnlp.splashscreen.SplashController; 30 32 import net.sourceforge.jnlp.util.*; 31 33 … … 88 90 // that do not have app code on the stack 89 91 WindowListener closer = new WindowAdapter() { 92 @Override 90 93 public void windowClosing(WindowEvent event) { 91 94 appletInstance.destroy(); 92 System.exit(0);95 JNLPRuntime.exit(0); 93 96 } 94 97 }; … … 104 107 */ 105 108 private void checkDestroyed() { 106 if (destroyed) 109 if (destroyed) { 107 110 throw new IllegalStateException("Illegal applet stub/context access: applet destroyed."); 111 } 108 112 } 109 113 … … 131 135 } 132 136 137 /** 138 * container must be SplashContoler 139 * 140 */ 141 public SplashController getSplashControler() { 142 143 return (SplashController)cont; 144 } 145 133 146 /** 134 147 * Initialize, start, and show the applet. … … 137 150 checkDestroyed(); 138 151 139 if (appletStarted) 152 if (appletStarted) { 140 153 return; 154 } 141 155 142 156 appletStarted = true; … … 145 159 AppletDesc appletDesc = file.getApplet(); 146 160 147 if (cont instanceof AppletStub) 161 if (cont instanceof AppletStub) { 148 162 applet.setStub((AppletStub) cont); 149 else 163 } 164 else { 150 165 applet.setStub(this); 166 } 151 167 152 168 cont.setLayout(new BorderLayout()); … … 166 182 try { 167 183 SwingUtilities.invokeAndWait(new Runnable() { 184 @Override 168 185 public void run() { 169 186 // do first because some applets need to be displayed before … … 185 202 } 186 203 } catch (Exception ex) { 187 if (JNLPRuntime.isDebug()) 188 ex.printStackTrace(); 204 OutputController.getLogger().log(ex); 189 205 190 206 // should also kill the applet? … … 198 214 * otherwise return null. 199 215 */ 216 @Override 200 217 public Applet getApplet(String name) { 201 218 checkDestroyed(); 202 219 203 if (name != null && name.equals(file.getApplet().getName())) 220 if (name != null && name.equals(file.getApplet().getName())) { 204 221 return applet; 205 else222 } else { 206 223 return null; 224 } 207 225 } 208 226 … … 212 230 public void setApplet(Applet applet) { 213 231 if (this.applet != null) { 214 if (JNLPRuntime.isDebug()) { 215 Exception ex = new IllegalStateException("Applet can only be set once."); 216 ex.printStackTrace(); 217 } 232 OutputController.getLogger().log(new IllegalStateException("Applet can only be set once.")); 218 233 return; 219 234 } … … 225 240 * from the JNLP file. 226 241 */ 242 @Override 227 243 public Enumeration<Applet> getApplets() { 228 244 checkDestroyed(); … … 234 250 * Returns an audio clip. 235 251 */ 252 @Override 236 253 public AudioClip getAudioClip(URL location) { 237 254 checkDestroyed(); … … 248 265 * Return an image loaded from the specified location. 249 266 */ 267 @Override 250 268 public Image getImage(URL location) { 251 269 checkDestroyed(); … … 260 278 * Not implemented yet. 261 279 */ 280 @Override 262 281 public void showDocument(java.net.URL uRL) { 263 282 checkDestroyed(); … … 268 287 * Not implemented yet. 269 288 */ 289 @Override 270 290 public void showDocument(java.net.URL uRL, java.lang.String str) { 271 291 checkDestroyed(); … … 276 296 * Not implemented yet. 277 297 */ 298 @Override 278 299 public void showStatus(java.lang.String str) { 279 300 checkDestroyed(); … … 284 305 * Required for JRE1.4, but not implemented yet. 285 306 */ 307 @Override 286 308 public void setStream(String key, InputStream stream) { 287 309 checkDestroyed(); … … 292 314 * Required for JRE1.4, but not implemented yet. 293 315 */ 316 @Override 294 317 public InputStream getStream(String key) { 295 318 checkDestroyed(); … … 301 324 * Required for JRE1.4, but not implemented yet. 302 325 */ 326 @Override 303 327 public Iterator<String> getStreamKeys() { 304 328 checkDestroyed(); … … 309 333 // stub methods 310 334 335 @Override 311 336 public void appletResize(int width, int height) { 312 337 checkDestroyed(); … … 321 346 } 322 347 348 @Override 323 349 public AppletContext getAppletContext() { 324 350 checkDestroyed(); … … 327 353 } 328 354 355 @Override 329 356 public URL getCodeBase() { 330 357 checkDestroyed(); … … 333 360 } 334 361 362 @Override 335 363 public URL getDocumentBase() { 336 364 checkDestroyed(); … … 341 369 // FIXME: Sun's applet code forces all parameters to lower case. 342 370 // Does Netx's JNLP code do the same, so we can remove the first lookup? 371 @Override 343 372 public String getParameter(String name) { 344 373 checkDestroyed(); 345 374 346 String s = (String)parameters.get(name);347 if (s != null) 375 String s = parameters.get(name); 376 if (s != null) { 348 377 return s; 349 350 return (String) parameters.get(name.toLowerCase()); 351 } 352 378 } 379 380 return parameters.get(name.toLowerCase()); 381 } 382 383 @Override 353 384 public boolean isActive() { 354 385 checkDestroyed(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/AppletInstance.java
r418 r429 21 21 22 22 import net.sourceforge.jnlp.*; 23 import net.sourceforge.jnlp.util.logging.OutputController; 23 24 24 25 /** … … 57 58 public void setApplet(Applet applet) { 58 59 if (this.applet != null) { 59 if (JNLPRuntime.isDebug()) { 60 Exception ex = new IllegalStateException("Applet can only be set once."); 61 ex.printStackTrace(); 62 } 60 OutputController.getLogger().log(new IllegalStateException("Applet can only be set once.")); 63 61 return; 64 62 } … … 130 128 applet.destroy(); 131 129 } catch (Exception ex) { 132 if (JNLPRuntime.isDebug()) 133 ex.printStackTrace(); 130 OutputController.getLogger().log(ex); 134 131 } 135 132 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
r418 r429 18 18 19 19 import java.awt.Window; 20 import java.io.File; 20 21 import java.net.URL; 21 22 import java.security.AccessControlContext; … … 38 39 import net.sourceforge.jnlp.security.SecurityDialogs; 39 40 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 41 import net.sourceforge.jnlp.util.logging.OutputController; 40 42 import net.sourceforge.jnlp.util.WeakList; 41 43 import net.sourceforge.jnlp.util.XDesktopEntry; … … 43 45 /** 44 46 * Represents a running instance of an application described in a 45 * JNLPFile. 46 * resources and destroy the application. <p>47 * JNLPFile. This class provides a way to track the application's 48 * resources and destroy the application. 47 49 * 48 50 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 64 66 65 67 /** 68 * <p> 66 69 * Every application/applet gets its own AppContext. This allows us to do 67 70 * things like have two different look and feels for two different applets 68 71 * (running in the same VM), allows untrusted programs to manipulate the 69 * event queue (safely) and (possibly) more.<p> 70 * 72 * event queue (safely) and (possibly) more. 73 * </p> 74 * <p> 71 75 * It is set to the AppContext which created this ApplicationInstance 76 * </p> 72 77 */ 73 78 private AppContext appContext; … … 147 152 XDesktopEntry entry = new XDesktopEntry(file); 148 153 ShortcutDesc sd = file.getInformation().getShortcut(); 149 154 File possibleDesktopFile = entry.getLinuxDesktopIconFile(); 155 if (possibleDesktopFile.exists()) { 156 OutputController.getLogger().log("ApplicationInstance.addMenuAndDesktopEntries(): file - " 157 + possibleDesktopFile.getAbsolutePath() + " already exists. Not proceeding with desktop additions"); 158 return; 159 } 150 160 if (shouldCreateShortcut(sd)) { 151 161 entry.createDesktopShortcut(); … … 156 166 * Sun's WebStart implementation doesnt seem to do anything under GNOME 157 167 */ 158 if (JNLPRuntime.isDebug()) { 159 System.err.println("ApplicationInstance.addMenuAndDesktopEntries():" 160 + " Adding menu entries NOT IMPLEMENTED"); 161 } 168 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "ApplicationInstance.addMenuAndDesktopEntries():" 169 + " Adding menu entries NOT IMPLEMENTED"); 162 170 } 163 171 … … 172 180 */ 173 181 private boolean shouldCreateShortcut(ShortcutDesc sd) { 182 if (JNLPRuntime.isTrustAll()) { 183 return (sd != null && sd.onDesktop()); 184 } 174 185 String currentSetting = JNLPRuntime.getConfiguration() 175 186 .getProperty(DeploymentConfiguration.KEY_CREATE_DESKTOP_SHORTCUT); … … 208 219 * also collectable so basically is almost never called (an 209 220 * application would have to close its windows and exit its 210 * threads but not call System.exit).221 * threads but not call JNLPRuntime.exit). 211 222 */ 212 223 public void finalize() { … … 284 295 int nthreads = group.enumerate(threads); 285 296 for (int i = 0; i < nthreads; i++) { 286 if (JNLPRuntime.isDebug()) 287 System.out.println("Interrupt thread: " + threads[i]); 288 297 OutputController.getLogger().log("Interrupt thread: " + threads[i]); 289 298 threads[i].interrupt(); 290 299 } 291 300 292 301 // then stop 293 Thread. currentThread().yield();302 Thread.yield(); 294 303 nthreads = group.enumerate(threads); 295 304 for (int i = 0; i < nthreads; i++) { 296 if (JNLPRuntime.isDebug()) 297 System.out.println("Stop thread: " + threads[i]); 298 305 OutputController.getLogger().log("Stop thread: " + threads[i]); 299 306 threads[i].stop(); 300 307 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/Boot.java
r418 r429 29 29 import java.util.Map; 30 30 31 import javax.swing.UIManager; 32 31 33 import net.sourceforge.jnlp.LaunchException; 32 34 import net.sourceforge.jnlp.Launcher; 33 35 import net.sourceforge.jnlp.ParserSettings; 36 import net.sourceforge.jnlp.about.AboutDialog; 34 37 import net.sourceforge.jnlp.cache.CacheUtil; 35 38 import net.sourceforge.jnlp.cache.UpdatePolicy; 39 import net.sourceforge.jnlp.config.DeploymentConfiguration; 36 40 import net.sourceforge.jnlp.security.viewer.CertificateViewer; 37 41 import net.sourceforge.jnlp.services.ServiceUtil; 42 import net.sourceforge.jnlp.util.logging.OutputController; 43 import sun.awt.AppContext; 44 import sun.awt.SunToolkit; 38 45 39 46 /** 40 * This is the main entry point for the JNLP client. 47 * This is the main entry point for the JNLP client. The main 41 48 * method parses the command line parameters and loads a JNLP 42 * file into the secure runtime environment. 49 * file into the secure runtime environment. This class is meant 43 50 * to be called from the command line or file association; to 44 51 * initialize the netx engine from other code invoke the 45 * <code>JNLPRuntime.initialize</code>method after configuring52 * {@link JNLPRuntime#initialize} method after configuring 46 53 * the runtime. 47 54 * … … 54 61 // should inherit the same options as this instance (store argv?) 55 62 56 private static final String name = Boot.class.getPackage().getImplementationTitle(); 57 private static final String version = Boot.class.getPackage().getImplementationVersion(); 58 59 /** the text to display before launching the about link */ 60 private static final String aboutMessage = "" 61 + name + " " + version 62 + "\n" 63 + R("BLaunchAbout"); 63 public static final String name = Boot.class.getPackage().getImplementationTitle(); 64 public static final String version = Boot.class.getPackage().getImplementationVersion(); 65 66 private static final String nameAndVersion = name + " " + version; 64 67 65 68 private static final String miniLicense = "\n" … … 82 85 + "\n"; 83 86 87 private static final String itwInfoMessage = "" 88 + nameAndVersion 89 + "\n\n* " 90 + R("BAboutITW") 91 + "\n* " 92 + R("BFileInfoAuthors") 93 + "\n* " 94 + R("BFileInfoNews") 95 + "\n* " 96 + R("BFileInfoCopying"); 97 84 98 private static final String helpMessage = "\n" 85 99 + "Usage: " + R("BOUsage") + "\n" … … 91 105 + "\n" 92 106 + "run-options:" + "\n" 107 + " -version " + R("BOVersion") + "\n" 93 108 + " -arg arg " + R("BOArg") + "\n" 94 109 + " -param name=value " + R("BOParam") + "\n" … … 101 116 + " -headless " + R("BOHeadless") + "\n" 102 117 + " -strict " + R("BOStrict") + "\n" 118 + " -xml " + R("BOXml") + "\n" 119 + " -allowredirect " + R("BOredirect") + "\n" 103 120 + " -Xnofork " + R("BXnofork") + "\n" 104 121 + " -Xclearcache " + R("BXclearcache") + "\n" 122 + " -Xignoreheaders " + R("BXignoreheaders") + "\n" 105 123 + " -help " + R("BOHelp") + "\n"; 106 124 … … 115 133 args = argsIn; 116 134 135 if (AppContext.getAppContext() == null) { 136 SunToolkit.createNewAppContext(); 137 } 138 if (null != getOption("-headless")) { 139 JNLPRuntime.setHeadless(true); 140 } 141 142 DeploymentConfiguration.move14AndOlderFilesTo15StructureCatched(); 143 117 144 if (null != getOption("-viewer")) { 118 119 145 try { 120 146 CertificateViewer.main(null); 121 System.exit(0);147 JNLPRuntime.exit(0); 122 148 } catch (Exception e) { 123 // TODO Auto-generated catch block 124 e.printStackTrace(); 149 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 125 150 } 126 151 } 152 153 if (null != getOption("-version")) { 154 OutputController.getLogger().printOutLn(nameAndVersion); 155 JNLPRuntime.exit(0); 127 156 } 128 157 129 158 if (null != getOption("-license")) { 130 System.out.println(miniLicense);131 System.exit(0);159 OutputController.getLogger().printOutLn(miniLicense); 160 JNLPRuntime.exit(0); 132 161 } 133 162 134 163 if (null != getOption("-help")) { 135 System.out.println(helpMessage); 136 System.exit(0); 137 } 138 139 if (null != getOption("-about")) 140 System.out.println(aboutMessage); 164 OutputController.getLogger().printOutLn(helpMessage); 165 JNLPRuntime.exit(0); 166 } 167 168 if (null != getOption("-about")) { 169 OutputController.getLogger().printOutLn(itwInfoMessage); 170 if (null != getOption("-headless")) { 171 JNLPRuntime.exit(0); 172 } else { 173 try { 174 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 175 } catch (Exception e) { 176 OutputController.getLogger().log("Unable to set system look and feel"); 177 } 178 OutputController.getLogger().printOutLn(R("BLaunchAbout")); 179 AboutDialog.display(); 180 return; 181 } 182 } 141 183 142 184 if (null != getOption("-verbose")) … … 148 190 } 149 191 150 if (null != getOption("-headless"))151 JNLPRuntime.setHeadless(true);152 153 192 if (null != getOption("-noupdate")) 154 193 JNLPRuntime.setDefaultUpdatePolicy(UpdatePolicy.NEVER); … … 160 199 JNLPRuntime.setTrustAll(true); 161 200 } 201 if (null != getOption("-Xtrustnone")) { 202 JNLPRuntime.setTrustNone(true); 203 } 204 if (null != getOption("-Xignoreheaders")) { 205 JNLPRuntime.setIgnoreHeaders(true); 206 } 207 if (null != getOption("-allowredirect")) { 208 JNLPRuntime.setAllowRedirect(true); 209 } 162 210 163 211 JNLPRuntime.setInitialArgments(Arrays.asList(argsIn)); 164 212 165 // do in a privileged action to clear the security context of166 // the Boot13 class, which doesn't have any privileges in167 // JRE1.3; JRE1.4 works without Boot13 or this PrivilegedAction.168 213 AccessController.doPrivileged(new Boot()); 169 214 … … 193 238 extra.put("properties", getOptions("-property")); 194 239 195 boolean strict = (null != getOption("-strict")); 196 ParserSettings settings = new ParserSettings(strict); 240 ParserSettings settings = ParserSettings.setGlobalParserSettingsFromArgs(args); 197 241 198 242 try { … … 200 244 launcher.setParserSettings(settings); 201 245 launcher.setInformationToMerge(extra); 202 launcher.launch(getFileLocation() , true);246 launcher.launch(getFileLocation()); 203 247 } catch (LaunchException ex) { 204 248 // default handler prints this 205 249 } catch (Exception ex) { 206 if (JNLPRuntime.isDebug()) 207 ex.printStackTrace(); 208 250 OutputController.getLogger().log(ex); 209 251 fatalError(R("RUnexpected", ex.toString(), ex.getStackTrace()[0])); 210 252 } … … 214 256 215 257 private static void fatalError(String message) { 216 System.err.println("netx: " + message); 217 System.exit(1); 218 } 219 220 /** 221 * Returns the location of the about.jnlp file or null if this file 222 * does not exist. 223 */ 224 private static String getAboutFile() { 225 ClassLoader cl = Boot.class.getClassLoader(); 226 if (cl == null) { 227 cl = ClassLoader.getSystemClassLoader(); 228 } 229 try { 230 //extracts full path to about.jnlp 231 String s = cl.getResource("net/sourceforge/jnlp/runtime/Boot.class").toString(); 232 s=s.substring(0,s.indexOf("!")); 233 s=s.substring(s.indexOf(":")+1); 234 s=s.substring(s.indexOf(":")+1); 235 s="file://"+s.replace("netx.jar","about.jnlp"); 236 if (JNLPRuntime.isDebug()){ 237 System.out.println("Using " + s + " as about.jnlp URL"); 238 } 239 240 return s; 241 } catch (Exception e) { 242 e.printStackTrace(); 243 return null; 244 } 258 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "netx: " + message); 259 JNLPRuntime.exit(1); 245 260 } 246 261 … … 253 268 String location = getJNLPFile(); 254 269 255 // override -jnlp with aboutFile256 if (getOption("-about") != null) {257 location = getAboutFile();258 if (location == null)259 fatalError(R("RNoAboutJnlp"));260 } else {261 location = getJNLPFile();262 }263 264 270 if (location == null) { 265 System.out.println(helpMessage); 266 System.exit(1); 267 } 268 269 if (JNLPRuntime.isDebug()) 270 System.out.println(R("BFileLoc") + ": " + location); 271 OutputController.getLogger().printOutLn(helpMessage); 272 JNLPRuntime.exit(1); 273 } 274 275 OutputController.getLogger().log(R("BFileLoc") + ": " + location); 271 276 272 277 URL url = null; … … 279 284 url = new URL(ServiceUtil.getBasicService().getCodeBase(), location); 280 285 } catch (Exception e) { 286 OutputController.getLogger().log(e); 281 287 fatalError("Invalid jnlp file " + location); 282 if (JNLPRuntime.isDebug())283 e.printStackTrace();284 288 } 285 289 … … 293 297 294 298 if (args.length == 0) { 295 System.out.println(helpMessage);296 System.exit(0);299 OutputController.getLogger().printOutLn(helpMessage); 300 JNLPRuntime.exit(0); 297 301 } else if (args.length == 1) { 298 302 return args[args.length - 1]; … … 304 308 return lastArg; 305 309 } else { 306 System.out.println(helpMessage);307 System.exit(0);310 OutputController.getLogger().printOutLn(helpMessage); 311 JNLPRuntime.exit(0); 308 312 } 309 313 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java
r418 r429 50 50 import java.util.Map; 51 51 import java.util.concurrent.ConcurrentHashMap; 52 import java.util.jar.JarFile; 52 import net.sourceforge.jnlp.util.logging.OutputController; 53 import net.sourceforge.jnlp.util.JarFile; 53 54 54 55 import net.sourceforge.jnlp.util.UrlUtils; … … 82 83 83 84 @Override 84 public JarFile retrieve(URL url) throws IOException {85 public java.util.jar.JarFile retrieve(URL url) throws IOException { 85 86 URL localUrl = mapping.get(url); 86 87 … … 104 105 returnFile.getManifest().getMainAttributes().putValue("Class-Path", ""); 105 106 106 if (JNLPRuntime.isDebug()) { 107 System.err.println("Class-Path attribute cleared for " + returnFile.getName()); 108 } 107 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Class-Path attribute cleared for " + returnFile.getName()); 108 109 109 110 110 } catch (NullPointerException npe) { … … 123 123 * This method is a copy of URLJarFile.retrieve() without the callback check. 124 124 */ 125 private JarFile cacheJarFile(URL url) throws IOException {126 JarFile result = null;125 private java.util.jar.JarFile cacheJarFile(URL url) throws IOException { 126 java.util.jar.JarFile result = null; 127 127 128 128 final int BUF_SIZE = 2048; … … 133 133 try { 134 134 result = 135 AccessController.doPrivileged(new PrivilegedExceptionAction< JarFile>() {135 AccessController.doPrivileged(new PrivilegedExceptionAction<java.util.jar.JarFile>() { 136 136 @Override 137 public JarFile run() throws IOException {137 public java.util.jar.JarFile run() throws IOException { 138 138 OutputStream out = null; 139 139 File tmpFile = null; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/FakePacEvaluator.java
r348 r429 40 40 import static net.sourceforge.jnlp.runtime.Translator.R; 41 41 import java.net.URL; 42 import net.sourceforge.jnlp.util.logging.OutputController; 42 43 43 44 /** … … 47 48 @Override 48 49 public String getProxies(URL url) { 49 if (JNLPRuntime.isDebug()) { 50 System.err.println(R("RPRoxyPacNotSupported")); 51 } 50 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RPRoxyPacNotSupported")); 52 51 return "DIRECT"; 53 52 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
r418 r429 18 18 import static net.sourceforge.jnlp.runtime.Translator.R; 19 19 20 import java.io.Closeable;21 20 import java.io.File; 22 21 import java.io.FileOutputStream; … … 56 55 import java.util.Vector; 57 56 import java.util.concurrent.ConcurrentHashMap; 57 import java.util.concurrent.locks.ReentrantLock; 58 import java.util.jar.Attributes; 58 59 import java.util.jar.JarEntry; 59 import java.util.jar.JarFile;60 60 import java.util.jar.Manifest; 61 61 62 62 import net.sourceforge.jnlp.AppletDesc; 63 63 import net.sourceforge.jnlp.ApplicationDesc; 64 import net.sourceforge.jnlp.DownloadOptions;65 64 import net.sourceforge.jnlp.ExtensionDesc; 66 65 import net.sourceforge.jnlp.JARDesc; … … 70 69 import net.sourceforge.jnlp.LaunchDesc; 71 70 import net.sourceforge.jnlp.LaunchException; 71 import net.sourceforge.jnlp.NullJnlpFileException; 72 72 import net.sourceforge.jnlp.ParseException; 73 import net.sourceforge.jnlp.ParserSettings; 73 74 import net.sourceforge.jnlp.PluginBridge; 74 75 import net.sourceforge.jnlp.ResourcesDesc; … … 77 78 import net.sourceforge.jnlp.cache.CacheUtil; 78 79 import net.sourceforge.jnlp.cache.IllegalResourceDescriptorException; 80 import net.sourceforge.jnlp.cache.NativeLibraryStorage; 79 81 import net.sourceforge.jnlp.cache.ResourceTracker; 80 82 import net.sourceforge.jnlp.cache.UpdatePolicy; 81 import net.sourceforge.jnlp.security.SecurityDialogs; 82 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 83 import net.sourceforge.jnlp.security.AppVerifier; 84 import net.sourceforge.jnlp.security.JNLPAppVerifier; 85 import net.sourceforge.jnlp.security.PluginAppVerifier; 86 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletTrustConfirmation; 83 87 import net.sourceforge.jnlp.tools.JarCertVerifier; 84 import net.sourceforge.jnlp.util.FileUtils; 88 import net.sourceforge.jnlp.util.JarFile; 89 import net.sourceforge.jnlp.util.StreamUtils; 90 import net.sourceforge.jnlp.util.UrlUtils; 91 import net.sourceforge.jnlp.util.logging.OutputController; 85 92 import sun.misc.JarIndex; 86 93 87 94 /** 88 * Classloader that takes it's resources from a JNLP file. 95 * Classloader that takes it's resources from a JNLP file. If the 89 96 * JNLP file defines extensions, separate classloaders for these 90 * will be created automatically. 97 * will be created automatically. Classes are loaded with the 91 98 * security context when the classloader was created. 92 99 * … … 103 110 final public static String TEMPLATE = "JNLP-INF/APPLICATION_TEMPLATE.JNLP"; 104 111 final public static String APPLICATION = "JNLP-INF/APPLICATION.JNLP"; 105 112 113 /** Actions to specify how cache is to be managed **/ 114 public static enum DownloadAction { 115 DOWNLOAD_TO_CACHE, REMOVE_FROM_CACHE, CHECK_CACHE 116 } 117 118 public static enum SigningState { 119 FULL, PARTIAL, NONE 120 } 121 106 122 /** True if the application has a signed JNLP File */ 107 123 private boolean isSignedJNLP = false; 108 124 109 /** map from JNLPFile u rlto shared classloader */110 private static Map<String, JNLPClassLoader> u rlToLoader =111 new HashMap<String, JNLPClassLoader>(); // never garbage collected! 112 113 /** the directory for native code*/114 private File nativeDir = null; // if set, some native code exists115 116 /** a list of directories that contain native libraries*/117 private List<File> nativeDirectories = Collections.synchronizedList(new LinkedList<File>());125 /** map from JNLPFile unique key to shared classloader */ 126 private static Map<String, JNLPClassLoader> uniqueKeyToLoader = new ConcurrentHashMap<String, JNLPClassLoader>(); 127 128 /** map from JNLPFile unique key to lock, the lock is needed to enforce correct 129 * initialization of applets that share a unique key*/ 130 private static Map<String, ReentrantLock> uniqueKeyToLock = new HashMap<String, ReentrantLock>(); 131 132 /** Provides a search path & temporary storage for native code */ 133 private NativeLibraryStorage nativeLibraryStorage; 118 134 119 135 /** security context */ … … 150 166 private ArrayList<Permission> runtimePermissions = new ArrayList<Permission>(); 151 167 152 /** all jars not yet part of classloader or active */ 153 private List<JARDesc> available = new ArrayList<JARDesc>(); 154 155 /** all of the jar files that were verified */ 156 private ArrayList<String> verifiedJars = null; 157 158 /** all of the jar files that were not verified */ 159 private ArrayList<String> unverifiedJars = null; 168 /** all jars not yet part of classloader or active 169 * Synchronized since this field may become shared data between multiple classloading threads. 170 * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). 171 */ 172 private List<JARDesc> available = Collections.synchronizedList(new ArrayList<JARDesc>()); 160 173 161 174 /** the jar cert verifier tool to verify our jars */ 162 private JarCertVerifier jcv = null; 163 164 private boolean signing = false; 165 166 /** ArrayList containing jar indexes for various jars available to this classloader */ 167 private ArrayList<JarIndex> jarIndexes = new ArrayList<JarIndex>(); 168 169 /** Set of classpath strings declared in the manifest.mf files */ 170 private Set<String> classpaths = new HashSet<String>(); 171 172 /** File entries in the jar files available to this classloader */ 173 private TreeSet<String> jarEntries = new TreeSet<String>(); 174 175 /** Map of specific original (remote) CodeSource Urls to securitydesc */ 176 private HashMap<URL, SecurityDesc> jarLocationSecurityMap = 177 new HashMap<URL, SecurityDesc>(); 175 private final JarCertVerifier jcv; 176 177 private SigningState signing = SigningState.NONE; 178 179 /** ArrayList containing jar indexes for various jars available to this classloader 180 * Synchronized since this field may become shared data between multiple classloading threads/ 181 * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). 182 */ 183 private List<JarIndex> jarIndexes = Collections.synchronizedList(new ArrayList<JarIndex>()); 184 185 /** Set of classpath strings declared in the manifest.mf files 186 * Synchronized since this field may become shared data between multiple classloading threads. 187 * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). 188 */ 189 private Set<String> classpaths = Collections.synchronizedSet(new HashSet<String>()); 190 191 /** File entries in the jar files available to this classloader 192 * Synchronized sinc this field may become shared data between multiple classloading threads. 193 * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). 194 */ 195 private Set<String> jarEntries = Collections.synchronizedSet(new TreeSet<String>()); 196 197 /** Map of specific original (remote) CodeSource Urls to securitydesc 198 * Synchronized since this field may become shared data between multiple classloading threads. 199 * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). 200 */ 201 private Map<URL, SecurityDesc> jarLocationSecurityMap = 202 Collections.synchronizedMap(new HashMap<URL, SecurityDesc>()); 178 203 179 204 /*Set to prevent once tried-to-get resources to be tried again*/ … … 189 214 /** Name of the application's main class */ 190 215 private String mainClass = null; 191 216 192 217 /** 193 218 * Variable to track how many times this loader is in use 194 219 */ 195 220 private int useCount = 0; 221 222 private boolean enableCodeBase = false; 223 224 private final SecurityDelegate securityDelegate; 196 225 197 226 /** … … 201 230 */ 202 231 protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy) throws LaunchException { 203 this(file, policy,null);232 this(file, policy, null, false); 204 233 } 205 234 … … 208 237 * 209 238 * @param file the JNLP file 210 * @param name of the application's main class 211 */ 212 protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy, String mainName) throws LaunchException { 239 * @param policy the UpdatePolicy for this class loader 240 * @param mainName name of the application's main class 241 */ 242 protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException { 213 243 super(new URL[0], JNLPClassLoader.class.getClassLoader()); 214 244 215 if (JNLPRuntime.isDebug()) 216 System.out.println("New classloader: " + file.getFileLocation()); 245 OutputController.getLogger().log("New classloader: " + file.getFileLocation()); 217 246 218 247 this.file = file; … … 220 249 this.resources = file.getResources(); 221 250 251 this.nativeLibraryStorage = new NativeLibraryStorage(tracker); 252 222 253 this.mainClass = mainName; 254 255 this.enableCodeBase = enableCodeBase; 256 257 258 AppVerifier verifier; 259 260 if (file instanceof PluginBridge && !((PluginBridge)file).useJNLPHref()) { 261 verifier = new PluginAppVerifier(); 262 } else { 263 verifier = new JNLPAppVerifier(); 264 } 265 266 jcv = new JarCertVerifier(verifier); 267 268 if (this.enableCodeBase) { 269 addToCodeBaseLoader(this.file.getCodeBase()); 270 } 271 272 this.securityDelegate = new SecurityDelegateImpl(this); 223 273 224 274 // initialize extensions … … 226 276 227 277 initializeResources(); 278 279 //loading mainfests before resources are initialised may cause waiting for resources 280 file.getManifestsAttributes().setLoader(this); 228 281 229 282 // initialize permissions … … 232 285 setSecurity(); 233 286 287 ManifestAttributesChecker mac = new ManifestAttributesChecker(security, file, signing, securityDelegate); 288 mac.checkAll(); 289 234 290 installShutdownHooks(); 291 235 292 236 293 } … … 249 306 * cleanup things they created 250 307 */ 251 if (nativeDir != null) { 252 if (JNLPRuntime.isDebug()) { 253 System.out.println("Cleaning up native directory" + nativeDir.getAbsolutePath()); 254 } 255 try { 256 FileUtils.recursiveDelete(nativeDir, 257 new File(System.getProperty("java.io.tmpdir"))); 258 } catch (IOException e) { 259 /* 260 * failed to delete a file in tmpdir, no big deal (not 261 * to mention that the VM is shutting down at this 262 * point so no much we can do) 263 */ 264 } 265 } 308 nativeLibraryStorage.cleanupTemporaryFolder(); 266 309 } 267 310 }); … … 269 312 270 313 private void setSecurity() throws LaunchException { 271 272 URL codebase = null; 273 274 if (file.getCodeBase() != null) { 275 codebase = file.getCodeBase(); 276 } else { 277 //Fixme: codebase should be the codebase of the Main Jar not 278 //the location. Although, it still works in the current state. 279 codebase = file.getResources().getMainJAR().getLocation(); 280 } 281 282 /** 283 * When we're trying to load an applet, file.getSecurity() will return 284 * null since there is no jnlp file to specify permissions. We 285 * determine security settings here, after trying to verify jars. 286 */ 287 if (file instanceof PluginBridge) { 288 if (signing == true) { 289 this.security = new SecurityDesc(file, 290 SecurityDesc.ALL_PERMISSIONS, 291 codebase.getHost()); 292 } else { 293 this.security = new SecurityDesc(file, 294 SecurityDesc.SANDBOX_PERMISSIONS, 295 codebase.getHost()); 296 } 297 } else { //regular jnlp file 298 299 /* 300 * Various combinations of the jars being signed and <security> tags being 301 * present are possible. They are treated as follows 302 * 303 * Jars JNLP File Result 304 * 305 * Signed <security> Appropriate Permissions 306 * Signed no <security> Sandbox 307 * Unsigned <security> Error 308 * Unsigned no <security> Sandbox 309 * 310 */ 311 if (!file.getSecurity().getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS) && !signing) { 312 throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LUnsignedJarWithSecurity"), R("LUnsignedJarWithSecurityInfo")); 313 } else if (signing == true) { 314 this.security = file.getSecurity(); 315 } else { 316 this.security = new SecurityDesc(file, 317 SecurityDesc.SANDBOX_PERMISSIONS, 318 codebase.getHost()); 319 } 320 } 321 } 322 323 /** 324 * Returns a JNLP classloader for the specified JNLP file. 314 URL codebase = UrlUtils.guessCodeBase(file); 315 this.security = securityDelegate.getClassLoaderSecurity(codebase.getHost()); 316 } 317 318 /** 319 * Gets the lock for a given unique key, creating one if it does not yet exist. 320 * This operation is atomic & thread-safe. 321 * 322 * @param uniqueKey the file whose unique key should be used 323 * @return the lock 324 */ 325 private static ReentrantLock getUniqueKeyLock(String uniqueKey) { 326 synchronized (uniqueKeyToLock) { 327 ReentrantLock storedLock = uniqueKeyToLock.get(uniqueKey); 328 329 if (storedLock == null) { 330 storedLock = new ReentrantLock(); 331 uniqueKeyToLock.put(uniqueKey, storedLock); 332 } 333 334 return storedLock; 335 } 336 } 337 338 /** 339 * Creates a fully initialized JNLP classloader for the specified JNLPFile, 340 * to be used as an applet/application's classloader. 341 * In contrast, JNLP classloaders can also be constructed simply to merge 342 * its resources into another classloader. 325 343 * 326 344 * @param file the file to load classes for 327 345 * @param policy the update policy to use when downloading resources 328 */ 329 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy) throws LaunchException { 330 return getInstance(file, policy, null); 346 * @param mainName Overrides the main class name of the application 347 */ 348 private static JNLPClassLoader createInstance(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException { 349 String uniqueKey = file.getUniqueKey(); 350 JNLPClassLoader baseLoader = uniqueKeyToLoader.get(uniqueKey); 351 JNLPClassLoader loader = new JNLPClassLoader(file, policy, mainName, enableCodeBase); 352 353 // If security level is 'high' or greater, we must check if the user allows unsigned applets 354 // when the JNLPClassLoader is created. We do so here, because doing so in the constructor 355 // causes unwanted side-effects for some applets. However, if the loader has been tagged 356 // with "runInSandbox", then we do not show this dialog - since this tag indicates that 357 // the user was already shown a CertWarning dialog and has chosen to run the applet sandboxed. 358 // This means they've already agreed to running the applet and have specified with which 359 // permission level to do it! 360 if (loader.getSigningState() == SigningState.PARTIAL) { 361 loader.securityDelegate.promptUserOnPartialSigning(); 362 } else if (!loader.getSigning() && !loader.securityDelegate.userPromptedForSandbox() && file instanceof PluginBridge) { 363 UnsignedAppletTrustConfirmation.checkUnsignedWithUserIfRequired((PluginBridge)file); 364 } 365 366 // New loader init may have caused extentions to create a 367 // loader for this unique key. Check. 368 JNLPClassLoader extLoader = uniqueKeyToLoader.get(uniqueKey); 369 370 if (extLoader != null && extLoader != loader) { 371 if (loader.getSigning() != extLoader.getSigning()) { 372 loader.securityDelegate.promptUserOnPartialSigning(); 373 } 374 loader.merge(extLoader); 375 extLoader.decrementLoaderUseCount(); // loader urls have been merged, ext loader is no longer used 376 } 377 378 // loader is now current + ext. But we also need to think of 379 // the baseLoader 380 if (baseLoader != null && baseLoader != loader) { 381 loader.merge(baseLoader); 382 } 383 384 return loader; 385 } 386 387 /** 388 * Returns a JNLP classloader for the specified JNLP file. 389 * 390 * @param file the file to load classes for 391 * @param policy the update policy to use when downloading resources 392 */ 393 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, boolean enableCodeBase) throws LaunchException { 394 return getInstance(file, policy, null, enableCodeBase); 331 395 } 332 396 … … 338 402 * @param mainName Overrides the main class name of the application 339 403 */ 340 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, String mainName ) throws LaunchException {404 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException { 341 405 JNLPClassLoader baseLoader = null; 342 406 JNLPClassLoader loader = null; 343 407 String uniqueKey = file.getUniqueKey(); 344 408 345 if (uniqueKey != null) 346 baseLoader = urlToLoader.get(uniqueKey); 347 348 try { 349 409 synchronized ( getUniqueKeyLock(uniqueKey) ) { 410 baseLoader = uniqueKeyToLoader.get(uniqueKey); 350 411 351 412 // A null baseloader implies that no loader has been created … … 355 416 !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) { 356 417 357 loader = new JNLPClassLoader(file, policy, mainName); 358 359 // New loader init may have caused extentions to create a 360 // loader for this unique key. Check. 361 JNLPClassLoader extLoader = urlToLoader.get(uniqueKey); 362 363 if (extLoader != null && extLoader != loader) { 364 if (loader.signing && !extLoader.signing) 365 if (!SecurityDialogs.showNotAllSignedWarningDialog(file)) 366 throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo")); 367 368 loader.merge(extLoader); 369 extLoader.decrementLoaderUseCount(); // loader urls have been merged, ext loader is no longer used 370 } 371 372 // loader is now current + ext. But we also need to think of 373 // the baseLoader 374 if (baseLoader != null && baseLoader != loader) { 375 loader.merge(baseLoader); 376 } 377 418 loader = createInstance(file, policy, mainName, enableCodeBase); 378 419 } else { 379 420 // if key is same and locations match, this is the loader we want 380 421 if (!file.isApplication()) { 381 422 // If this is an applet, we do need to consider its loader 382 loader = new JNLPClassLoader(file, policy, mainName);423 loader = new JNLPClassLoader(file, policy, mainName, enableCodeBase); 383 424 384 425 if (baseLoader != null) … … 388 429 } 389 430 390 } catch (LaunchException e) { 391 throw e; 392 } 393 394 // loaders are mapped to a unique key. Only extensions and parent 395 // share a key, so it is safe to always share based on it 396 397 loader.incrementLoaderUseCount(); 398 synchronized(urlToLoader) { 399 urlToLoader.put(uniqueKey, loader); 431 // loaders are mapped to a unique key. Only extensions and parent 432 // share a key, so it is safe to always share based on it 433 434 loader.incrementLoaderUseCount(); 435 436 uniqueKeyToLoader.put(uniqueKey, loader); 400 437 } 401 438 … … 412 449 * @param mainName Overrides the main class name of the application 413 450 */ 414 public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy, String mainName)451 public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, ParserSettings settings, UpdatePolicy policy, String mainName, boolean enableCodeBase) 415 452 throws IOException, ParseException, LaunchException { 416 JNLPClassLoader loader = urlToLoader.get(uniqueKey); 417 418 if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) { 419 JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, false, policy); 420 421 loader = getInstance(jnlpFile, policy, mainName); 453 454 JNLPClassLoader loader; 455 456 synchronized ( getUniqueKeyLock(uniqueKey) ) { 457 loader = uniqueKeyToLoader.get(uniqueKey); 458 459 if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) { 460 JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, settings, policy); 461 462 loader = getInstance(jnlpFile, policy, mainName, enableCodeBase); 463 } 422 464 } 423 465 … … 429 471 */ 430 472 void initializeExtensions() { 431 ExtensionDesc[] ext = resources.getExtensions();473 ExtensionDesc[] extDescs = resources.getExtensions(); 432 474 433 475 List<JNLPClassLoader> loaderList = new ArrayList<JNLPClassLoader>(); … … 448 490 449 491 //if (ext != null) { 450 for ( int i = 0; i < ext.length; i++) {492 for (ExtensionDesc ext : extDescs) { 451 493 try { 452 494 String uniqueKey = this.getJNLPFile().getUniqueKey(); 453 JNLPClassLoader loader = getInstance(ext [i].getLocation(), uniqueKey, ext[i].getVersion(), updatePolicy, mainClass);495 JNLPClassLoader loader = getInstance(ext.getLocation(), uniqueKey, ext.getVersion(), file.getParserSettings(), updatePolicy, mainClass, this.enableCodeBase); 454 496 loaderList.add(loader); 455 497 } catch (Exception ex) { 456 ex.printStackTrace();498 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 457 499 } 458 500 } … … 469 511 470 512 JARDesc jars[] = resources.getJARs(); 471 for (int i = 0; i < jars.length; i++) { 472 Permission p = CacheUtil.getReadPermission(jars[i].getLocation(), 473 jars[i].getVersion()); 474 475 if (JNLPRuntime.isDebug()) { 476 if (p == null) 477 System.out.println("Unable to add permission for " + jars[i].getLocation()); 478 else 479 System.out.println("Permission added: " + p.toString()); 513 for (JARDesc jar : jars) { 514 Permission p = CacheUtil.getReadPermission(jar.getLocation(), jar.getVersion()); 515 516 if (p == null) { 517 OutputController.getLogger().log("Unable to add permission for " + jar.getLocation()); 518 } else { 519 OutputController.getLogger().log("Permission added: " + p.toString()); 480 520 } 481 521 if (p != null) … … 489 529 * @return true if file exists AND is an invalid jar, false otherwise 490 530 */ 491 privateboolean isInvalidJar(JARDesc jar){531 boolean isInvalidJar(JARDesc jar){ 492 532 File cacheFile = tracker.getCacheFile(jar.getLocation()); 493 533 if (cacheFile == null) … … 529 569 addToCodeBaseLoader(new URL(file.getCodeBase(), codeBaseFolder)); 530 570 } catch (MalformedURLException mfe) { 531 System.err.println("Problem trying to add folder to code base:");532 System.err.println(mfe.getMessage());571 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, "Problem trying to add folder to code base:"); 572 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, mfe); 533 573 } 534 574 } … … 537 577 JARDesc jars[] = resources.getJARs(); 538 578 539 if (jars == null || jars.length == 0) {540 541 boolean allSigned = true;579 if (jars.length == 0) { 580 581 boolean allSigned = (loaders.length > 1) /* has extensions */; 542 582 for (int i = 1; i < loaders.length; i++) { 543 583 if (!loaders[i].getSigning()) { … … 547 587 } 548 588 549 if (allSigned)550 signing = true;589 if (allSigned) 590 signing = SigningState.FULL; 551 591 552 592 //Check if main jar is found within extensions … … 563 603 List<JARDesc> initialJars = new ArrayList<JARDesc>(); 564 604 565 for (int i = 0; i < jars.length; i++) { 566 567 available.add(jars[i]); 568 569 if (jars[i].isEager()) 570 initialJars.add(jars[i]); // regardless of part 571 572 tracker.addResource(jars[i].getLocation(), 573 jars[i].getVersion(), 574 getDownloadOptionsForJar(jars[i]), 575 jars[i].isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE 576 ); 577 } 578 605 for (JARDesc jar : jars) { 606 607 available.add(jar); 608 609 if (jar.isEager()) 610 initialJars.add(jar); // regardless of part 611 612 tracker.addResource(jar.getLocation(), 613 jar.getVersion(), file.getDownloadOptions(), 614 jar.isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE); 615 } 616 579 617 //If there are no eager jars, initialize the first jar 580 618 if(initialJars.size() == 0) … … 603 641 if (JNLPRuntime.isVerifying()) { 604 642 605 JarCertVerifier jcv;606 607 643 try { 608 jcv = verifyJars(initialJars);644 jcv.add(initialJars, tracker); 609 645 } catch (Exception e) { 610 646 //we caught an Exception from the JarCertVerifier class. 611 647 //Note: one of these exceptions could be from not being able 612 648 //to read the cacerts or trusted.certs files. 613 e.printStackTrace();649 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 614 650 throw new LaunchException(null, null, R("LSFatal"), 615 R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo") );651 R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo") + ": " +e.getMessage()); 616 652 } 617 653 618 654 //Case when at least one jar has some signing 619 if (jcv.anyJarsSigned() && jcv.isFullySignedByASingleCert()) { 620 signing = true; 621 622 if (!jcv.allJarsSigned() && 623 !SecurityDialogs.showNotAllSignedWarningDialog(file)) 624 throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo")); 625 655 if (jcv.isFullySigned()) { 656 signing = SigningState.FULL; 626 657 627 658 // Check for main class in the downloaded jars, and check/verify signed JNLP fill … … 629 660 630 661 // If jar with main class was not found, check available resources 631 while (!foundMainJar && available != null && available.size() != 0) 662 while (!foundMainJar && available != null && available.size() != 0) 632 663 addNextResource(); 633 664 … … 636 667 foundMainJar = foundMainJar || hasMainInExtensions(); 637 668 638 // If jar with main class was not found and there are no more 639 // available jars, throw a LaunchException 640 if (file.getLaunchInfo() != null) { 641 if (!foundMainJar 642 && (available == null || available.size() == 0)) 643 throw new LaunchException(file, null, R("LSFatal"), 644 R("LCClient"), R("LCantDetermineMainClass"), 645 R("LCantDetermineMainClassInfo")); 669 boolean externalAppletMainClass = (file.getLaunchInfo() != null && !foundMainJar 670 && (available == null || available.size() == 0)); 671 672 // We do this check here simply to ensure that if there are no JARs at all, 673 // and also no main-class in the codebase (ie the applet doesn't really exist), we 674 // fail ASAP rather than continuing (and showing the NotAllSigned dialog for no applet) 675 if (externalAppletMainClass) { 676 if (codeBaseLoader != null) { 677 try { 678 codeBaseLoader.findClass(mainClass); 679 } catch (ClassNotFoundException extCnfe) { 680 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, extCnfe); 681 throw new LaunchException(file, extCnfe, R("LSFatal"), R("LCInit"), R("LCantDetermineMainClass"), R("LCantDetermineMainClassInfo")); 682 } 683 } else { 684 throw new LaunchException(file, null, R("LSFatal"), R("LCInit"), R("LCantDetermineMainClass"), R("LCantDetermineMainClassInfo")); 685 } 686 } 687 688 // If externalAppletMainClass is true and a LaunchException was not thrown above, 689 // then the main-class can be loaded from the applet codebase, but is obviously not signed 690 if (!jcv.allJarsSigned()) { 691 checkPartialSigningWithUser(); 646 692 } 647 693 648 694 // If main jar was found, but a signed JNLP file was not located 649 if (!isSignedJNLP && foundMainJar) 695 if (!isSignedJNLP && foundMainJar) 650 696 file.setSignedJNLPAsMissing(); 651 697 652 698 //user does not trust this publisher 653 if (!jcv. getAlreadyTrustPublisher()) {654 checkTrustWithUser( jcv);699 if (!jcv.isTriviallySigned()) { 700 checkTrustWithUser(); 655 701 } else { 656 702 /** … … 661 707 } else { 662 708 663 signing = false; 664 //otherwise this jar is simply unsigned -- make sure to ask 665 //for permission on certain actions 666 } 667 } 668 709 // Otherwise this jar is simply unsigned -- make sure to ask 710 // for permission on certain actions 711 signing = SigningState.NONE; 712 } 713 } 714 715 boolean containsSignedJar = false, containsUnsignedJar = false; 669 716 for (JARDesc jarDesc : file.getResources().getJARs()) { 717 File cachedFile; 718 670 719 try { 671 672 File cachedFile; 673 674 try { 675 cachedFile = tracker.getCacheFile(jarDesc.getLocation()); 676 } catch (IllegalResourceDescriptorException irde){ 677 //Caused by ignored resource being removed due to not being valid 678 System.err.println("JAR " + jarDesc.getLocation() + " is not a valid jar file. Continuing."); 679 continue; 680 } 681 682 if (cachedFile == null) { 683 System.err.println("JAR " + jarDesc.getLocation() + " not found. Continuing."); 684 continue; // JAR not found. Keep going. 685 } 686 687 // TODO: Should be toURI().toURL() 688 URL location = cachedFile.toURL(); 689 SecurityDesc jarSecurity = file.getSecurity(); 690 691 if (file instanceof PluginBridge) { 692 693 URL codebase = null; 694 695 if (file.getCodeBase() != null) { 696 codebase = file.getCodeBase(); 697 } else { 698 //Fixme: codebase should be the codebase of the Main Jar not 699 //the location. Although, it still works in the current state. 700 codebase = file.getResources().getMainJAR().getLocation(); 701 } 702 703 if (signing) { 704 jarSecurity = new SecurityDesc(file, 705 SecurityDesc.ALL_PERMISSIONS, 706 codebase.getHost()); 707 } else { 708 jarSecurity = new SecurityDesc(file, 709 SecurityDesc.SANDBOX_PERMISSIONS, 710 codebase.getHost()); 711 } 712 } 713 714 jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity); 715 } catch (MalformedURLException mfe) { 716 System.err.println(mfe.getMessage()); 717 } 718 } 720 cachedFile = tracker.getCacheFile(jarDesc.getLocation()); 721 } catch (IllegalResourceDescriptorException irde) { 722 //Caused by ignored resource being removed due to not being valid 723 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "JAR " + jarDesc.getLocation() + " is not a valid jar file. Continuing."); 724 continue; 725 } 726 727 if (cachedFile == null) { 728 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "JAR " + jarDesc.getLocation() + " not found. Continuing."); 729 continue; // JAR not found. Keep going. 730 } 731 732 final URL codebase; 733 if (file.getCodeBase() != null) { 734 codebase = file.getCodeBase(); 735 } else { 736 // FIXME: codebase should be the codebase of the Main Jar not 737 // the location. Although, it still works in the current state. 738 codebase = file.getResources().getMainJAR().getLocation(); 739 } 740 741 final SecurityDesc jarSecurity = securityDelegate.getCodebaseSecurityDesc(jarDesc, codebase.getHost()); 742 if (jarSecurity.getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS)) { 743 containsUnsignedJar = true; 744 } else { 745 containsSignedJar = true; 746 } 747 748 jarLocationSecurityMap.put(jarDesc.getLocation(), jarSecurity); 749 } 750 751 if (containsSignedJar && containsUnsignedJar) { 752 checkPartialSigningWithUser(); 753 } 754 719 755 activateJars(initialJars); 720 756 } 721 757 758 /*** 759 * Checks for the jar that contains the attribute. 760 * 761 * @param jars Jars that are checked to see if they contain the main class 762 * @param name attribute to be found 763 */ 764 public String checkForAttributeInJars(List<JARDesc> jars, Attributes.Name name) { 765 766 if (jars.isEmpty()) { 767 return null; 768 } 769 770 String result = null; 771 772 // Check main jar 773 JARDesc mainJarDesc = ResourcesDesc.getMainJAR(jars); 774 result = getManifestAttribute(mainJarDesc.getLocation(), name); 775 776 if (result != null) { 777 return result; 778 } 779 780 // Check first jar 781 JARDesc firstJarDesc = jars.get(0); 782 result = getManifestAttribute(firstJarDesc.getLocation(),name); 783 784 if (result != null) { 785 return result; 786 } 787 788 // Still not found? Iterate and set if only 1 was found 789 for (JARDesc jarDesc: jars) { 790 String attributeInThisJar = getManifestAttribute(jarDesc.getLocation(), name); 791 if (attributeInThisJar != null) { 792 if (result == null) { // first main class 793 result = attributeInThisJar; 794 } else { // There is more than one main class. Set to null and break. 795 result = null; 796 break; 797 } 798 } 799 } 800 return result; 801 } 722 802 /*** 723 803 * Checks for the jar that contains the main class. If the main class was … … 728 808 * @throws LaunchException Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match 729 809 */ 730 privatevoid checkForMain(List<JARDesc> jars) throws LaunchException {810 void checkForMain(List<JARDesc> jars) throws LaunchException { 731 811 732 812 // Check launch info 733 813 if (mainClass == null) { 734 814 LaunchDesc launchDesc = file.getLaunchInfo(); 735 if (launchDesc == null) { 736 return; 737 } 738 739 mainClass = launchDesc.getMainClass(); 815 if (launchDesc != null) { 816 mainClass = launchDesc.getMainClass(); 817 } 740 818 } 741 819 742 820 // The main class may be specified in the manifest 743 821 744 // Check main jar745 822 if (mainClass == null) { 746 JARDesc mainJarDesc = file.getResources().getMainJAR(); 747 mainClass = getMainClassName(mainJarDesc.getLocation()); 748 } 749 750 // Check first jar 751 if (mainClass == null) { 752 JARDesc firstJarDesc = jars.get(0); 753 mainClass = getMainClassName(firstJarDesc.getLocation()); 754 } 755 756 // Still not found? Iterate and set if only 1 was found 757 if (mainClass == null) { 758 759 for (JARDesc jarDesc: jars) { 760 String mainClassInThisJar = getMainClassName(jarDesc.getLocation()); 761 762 if (mainClassInThisJar != null) { 763 764 if (mainClass == null) { // first main class 765 mainClass = mainClassInThisJar; 766 } else { // There is more than one main class. Set to null and break. 767 mainClass = null; 823 mainClass = checkForAttributeInJars(jars, Attributes.Name.MAIN_CLASS); 824 } 825 826 String desiredJarEntryName = mainClass + ".class"; 827 828 for (JARDesc jar : jars) { 829 830 try { 831 File localFile = tracker 832 .getCacheFile(jar.getLocation()); 833 834 if (localFile == null) { 835 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "JAR " + jar.getLocation() + " not found. Continuing."); 836 continue; // JAR not found. Keep going. 837 } 838 839 JarFile jarFile = new JarFile(localFile); 840 841 for (JarEntry entry : Collections.list(jarFile.entries())) { 842 String jeName = entry.getName().replaceAll("/", "."); 843 if (jeName.equals(desiredJarEntryName)) { 844 foundMainJar = true; 845 verifySignedJNLP(jar, jarFile); 768 846 break; 769 847 } 770 848 } 771 } 772 } 773 774 String desiredJarEntryName = mainClass + ".class"; 775 776 for (int i = 0; i < jars.size(); i++) { 777 778 try { 779 File localFile = tracker 780 .getCacheFile(jars.get(i).getLocation()); 781 782 if (localFile == null) { 783 System.err.println("JAR " + jars.get(i).getLocation() + " not found. Continuing."); 784 continue; // JAR not found. Keep going. 785 } 786 787 JarFile jarFile = new JarFile(localFile); 788 Enumeration<JarEntry> entries = jarFile.entries(); 789 JarEntry je; 790 791 while (entries.hasMoreElements()) { 792 je = entries.nextElement(); 793 String jeName = je.getName().replaceAll("/", "."); 794 if (jeName.equals(desiredJarEntryName)) { 795 foundMainJar = true; 796 verifySignedJNLP(jars.get(i), jarFile); 797 break; 798 } 799 } 849 850 jarFile.close(); 800 851 } catch (IOException e) { 801 852 /* … … 814 865 * @return the main class name, null if there isn't one of if there was an error 815 866 */ 816 private String getMainClassName(URL location) { 817 818 String mainClass = null; 867 String getMainClassName(URL location) { 868 return getManifestAttribute(location, Attributes.Name.MAIN_CLASS); 869 } 870 871 872 /** 873 * Gets the name of the main method if specified in the manifest 874 * 875 * @param location The JAR location 876 * @return the attribute value, null if there isn't one of if there was an error 877 */ 878 public String getManifestAttribute(URL location, Attributes.Name attribute) { 879 880 String attributeValue = null; 819 881 File f = tracker.getCacheFile(location); 820 882 821 883 if( f != null) { 884 JarFile mainJar = null; 822 885 try { 823 JarFile mainJar = new JarFile(f); 824 mainClass = mainJar.getManifest(). 825 getMainAttributes().getValue("Main-Class"); 886 mainJar = new JarFile(f); 887 Manifest manifest = mainJar.getManifest(); 888 if (manifest == null || manifest.getMainAttributes() == null){ 889 //yes, jars without manifest exists 890 return null; 891 } 892 attributeValue = manifest.getMainAttributes().getValue(attribute); 826 893 } catch (IOException ioe) { 827 mainClass = null; 828 } 829 } 830 831 return mainClass; 894 attributeValue = null; 895 } finally { 896 StreamUtils.closeSilently(mainJar); 897 } 898 } 899 900 return attributeValue; 832 901 } 833 902 … … 863 932 throws LaunchException { 864 933 865 JarCertVerifier signer = new JarCertVerifier();866 934 List<JARDesc> desc = new ArrayList<JARDesc>(); 867 935 desc.add(jarDesc); … … 874 942 875 943 try { 876 signer.verifyJars(desc, tracker); 877 878 if (signer.allJarsSigned()) { // If the jar is signed 879 880 Enumeration<JarEntry> entries = jarFile.entries(); 881 JarEntry je; 882 883 while (entries.hasMoreElements()) { 884 je = entries.nextElement(); 944 // NOTE: verification should have happened by now. In other words, 945 // calling jcv.verifyJars(desc, tracker) here should have no affect. 946 if (jcv.isFullySigned()) { 947 948 for (JarEntry je : Collections.list(jarFile.entries())) { 885 949 String jeName = je.getName().toUpperCase(); 886 950 887 951 if (jeName.equals(TEMPLATE) || jeName.equals(APPLICATION)) { 888 952 889 if (JNLPRuntime.isDebug()) 890 System.err.println("Creating Jar InputStream from JarEntry"); 953 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Creating Jar InputStream from JarEntry"); 891 954 892 955 inStream = jarFile.getInputStream(je); 893 956 inputReader = new InputStreamReader(inStream); 894 957 895 if (JNLPRuntime.isDebug()) 896 System.err.println("Creating File InputStream from lauching JNLP file"); 958 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Creating File InputStream from lauching JNLP file"); 897 959 898 960 JNLPFile jnlp = this.getJNLPFile(); … … 913 975 914 976 if (jeName.equals(APPLICATION)) { // If signed application was found 915 if (JNLPRuntime.isDebug()) 916 System.err.println("APPLICATION.JNLP has been located within signed JAR. Starting verfication..."); 977 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "APPLICATION.JNLP has been located within signed JAR. Starting verfication..."); 917 978 918 979 matcher = new JNLPMatcher(inputReader, jnlpReader, false); 919 980 } else { // Otherwise template was found 920 if (JNLPRuntime.isDebug()) 921 System.err.println("APPLICATION_TEMPLATE.JNLP has been located within signed JAR. Starting verfication..."); 981 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "APPLICATION_TEMPLATE.JNLP has been located within signed JAR. Starting verfication..."); 922 982 923 983 matcher = new JNLPMatcher(inputReader, jnlpReader, … … 930 990 931 991 this.isSignedJNLP = true; 932 if (JNLPRuntime.isDebug()) 933 System.err.println("Signed Application Verification Successful"); 992 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Signed Application Verification Successful"); 934 993 935 994 break; … … 954 1013 } catch (Exception e) { 955 1014 956 if (JNLPRuntime.isDebug()) 957 e.printStackTrace(System.err); 1015 OutputController.getLogger().log(e); 958 1016 959 1017 /* 960 1018 * After this exception is caught, it is escaped. If an exception is 961 1019 * thrown while handling the jar file, (mainly for 962 * JarCertVerifier. verifyJars) it assumes the jar file is unsigned and1020 * JarCertVerifier.add) it assumes the jar file is unsigned and 963 1021 * skip the check for a signed JNLP file 964 1022 */ … … 967 1025 968 1026 //Close all streams 969 closeStream(inStream); 970 closeStream(inputReader); 971 closeStream(fr); 972 closeStream(jnlpReader); 973 } 974 975 if (JNLPRuntime.isDebug()) 976 System.err.println("Ending check for signed JNLP file..."); 977 } 978 979 /*** 980 * Closes a stream 981 * 982 * @param stream the stream that will be closed 983 */ 984 private void closeStream (Closeable stream) { 985 if (stream != null) 986 try { 987 stream.close(); 988 } catch (Exception e) { 989 e.printStackTrace(System.err); 990 } 991 } 992 993 private void checkTrustWithUser(JarCertVerifier jcv) throws LaunchException { 994 if (JNLPRuntime.isTrustAll()){ 1027 StreamUtils.closeSilently(inStream); 1028 StreamUtils.closeSilently(inputReader); 1029 StreamUtils.closeSilently(fr); 1030 StreamUtils.closeSilently(jnlpReader); 1031 } 1032 1033 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Ending check for signed JNLP file..."); 1034 } 1035 1036 /** 1037 * Prompt the user for trust on all the signers that require approval. 1038 * @throws LaunchException if the user does not approve every dialog prompt. 1039 */ 1040 private void checkTrustWithUser() throws LaunchException { 1041 if (JNLPRuntime.isTrustNone()) { 1042 if (!securityDelegate.getRunInSandbox()) { 1043 setRunInSandbox(); 1044 } 995 1045 return; 996 1046 } 997 if (!jcv.getRootInCacerts()) { //root cert is not in cacerts 998 boolean b = SecurityDialogs.showCertWarningDialog( 999 AccessType.UNVERIFIED, file, jcv); 1000 if (!b) 1001 throw new LaunchException(null, null, R("LSFatal"), 1002 R("LCLaunching"), R("LNotVerified"), ""); 1003 } else if (jcv.getRootInCacerts()) { //root cert is in cacerts 1004 boolean b = false; 1005 if (jcv.noSigningIssues()) 1006 b = SecurityDialogs.showCertWarningDialog( 1007 AccessType.VERIFIED, file, jcv); 1008 else if (!jcv.noSigningIssues()) 1009 b = SecurityDialogs.showCertWarningDialog( 1010 AccessType.SIGNING_ERROR, file, jcv); 1011 if (!b) 1012 throw new LaunchException(null, null, R("LSFatal"), 1013 R("LCLaunching"), R("LCancelOnUserRequest"), ""); 1014 } 1047 if (JNLPRuntime.isTrustAll() || securityDelegate.getRunInSandbox()) { 1048 return; 1049 } 1050 1051 if (getSigningState() == SigningState.FULL && jcv.isFullySigned() && !jcv.getAlreadyTrustPublisher()) { 1052 jcv.checkTrustWithUser(securityDelegate, file); 1053 } 1054 } 1055 1056 /* 1057 * Sets whether applets are to be run sandboxed, regardless of JAR 1058 * signing. This MUST be called before any call to initializeResources, 1059 * setSecurity, activateJars, or any other method that sets the value 1060 * of this.security or adds entries into this.jarLocationSecurityMap. 1061 * @throws LaunchException if security settings have been initialized before 1062 * this method is called 1063 */ 1064 public void setRunInSandbox() throws LaunchException { 1065 securityDelegate.setRunInSandbox(); 1066 } 1067 1068 public boolean userPromptedForSandbox() { 1069 return securityDelegate.getRunInSandbox(); 1015 1070 } 1016 1071 … … 1030 1085 public void setApplication(ApplicationInstance app) { 1031 1086 if (this.app != null) { 1032 if (JNLPRuntime.isDebug()) { 1033 Exception ex = new IllegalStateException("Application can only be set once"); 1034 ex.printStackTrace(); 1035 } 1087 OutputController.getLogger().log(new IllegalStateException("Application can only be set once")); 1036 1088 return; 1037 1089 } … … 1087 1139 } 1088 1140 if (getCodeSourceSecurity(cs.getLocation()).getSecurityType() == null) { 1089 if (JNLPRuntime.isDebug()){ 1090 new NullPointerException("Warning! Code source security type was null").printStackTrace(); 1091 } 1141 OutputController.getLogger().log(new NullPointerException("Warning! Code source security type was null")); 1092 1142 } 1093 1143 Object securityType = getCodeSourceSecurity(cs.getLocation()).getSecurityType(); … … 1099 1149 } 1100 1150 1101 Enumeration<Permission> e = permissions.elements(); 1102 while (e.hasMoreElements()) { 1103 result.add(e.nextElement()); 1151 for (Permission perm : Collections.list(permissions.elements())) { 1152 result.add(perm); 1104 1153 } 1105 1154 } 1106 1155 1107 1156 // add in permission to read the cached JAR files 1108 for ( int i = 0; i < resourcePermissions.size(); i++) {1109 result.add( resourcePermissions.get(i));1157 for (Permission perm : resourcePermissions) { 1158 result.add(perm); 1110 1159 } 1111 1160 1112 1161 // add in the permissions that the user granted. 1113 for ( int i = 0; i < runtimePermissions.size(); i++) {1114 result.add( runtimePermissions.get(i));1162 for (Permission perm : runtimePermissions) { 1163 result.add(perm); 1115 1164 } 1116 1165 1117 1166 // Class from host X should be allowed to connect to host X 1118 if (cs.getLocation() .getHost().length() > 0)1167 if (cs.getLocation() != null && cs.getLocation().getHost().length() > 0) 1119 1168 result.add(new SocketPermission(cs.getLocation().getHost(), 1120 1169 "connect, accept")); … … 1122 1171 return result; 1123 1172 } catch (RuntimeException ex) { 1124 if (JNLPRuntime.isDebug()) { 1125 ex.printStackTrace(); 1126 } 1173 OutputController.getLogger().log(ex); 1127 1174 throw ex; 1128 1175 } … … 1139 1186 */ 1140 1187 protected void fillInPartJars(List<JARDesc> jars) { 1141 for (int i = 0; i < jars.size(); i++) { 1142 String part = jars.get(i).getPart(); 1143 1144 for (int a = 0; a < available.size(); a++) { 1145 JARDesc jar = available.get(a); 1146 1147 if (part != null && part.equals(jar.getPart())) 1148 if (!jars.contains(jar)) 1149 jars.add(jar); 1188 for (JARDesc desc : jars) { 1189 String part = desc.getPart(); 1190 1191 // "available" field can be affected by two different threads 1192 // working in loadClass(String) 1193 synchronized (available) { 1194 for (JARDesc jar : available) { 1195 if (part != null && part.equals(jar.getPart())) 1196 if (!jars.contains(jar)) 1197 jars.add(jar); 1198 } 1150 1199 } 1151 1200 } … … 1168 1217 waitForJars(jars); 1169 1218 1170 for (int i = 0; i < jars.size(); i++) { 1171 JARDesc jar = jars.get(i); 1172 1219 for (JARDesc jar : jars) { 1173 1220 available.remove(jar); 1174 1221 … … 1190 1237 1191 1238 JarFile jarFile = new JarFile(localFile); 1192 Enumeration<JarEntry> e = jarFile.entries(); 1193 while (e.hasMoreElements()) { 1194 JarEntry je = e.nextElement(); 1239 for (JarEntry je : Collections.list(jarFile.entries())) { 1195 1240 1196 1241 // another jar in my jar? it is more likely than you think … … 1225 1270 } 1226 1271 1227 JarCertVerifier signer = new JarCertVerifier();1228 List<JARDesc> jars = new ArrayList<JARDesc>();1229 JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false);1230 jars.add(jarDesc);1231 1272 tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null); 1232 signer.verifyJars(jars, tracker); 1233 1234 if (signer.anyJarsSigned() && !signer.getAlreadyTrustPublisher()) { 1235 checkTrustWithUser(signer); 1273 1274 URL codebase = file.getCodeBase(); 1275 if (codebase == null) { 1276 //FIXME: codebase should be the codebase of the Main Jar not 1277 //the location. Although, it still works in the current state. 1278 codebase = file.getResources().getMainJAR().getLocation(); 1236 1279 } 1280 1281 final SecurityDesc jarSecurity = securityDelegate.getJarPermissions(codebase.getHost()); 1237 1282 1238 1283 try { … … 1243 1288 addURL(fakeRemote); 1244 1289 1245 SecurityDesc jarSecurity = file.getSecurity();1246 1247 if (file instanceof PluginBridge) {1248 1249 URL codebase = null;1250 1251 if (file.getCodeBase() != null) {1252 codebase = file.getCodeBase();1253 } else {1254 //Fixme: codebase should be the codebase of the Main Jar not1255 //the location. Although, it still works in the current state.1256 codebase = file.getResources().getMainJAR().getLocation();1257 }1258 1259 jarSecurity = new SecurityDesc(file,1260 SecurityDesc.ALL_PERMISSIONS,1261 codebase.getHost());1262 }1263 1264 1290 jarLocationSecurityMap.put(fakeRemote, jarSecurity); 1265 1291 1266 1292 } catch (MalformedURLException mfue) { 1267 if (JNLPRuntime.isDebug()) 1268 System.err.println("Unable to add extracted nested jar to classpath"); 1269 1270 mfue.printStackTrace(); 1293 OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Unable to add extracted nested jar to classpath"); 1294 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, mfue); 1271 1295 } 1272 1296 } … … 1275 1299 } 1276 1300 1301 jarFile.close(); 1277 1302 } 1278 1303 … … 1298 1323 if (index != null) 1299 1324 jarIndexes.add(index); 1325 1326 jarFile.close(); 1300 1327 } else { 1301 1328 CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), jar.getLocation()); 1302 1329 } 1303 1330 1304 if (JNLPRuntime.isDebug()) 1305 System.err.println("Activate jar: " + location); 1331 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Activate jar: " + location); 1306 1332 } 1307 1333 catch (Exception ex) { 1308 if (JNLPRuntime.isDebug()) 1309 ex.printStackTrace(); 1334 OutputController.getLogger().log(ex); 1310 1335 } 1311 1336 1312 1337 // some programs place a native library in any jar 1313 activateNative(jar);1338 nativeLibraryStorage.addSearchJar(jar.getLocation()); 1314 1339 } 1315 1340 … … 1319 1344 1320 1345 AccessController.doPrivileged(activate, acc); 1321 }1322 1323 /**1324 * Search for and enable any native code contained in a JAR by copying the1325 * native files into the filesystem. Called in the security context of the1326 * classloader.1327 */1328 protected void activateNative(JARDesc jar) {1329 if (JNLPRuntime.isDebug())1330 System.out.println("Activate native: " + jar.getLocation());1331 1332 File localFile = tracker.getCacheFile(jar.getLocation());1333 if (localFile == null)1334 return;1335 1336 String[] librarySuffixes = { ".so", ".dylib", ".jnilib", ".framework", ".dll" };1337 1338 try {1339 JarFile jarFile = new JarFile(localFile, false);1340 Enumeration<JarEntry> entries = jarFile.entries();1341 1342 while (entries.hasMoreElements()) {1343 JarEntry e = entries.nextElement();1344 1345 if (e.isDirectory()) {1346 continue;1347 }1348 1349 String name = new File(e.getName()).getName();1350 boolean isLibrary = false;1351 1352 for (String suffix : librarySuffixes) {1353 if (name.endsWith(suffix)) {1354 isLibrary = true;1355 break;1356 }1357 }1358 if (!isLibrary) {1359 continue;1360 }1361 1362 if (nativeDir == null)1363 nativeDir = getNativeDir();1364 1365 File outFile = new File(nativeDir, name);1366 if (!outFile.isFile()) {1367 FileUtils.createRestrictedFile(outFile, true);1368 }1369 CacheUtil.streamCopy(jarFile.getInputStream(e),1370 new FileOutputStream(outFile));1371 1372 }1373 } catch (IOException ex) {1374 if (JNLPRuntime.isDebug())1375 ex.printStackTrace();1376 }1377 }1378 1379 /**1380 * Return the base directory to store native code files in.1381 * This method does not need to return the same directory across1382 * calls.1383 */1384 protected File getNativeDir() {1385 final int rand = (int)((Math.random()*2 - 1) * Integer.MAX_VALUE);1386 nativeDir = new File(System.getProperty("java.io.tmpdir")1387 + File.separator + "netx-native-"1388 + (rand & 0xFFFF));1389 File parent = nativeDir.getParentFile();1390 if (!parent.isDirectory() && !parent.mkdirs()) {1391 return null;1392 }1393 1394 try {1395 FileUtils.createRestrictedDirectory(nativeDir);1396 // add this new native directory to the search path1397 addNativeDirectory(nativeDir);1398 return nativeDir;1399 } catch (IOException e) {1400 return null;1401 }1402 }1403 1404 /**1405 * Adds the {@link File} to the search path of this {@link JNLPClassLoader}1406 * when trying to find a native library1407 */1408 protected void addNativeDirectory(File nativeDirectory) {1409 nativeDirectories.add(nativeDirectory);1410 }1411 1412 /**1413 * Returns a list of all directories in the search path of the current classloader1414 * when it tires to find a native library.1415 * @return a list of directories in the search path for native libraries1416 */1417 protected List<File> getNativeDirectories() {1418 return nativeDirectories;1419 1346 } 1420 1347 … … 1424 1351 protected String findLibrary(String lib) { 1425 1352 String syslib = System.mapLibraryName(lib); 1426 1427 for (File dir : getNativeDirectories()) { 1428 File target = new File(dir, syslib); 1429 if (target.exists()) 1430 return target.toString(); 1353 File libFile = nativeLibraryStorage.findLibrary(syslib); 1354 1355 if (libFile != null) { 1356 return libFile.toString(); 1431 1357 } 1432 1358 … … 1442 1368 */ 1443 1369 protected String findLibraryExt(String lib) { 1444 for ( int i = 0; i < loaders.length; i++) {1370 for (JNLPClassLoader loader : loaders) { 1445 1371 String result = null; 1446 1372 1447 if (loader s[i]!= this)1448 result = loader s[i].findLibrary(lib);1373 if (loader != this) 1374 result = loader.findLibrary(lib); 1449 1375 1450 1376 if (result != null) … … 1461 1387 * @param jars the jars 1462 1388 */ 1463 private void waitForJars(List jars) {1389 private void waitForJars(List<JARDesc> jars) { 1464 1390 URL urls[] = new URL[jars.size()]; 1465 1391 1466 1392 for (int i = 0; i < jars.size(); i++) { 1467 JARDesc jar = (JARDesc)jars.get(i);1393 JARDesc jar = jars.get(i); 1468 1394 1469 1395 urls[i] = jar.getLocation(); … … 1474 1400 1475 1401 /** 1476 * Verifies code signing of jars to be used.1477 *1478 * @param jars the jars to be verified.1479 */1480 private JarCertVerifier verifyJars(List<JARDesc> jars) throws Exception {1481 1482 jcv = new JarCertVerifier();1483 jcv.verifyJars(jars, tracker);1484 return jcv;1485 }1486 1487 /**1488 1402 * Find the loaded class in this loader or any of its extension loaders. 1489 1403 */ 1490 protected Class findLoadedClassAll(String name) { 1491 for (int i = 0; i < loaders.length; i++) { 1492 Class result = null; 1493 1494 if (loaders[i] == this) { 1495 final String fName = name; 1496 try { 1497 result = AccessController.doPrivileged( 1498 new PrivilegedExceptionAction<Class<?>>() { 1499 public Class<?> run() { 1500 return JNLPClassLoader.super.findLoadedClass(fName); 1501 } 1502 }, getAccessControlContextForClassLoading()); 1503 } catch (PrivilegedActionException pae) { 1504 result = null; 1505 } 1404 protected Class<?> findLoadedClassAll(String name) { 1405 for (JNLPClassLoader loader : loaders) { 1406 Class<?> result = null; 1407 1408 if (loader == this) { 1409 result = JNLPClassLoader.super.findLoadedClass(name); 1506 1410 } else { 1507 result = loader s[i].findLoadedClassAll(name);1411 result = loader.findLoadedClassAll(name); 1508 1412 } 1509 1413 … … 1524 1428 * classloader, or one of the classloaders for the JNLP file's 1525 1429 * extensions. 1526 */ 1527 public synchronized Class<?> loadClass(String name) throws ClassNotFoundException { 1528 1430 * This method used to be qualified "synchronized." This was done solely for the 1431 * purpose of ensuring only one thread entered the method at a time. This was not 1432 * strictly necessary - ensuring that all affected fields are thread-safe is 1433 * sufficient. Locking on the JNLPClassLoader instance when this method is called 1434 * can result in deadlock if another thread is dealing with the CodebaseClassLoader 1435 * at the same time. This solution is very heavy-handed as the instance lock is not 1436 * truly required, and taking the lock on the classloader instance when not needed is 1437 * not in general a good idea because it can and will lead to deadlock when multithreaded 1438 * classloading is in effect. The solution is to keep the fields thread safe on their own. 1439 * This is accomplished by wrapping them in Collections.synchronized* to provide 1440 * atomic add/remove operations, and synchronizing on them when iterating or performing 1441 * multiple mutations. 1442 * See bug report RH976833. On some systems this bug will manifest itself as deadlock on 1443 * every webpage with more than one Java applet, potentially also causing the browser 1444 * process to hang. 1445 * More information in the mailing list archives: 1446 * http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2013-September/024536.html 1447 * 1448 * Affected fields: available, classpaths, jarIndexes, jarEntries, jarLocationSecurityMap 1449 */ 1450 public Class<?> loadClass(String name) throws ClassNotFoundException { 1529 1451 Class<?> result = findLoadedClassAll(name); 1530 1452 … … 1553 1475 // Look in 'Class-Path' as specified in the manifest file 1554 1476 try { 1555 for (String classpath: classpaths) { 1556 JARDesc desc; 1557 try { 1558 URL jarUrl = new URL(file.getCodeBase(), classpath); 1559 desc = new JARDesc(jarUrl, null, null, false, true, false, true); 1560 } catch (MalformedURLException mfe) { 1561 throw new ClassNotFoundException(name, mfe); 1477 // This field synchronized before iterating over it since it may 1478 // be shared data between threads 1479 synchronized (classpaths) { 1480 for (String classpath : classpaths) { 1481 JARDesc desc; 1482 try { 1483 URL jarUrl = new URL(file.getCodeBase(), classpath); 1484 desc = new JARDesc(jarUrl, null, null, false, true, false, true); 1485 } catch (MalformedURLException mfe) { 1486 throw new ClassNotFoundException(name, mfe); 1487 } 1488 addNewJar(desc); 1562 1489 } 1563 addNewJar(desc);1564 1490 } 1565 1491 … … 1567 1493 return result; 1568 1494 } catch (ClassNotFoundException cnfe1) { 1569 if (JNLPRuntime.isDebug()) { 1570 cnfe1.printStackTrace(); 1571 } 1495 OutputController.getLogger().log(cnfe1); 1572 1496 } 1573 1497 … … 1576 1500 // Currently this loads jars directly from the site. We cannot cache it because this 1577 1501 // call is initiated from within the applet, which does not have disk read/write permissions 1578 for (JarIndex index : jarIndexes) { 1579 // Non-generic code in sun.misc.JarIndex 1580 @SuppressWarnings("unchecked") 1581 LinkedList<String> jarList = index.get(name.replace('.', '/')); 1582 1583 if (jarList != null) { 1584 for (String jarName : jarList) { 1585 JARDesc desc; 1586 try { 1587 desc = new JARDesc(new URL(file.getCodeBase(), jarName), 1588 null, null, false, true, false, true); 1589 } catch (MalformedURLException mfe) { 1590 throw new ClassNotFoundException(name); 1591 } 1592 try { 1593 addNewJar(desc); 1594 } catch (Exception e) { 1595 if (JNLPRuntime.isDebug()) { 1596 e.printStackTrace(); 1502 // This field synchronized before iterating over it since it may 1503 // be shared data between threads 1504 synchronized (jarIndexes) { 1505 for (JarIndex index : jarIndexes) { 1506 // Non-generic code in sun.misc.JarIndex 1507 @SuppressWarnings("unchecked") 1508 LinkedList<String> jarList = index.get(name.replace('.', '/')); 1509 1510 if (jarList != null) { 1511 for (String jarName : jarList) { 1512 JARDesc desc; 1513 try { 1514 desc = new JARDesc(new URL(file.getCodeBase(), jarName), 1515 null, null, false, true, false, true); 1516 } catch (MalformedURLException mfe) { 1517 throw new ClassNotFoundException(name); 1518 } 1519 try { 1520 addNewJar(desc); 1521 } catch (Exception e) { 1522 OutputController.getLogger().log(e); 1597 1523 } 1598 1524 } 1525 1526 // If it still fails, let it error out 1527 result = loadClassExt(name); 1599 1528 } 1600 1601 // If it still fails, let it error out1602 result = loadClassExt(name);1603 1529 } 1604 1530 } … … 1618 1544 * This will add the JARDesc into the resourceTracker and block until it 1619 1545 * is downloaded. 1546 * </p> 1620 1547 * @param desc the JARDesc for the new jar 1621 1548 */ 1622 1549 private void addNewJar(final JARDesc desc) { 1550 this.addNewJar(desc, JNLPRuntime.getDefaultUpdatePolicy()); 1551 } 1552 1553 /** 1554 * Adds a new JARDesc into this classloader. 1555 * @param desc the JARDesc for the new jar 1556 * @param updatePolicy the UpdatePolicy for the resource 1557 */ 1558 private void addNewJar(final JARDesc desc, UpdatePolicy updatePolicy) { 1623 1559 1624 1560 available.add(desc); … … 1627 1563 desc.getVersion(), 1628 1564 null, 1629 JNLPRuntime.getDefaultUpdatePolicy()1565 updatePolicy 1630 1566 ); 1631 1567 … … 1651 1587 // Verify if needed 1652 1588 1653 final JarCertVerifier signer = new JarCertVerifier();1654 1589 final List<JARDesc> jars = new ArrayList<JARDesc>(); 1655 1590 jars.add(desc); … … 1663 1598 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { 1664 1599 public Void run() throws Exception { 1665 signer.verifyJars(jars, tracker); 1666 1667 if (signer.anyJarsSigned() && !signer.getAlreadyTrustPublisher()) { 1668 checkTrustWithUser(signer); 1669 } 1670 1671 final SecurityDesc security; 1672 if (signer.anyJarsSigned()) { 1673 security = new SecurityDesc(file, 1674 SecurityDesc.ALL_PERMISSIONS, 1675 file.getCodeBase().getHost()); 1676 } else { 1677 security = new SecurityDesc(file, 1678 SecurityDesc.SANDBOX_PERMISSIONS, 1679 file.getCodeBase().getHost()); 1680 } 1600 jcv.add(jars, tracker); 1601 1602 checkTrustWithUser(); 1603 1604 final SecurityDesc security = securityDelegate.getJarPermissions(file.getCodeBase().getHost()); 1681 1605 1682 1606 jarLocationSecurityMap.put(remoteURL, security); … … 1694 1618 // Exception => jar will not get added to classpath, which will 1695 1619 // result in CNFE from loadClass. 1696 e.printStackTrace();1620 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 1697 1621 } 1698 1622 } … … 1701 1625 * Find the class in this loader or any of its extension loaders. 1702 1626 */ 1703 protected Class findClass(String name) throws ClassNotFoundException { 1704 for (int i = 0; i < loaders.length; i++) { 1627 @Override 1628 protected Class<?> findClass(String name) throws ClassNotFoundException { 1629 for (JNLPClassLoader loader : loaders) { 1705 1630 try { 1706 if (loader s[i]== this) {1631 if (loader == this) { 1707 1632 final String fName = name; 1708 1633 return AccessController.doPrivileged( … … 1713 1638 }, getAccessControlContextForClassLoading()); 1714 1639 } else { 1715 return loader s[i].findClass(name);1640 return loader.findClass(name); 1716 1641 } 1717 1642 } catch (ClassNotFoundException ex) { 1718 1643 } catch (ClassFormatError cfe) { 1644 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, cfe); 1719 1645 } catch (PrivilegedActionException pae) { 1646 } catch (NullJnlpFileException ex) { 1647 throw new ClassNotFoundException(this.mainClass + " in main classloader ", ex); 1720 1648 } 1721 1649 } … … 1723 1651 // Try codebase loader 1724 1652 if (codeBaseLoader != null) 1725 return codeBaseLoader.findClass (name, true);1653 return codeBaseLoader.findClassNonRecursive(name); 1726 1654 1727 1655 // All else failed. Throw CNFE … … 1734 1662 * is found. 1735 1663 */ 1736 private Class loadClassExt(String name) throws ClassNotFoundException {1664 private Class<?> loadClassExt(String name) throws ClassNotFoundException { 1737 1665 // make recursive 1738 1666 addAvailable(); … … 1775 1703 * class loaders. 1776 1704 * 1777 * @return a <code>URL</code> for the resource, or <code>null</code>1705 * @return a {@link URL} for the resource, or {@code null} 1778 1706 * if the resource could not be found. 1779 1707 */ … … 1788 1716 } 1789 1717 } catch (IOException e) { 1790 if (JNLPRuntime.isDebug()) { 1791 e.printStackTrace(); 1792 } 1718 OutputController.getLogger().log(e); 1793 1719 } 1794 1720 … … 1814 1740 } 1815 1741 } catch (LaunchException le) { 1816 le.printStackTrace();1742 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, le); 1817 1743 } 1818 1744 … … 1828 1754 Enumeration<URL> e = null; 1829 1755 1830 for ( int i = 0; i < loaders.length; i++) {1756 for (JNLPClassLoader loader : loaders) { 1831 1757 // TODO check if this will blow up or not 1832 1758 // if loaders[1].getResource() is called, wont it call getResource() on 1833 1759 // the original caller? infinite recursion? 1834 1760 1835 if (loader s[i]== this) {1761 if (loader == this) { 1836 1762 final String fName = name; 1837 1763 try { … … 1845 1771 } 1846 1772 } else { 1847 e = loader s[i].findResources(name);1773 e = loader.findResources(name); 1848 1774 } 1849 1775 … … 1956 1882 1957 1883 public boolean getSigning() { 1884 return signing == SigningState.FULL; 1885 } 1886 1887 /** 1888 * Call this when it's suspected that an applet's permission level may have 1889 * just changed from Full Signing to Partial Signing. 1890 * This will display a one-time prompt asking the user to confirm running 1891 * the partially signed applet. 1892 * Partially Signed applets always start off as appearing to be Fully 1893 * Signed, and then during the initialization or loading process, we find 1894 * that we actually need to demote the applet to Partial, either due to 1895 * finding that not all of its JARs are actually signed, or because it 1896 * needs to load something unsigned out of the codebase. 1897 */ 1898 private void checkPartialSigningWithUser() { 1899 if (signing == SigningState.FULL && JNLPRuntime.isVerifying()) { 1900 signing = SigningState.PARTIAL; 1901 try { 1902 securityDelegate.promptUserOnPartialSigning(); 1903 } catch (LaunchException e) { 1904 throw new RuntimeException("The signed applet required loading of unsigned code from the codebase, " 1905 + "which the user refused", e); 1906 } 1907 } 1908 } 1909 1910 public SigningState getSigningState() { 1958 1911 return signing; 1959 1912 } … … 1972 1925 protected SecurityDesc getCodeSourceSecurity(URL source) { 1973 1926 SecurityDesc sec=jarLocationSecurityMap.get(source); 1974 if (sec == null && !alreadyTried.contains(source)) { 1975 alreadyTried.add(source); 1976 //try to load the jar which is requesting the permissions, but was NOT downloaded by standard way 1977 if (JNLPRuntime.isDebug()) { 1978 System.out.println("Application is trying to get permissions for " + source.toString() + ", which was not added by standard way. Trying to download and verify!"); 1979 } 1980 try { 1981 JARDesc des = new JARDesc(source, null, null, false, false, false, false); 1982 addNewJar(des); 1983 sec = jarLocationSecurityMap.get(source); 1984 } catch (Throwable t) { 1985 if (JNLPRuntime.isDebug()) { 1986 t.printStackTrace(); 1987 } 1988 sec = null; 1927 synchronized (alreadyTried) { 1928 if (sec == null && !alreadyTried.contains(source)) { 1929 alreadyTried.add(source); 1930 //try to load the jar which is requesting the permissions, but was NOT downloaded by standard way 1931 OutputController.getLogger().log("Application is trying to get permissions for " + source.toString() + ", which was not added by standard way. Trying to download and verify!"); 1932 try { 1933 JARDesc des = new JARDesc(source, null, null, false, false, false, false); 1934 addNewJar(des); 1935 sec = jarLocationSecurityMap.get(source); 1936 } catch (Throwable t) { 1937 OutputController.getLogger().log(t); 1938 sec = null; 1939 } 1989 1940 } 1990 1941 } 1991 1942 if (sec == null){ 1992 System.out.println(Translator.R("LNoSecInstance",source.toString()));1943 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("LNoSecInstance",source.toString())); 1993 1944 } 1994 1945 return sec; … … 2017 1968 2018 1969 // native search paths 2019 for (File nativeDirectory : extLoader.getNativeDirectories()) 2020 addNativeDirectory(nativeDirectory); 1970 for (File nativeDirectory : extLoader.nativeLibraryStorage.getSearchDirectories()) { 1971 nativeLibraryStorage.addSearchDirectory(nativeDirectory); 1972 } 2021 1973 2022 1974 // security descriptors 2023 for (URL key : extLoader.jarLocationSecurityMap.keySet()) { 2024 jarLocationSecurityMap.put(key, extLoader.jarLocationSecurityMap.get(key)); 1975 synchronized (jarLocationSecurityMap) { 1976 for (URL key : extLoader.jarLocationSecurityMap.keySet()) { 1977 jarLocationSecurityMap.put(key, extLoader.jarLocationSecurityMap.get(key)); 1978 } 2025 1979 } 2026 1980 } … … 2029 1983 * Adds the given path to the path loader 2030 1984 * 2031 * @param URLthe path to add1985 * @param u the path to add 2032 1986 * @throws IllegalArgumentException If the given url is not a path 2033 1987 */ … … 2049 2003 codeBaseLoader.addURL(u); 2050 2004 } 2051 }2052 2053 private DownloadOptions getDownloadOptionsForJar(JARDesc jar) {2054 return file.getDownloadOptionsForJar(jar);2055 2005 } 2056 2006 … … 2098 2048 * @throws SecurityException if caller is not trusted 2099 2049 */ 2100 private synchronizedvoid incrementLoaderUseCount() {2101 2050 private void incrementLoaderUseCount() { 2051 2102 2052 // For use by trusted code only 2103 2053 if (System.getSecurityManager() != null) 2104 2054 System.getSecurityManager().checkPermission(new AllPermission()); 2105 2106 useCount++; 2055 2056 // NB: There will only ever be one class-loader per unique-key 2057 synchronized ( getUniqueKeyLock(file.getUniqueKey()) ){ 2058 useCount++; 2059 } 2060 } 2061 2062 /** 2063 * Returns all loaders that this loader uses, including itself 2064 */ 2065 JNLPClassLoader[] getLoaders() { 2066 return loaders; 2067 } 2068 2069 /** 2070 * Remove jars from the file system. 2071 * 2072 * @param jars Jars marked for removal. 2073 */ 2074 void removeJars(JARDesc[] jars) { 2075 2076 for (JARDesc eachJar : jars) { 2077 try { 2078 tracker.removeResource(eachJar.getLocation()); 2079 } catch (Exception e) { 2080 OutputController.getLogger().log(e); 2081 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Failed to remove resource from tracker, continuing.."); 2082 } 2083 2084 File cachedFile = CacheUtil.getCacheFile(eachJar.getLocation(), null); 2085 String directoryUrl = CacheUtil.getCacheParentDirectory(cachedFile.getAbsolutePath()); 2086 2087 File directory = new File(directoryUrl); 2088 2089 OutputController.getLogger().log("Deleting cached file: " + cachedFile.getAbsolutePath()); 2090 2091 cachedFile.delete(); 2092 2093 OutputController.getLogger().log("Deleting cached directory: " + directory.getAbsolutePath()); 2094 2095 directory.delete(); 2096 } 2097 } 2098 2099 /** 2100 * Downloads and initializes jars into this loader. 2101 * 2102 * @param ref Path of the launch or extension JNLP File containing the 2103 * resource. If null, main JNLP's file location will be used instead. 2104 * @param part The name of the path. 2105 * @throws LaunchException 2106 */ 2107 void initializeNewJarDownload(URL ref, String part, Version version) { 2108 JARDesc[] jars = ManageJnlpResources.findJars(this, ref, part, version); 2109 2110 for (JARDesc eachJar : jars) { 2111 OutputController.getLogger().log("Downloading and initializing jar: " + eachJar.getLocation().toString()); 2112 2113 this.addNewJar(eachJar, UpdatePolicy.FORCE); 2114 } 2115 } 2116 2117 /** 2118 * Manages DownloadService jars which are not mentioned in the JNLP file 2119 * @param ref Path to the resource. 2120 * @param version The version of resource. If null, no version is specified. 2121 * @param action The action to perform with the resource. Either DOWNLOADTOCACHE, REMOVEFROMCACHE, or CHECKCACHE. 2122 * @return true if CHECKCACHE and the resource is cached. 2123 */ 2124 boolean manageExternalJars(URL ref, String version, DownloadAction action) { 2125 boolean approved = false; 2126 JNLPClassLoader foundLoader = LocateJnlpClassLoader.getLoaderByResourceUrl(this, ref, version); 2127 Version resourceVersion = (version == null) ? null : new Version(version); 2128 2129 if (foundLoader != null) 2130 approved = true; 2131 2132 else if (ref.toString().startsWith(file.getCodeBase().toString())) 2133 approved = true; 2134 else if (SecurityDesc.ALL_PERMISSIONS.equals(security.getSecurityType())) 2135 approved = true; 2136 2137 if (approved) { 2138 if (foundLoader == null) 2139 foundLoader = this; 2140 2141 if (action == DownloadAction.DOWNLOAD_TO_CACHE) { 2142 JARDesc jarToCache = new JARDesc(ref, resourceVersion, null, false, true, false, true); 2143 OutputController.getLogger().log("Downloading and initializing jar: " + ref.toString()); 2144 2145 foundLoader.addNewJar(jarToCache, UpdatePolicy.FORCE); 2146 2147 } else if (action == DownloadAction.REMOVE_FROM_CACHE) { 2148 JARDesc[] jarToRemove = { new JARDesc(ref, resourceVersion, null, false, true, false, true) }; 2149 foundLoader.removeJars(jarToRemove); 2150 2151 } else if (action == DownloadAction.CHECK_CACHE) { 2152 return CacheUtil.isCached(ref, resourceVersion); 2153 } 2154 } 2155 return false; 2107 2156 } 2108 2157 … … 2114 2163 * @throws SecurityException if caller is not trusted 2115 2164 */ 2116 public synchronizedvoid decrementLoaderUseCount() {2165 public void decrementLoaderUseCount() { 2117 2166 2118 2167 // For use by trusted code only … … 2120 2169 System.getSecurityManager().checkPermission(new AllPermission()); 2121 2170 2122 useCount--; 2123 2124 if (useCount <= 0) { 2125 synchronized(urlToLoader) { 2126 urlToLoader.remove(file.getUniqueKey()); 2171 String uniqueKey = file.getUniqueKey(); 2172 2173 // NB: There will only ever be one class-loader per unique-key 2174 synchronized ( getUniqueKeyLock(uniqueKey) ) { 2175 useCount--; 2176 2177 if (useCount <= 0) { 2178 uniqueKeyToLoader.remove(uniqueKey); 2127 2179 } 2128 2180 } … … 2150 2202 } catch (AccessControlException ace) { 2151 2203 // continue below 2152 } catch (ClassCircularityError cce) {2153 // continue below2154 2204 } 2155 2205 … … 2165 2215 2166 2216 // Permissions for all remote hosting urls 2167 for (URL u: jarLocationSecurityMap.keySet()) { 2168 permissions.add(new SocketPermission(u.getHost(), 2169 "connect, accept")); 2217 synchronized (jarLocationSecurityMap) { 2218 for (URL u : jarLocationSecurityMap.keySet()) { 2219 permissions.add(new SocketPermission(u.getHost(), 2220 "connect, accept")); 2221 } 2170 2222 } 2171 2223 … … 2182 2234 return new AccessControlContext(new ProtectionDomain[] { pd }); 2183 2235 } 2236 2237 public String getMainClass() { 2238 return mainClass; 2239 } 2240 2241 2242 2243 /** 2244 * SecurityDelegate, in real usage, relies on having a "parent" JNLPClassLoader instance. 2245 * However, JNLPClassLoaders are very large, heavyweight, difficult-to-mock objects, which 2246 * means that unit testing on anything that uses a SecurityDelegate can become very difficult. 2247 * For example, JarCertVerifier is designed separated from the ClassLoader so it can be tested 2248 * in isolation. However, JCV needs some sort of access back to JNLPClassLoader instances to 2249 * be able to invoke setRunInSandbox(). The SecurityDelegate handles this, allowing JCV to be 2250 * tested without instantiating JNLPClassLoaders, by creating a fake SecurityDelegate that does 2251 * not require one. 2252 */ 2253 public static interface SecurityDelegate { 2254 public boolean isPluginApplet(); 2255 2256 public boolean userPromptedForPartialSigning(); 2257 2258 public boolean userPromptedForSandbox(); 2259 2260 public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final String codebaseHost); 2261 2262 public SecurityDesc getClassLoaderSecurity(final String codebaseHost) throws LaunchException; 2263 2264 public SecurityDesc getJarPermissions(final String codebaseHost); 2265 2266 public void promptUserOnPartialSigning() throws LaunchException; 2267 2268 public void setRunInSandbox() throws LaunchException; 2269 2270 public boolean getRunInSandbox(); 2271 2272 public void addPermission(final Permission perm); 2273 2274 public void addPermissions(final PermissionCollection perms); 2275 2276 public void addPermissions(final Collection<Permission> perms); 2277 } 2278 2279 /** 2280 * Handles security decision logic for the JNLPClassLoader, eg which permission level to assign 2281 * to JARs. 2282 */ 2283 public static class SecurityDelegateImpl implements SecurityDelegate { 2284 private final JNLPClassLoader classLoader; 2285 private boolean runInSandbox; 2286 private boolean promptedForPartialSigning; 2287 private boolean promptedForSandbox; 2288 2289 public SecurityDelegateImpl(final JNLPClassLoader classLoader) { 2290 this.classLoader = classLoader; 2291 runInSandbox = false; 2292 promptedForSandbox = false; 2293 } 2294 2295 public boolean isPluginApplet() { 2296 return classLoader.file instanceof PluginBridge; 2297 } 2298 2299 public SecurityDesc getCodebaseSecurityDesc(final JARDesc jarDesc, final String codebaseHost) { 2300 if (runInSandbox) { 2301 return new SecurityDesc(classLoader.file, 2302 SecurityDesc.SANDBOX_PERMISSIONS, 2303 codebaseHost); 2304 } else { 2305 if (isPluginApplet()) { 2306 try { 2307 if (JarCertVerifier.isJarSigned(jarDesc, new PluginAppVerifier(), classLoader.tracker)) { 2308 return new SecurityDesc(classLoader.file, 2309 SecurityDesc.ALL_PERMISSIONS, 2310 codebaseHost); 2311 } else { 2312 return new SecurityDesc(classLoader.file, 2313 SecurityDesc.SANDBOX_PERMISSIONS, 2314 codebaseHost); 2315 } 2316 } catch (final Exception e) { 2317 OutputController.getLogger().log(e); 2318 return new SecurityDesc(classLoader.file, 2319 SecurityDesc.SANDBOX_PERMISSIONS, 2320 codebaseHost); 2321 } 2322 } else { 2323 return classLoader.file.getSecurity(); 2324 } 2325 } 2326 } 2327 2328 public SecurityDesc getClassLoaderSecurity(final String codebaseHost) throws LaunchException { 2329 if (isPluginApplet()) { 2330 if (!runInSandbox && classLoader.getSigning()) { 2331 return new SecurityDesc(classLoader.file, 2332 SecurityDesc.ALL_PERMISSIONS, 2333 codebaseHost); 2334 } else { 2335 return new SecurityDesc(classLoader.file, 2336 SecurityDesc.SANDBOX_PERMISSIONS, 2337 codebaseHost); 2338 } 2339 } else { 2340 /* 2341 * Various combinations of the jars being signed and <security> tags being 2342 * present are possible. They are treated as follows 2343 * 2344 * Jars JNLP File Result 2345 * 2346 * Signed <security> Appropriate Permissions 2347 * Signed no <security> Sandbox 2348 * Unsigned <security> Error 2349 * Unsigned no <security> Sandbox 2350 * 2351 */ 2352 if (!runInSandbox && !classLoader.getSigning() 2353 && !classLoader.file.getSecurity().getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS)) { 2354 if (classLoader.jcv.allJarsSigned()) { 2355 throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LSignedJNLPAppDifferentCerts"), R("LSignedJNLPAppDifferentCertsInfo")); 2356 } else { 2357 throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LUnsignedJarWithSecurity"), R("LUnsignedJarWithSecurityInfo")); 2358 } 2359 } else if (!runInSandbox && classLoader.getSigning()) { 2360 return classLoader.file.getSecurity(); 2361 } else { 2362 return new SecurityDesc(classLoader.file, 2363 SecurityDesc.SANDBOX_PERMISSIONS, 2364 codebaseHost); 2365 } 2366 } 2367 } 2368 2369 public SecurityDesc getJarPermissions(final String codebaseHost) { 2370 if (!runInSandbox && classLoader.jcv.isFullySigned()) { 2371 // Already trust application, nested jar should be given 2372 return new SecurityDesc(classLoader.file, 2373 SecurityDesc.ALL_PERMISSIONS, 2374 codebaseHost); 2375 } else { 2376 return new SecurityDesc(classLoader.file, 2377 SecurityDesc.SANDBOX_PERMISSIONS, 2378 codebaseHost); 2379 } 2380 } 2381 2382 public void setRunInSandbox() throws LaunchException { 2383 if (promptedForSandbox || classLoader.security != null 2384 || classLoader.jarLocationSecurityMap.size() != 0) { 2385 throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCInit"), R("LRunInSandboxError"), R("LRunInSandboxErrorInfo")); 2386 } 2387 2388 JNLPRuntime.reloadPolicy(); // ensure that we have the most up-to-date custom policy loaded 2389 this.promptedForSandbox = true; 2390 this.runInSandbox = true; 2391 } 2392 2393 public void promptUserOnPartialSigning() throws LaunchException { 2394 if (promptedForPartialSigning || JNLPRuntime.isTrustAll()) { 2395 return; 2396 } 2397 promptedForPartialSigning = true; 2398 UnsignedAppletTrustConfirmation.checkPartiallySignedWithUserIfRequired(this, classLoader.file, classLoader.jcv); 2399 } 2400 2401 public boolean getRunInSandbox() { 2402 return this.runInSandbox; 2403 } 2404 2405 public boolean userPromptedForPartialSigning() { 2406 return this.promptedForPartialSigning; 2407 } 2408 2409 public boolean userPromptedForSandbox() { 2410 return this.promptedForSandbox; 2411 } 2412 2413 public void addPermission(final Permission perm) { 2414 classLoader.addPermission(perm); 2415 } 2416 2417 public void addPermissions(final PermissionCollection perms) { 2418 Enumeration<Permission> e = perms.elements(); 2419 while (e.hasMoreElements()) { 2420 addPermission(e.nextElement()); 2421 } 2422 } 2423 2424 public void addPermissions(final Collection<Permission> perms) { 2425 for (final Permission perm : perms) { 2426 addPermission(perm); 2427 } 2428 } 2429 2430 } 2431 2184 2432 2185 2433 /* 2186 2434 * Helper class to expose protected URLClassLoader methods. 2187 */ 2188 2435 * Classes loaded from the codebase are absolutely NOT signed, by definition! 2436 * If the CodeBaseClassLoader is used to load any classes in JNLPClassLoader, 2437 * then you *MUST* check if the JNLPClassLoader is set to FULL signing. If so, 2438 * then it must be set instead to PARTIAL, and the user prompted if it is okay 2439 * to proceed. If the JNLPClassLoader is already PARTIAL or NONE signing, then 2440 * nothing must be done. This is required so that we can support partial signing 2441 * of applets but also ensure that using codebase loading in conjunction with 2442 * signed JARs still results in the user having to confirm that this is 2443 * acceptable. 2444 */ 2189 2445 public static class CodeBaseClassLoader extends URLClassLoader { 2190 2446 … … 2197 2453 2198 2454 public CodeBaseClassLoader(URL[] urls, JNLPClassLoader cl) { 2199 super(urls );2455 super(urls, cl); 2200 2456 parentJNLPClassLoader = cl; 2201 2457 } … … 2206 2462 } 2207 2463 2208 @Override 2209 public Class<?> findClass(String name) throws ClassNotFoundException { 2210 return findClass(name, false); 2211 } 2212 2213 public Class<?> findClass(String name, boolean recursivelyInvoked) throws ClassNotFoundException { 2214 2215 if (!recursivelyInvoked) { 2216 try { 2217 return parentJNLPClassLoader.findClass(name); 2218 } catch (ClassNotFoundException cnfe) { 2219 // continue 2220 } 2221 } 2222 2464 /* 2465 * Use with care! Check the class-level Javadoc before calling this. 2466 */ 2467 Class<?> findClassNonRecursive(final String name) throws ClassNotFoundException { 2223 2468 // If we have searched this path before, don't try again 2224 2469 if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) … … 2226 2471 2227 2472 try { 2228 final String fName = name;2229 2473 return AccessController.doPrivileged( 2230 2474 new PrivilegedExceptionAction<Class<?>>() { 2231 2475 public Class<?> run() throws ClassNotFoundException { 2232 return CodeBaseClassLoader.super.findClass(fName); 2476 Class<?> c = CodeBaseClassLoader.super.findClass(name); 2477 parentJNLPClassLoader.checkPartialSigningWithUser(); 2478 return c; 2233 2479 } 2234 2480 }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); 2235 2481 } catch (PrivilegedActionException pae) { 2236 2482 notFoundResources.put(name, super.getURLs()); 2237 throw new ClassNotFoundException("Could not find class " + name); 2238 } 2483 throw new ClassNotFoundException("Could not find class " + name, pae); 2484 } catch (NullJnlpFileException njf) { 2485 notFoundResources.put(name, super.getURLs()); 2486 throw new ClassNotFoundException("Could not find class " + name, njf); 2487 } 2488 } 2489 2490 /* 2491 * Use with care! Check the class-level Javadoc before calling this. 2492 */ 2493 @Override 2494 public Class<?> findClass(String name) throws ClassNotFoundException { 2495 // Calls JNLPClassLoader#findClass which may call into this.findClassNonRecursive 2496 Class<?> c = getParentJNLPClassLoader().findClass(name); 2497 parentJNLPClassLoader.checkPartialSigningWithUser(); 2498 return c; 2239 2499 } 2240 2500 … … 2299 2559 }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); 2300 2560 } catch (PrivilegedActionException pae) { 2301 } 2561 } 2302 2562 2303 2563 if (url == null) { … … 2311 2571 } 2312 2572 } 2573 2574 2313 2575 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java
r348 r429 24 24 25 25 import net.sourceforge.jnlp.config.DeploymentConfiguration; 26 import net.sourceforge.jnlp.util.logging.OutputController; 26 27 27 28 /** … … 91 92 // systempolicy permissions need to be accounted for as well 92 93 e = systemPolicy.getPermissions(appletCS).elements(); 93 while (e.hasMoreElements()) 94 while (e.hasMoreElements()) { 94 95 clPermissions.add(e.nextElement()); 96 } 95 97 96 98 // and so do permissions from the jnlp-specific system policy 97 99 if (systemJnlpPolicy != null) { 98 100 e = systemJnlpPolicy.getPermissions(appletCS).elements(); 99 while (e.hasMoreElements()) 101 while (e.hasMoreElements()) { 100 102 clPermissions.add(e.nextElement()); 103 } 101 104 } 102 105 … … 104 107 if (userJnlpPolicy != null) { 105 108 e = userJnlpPolicy.getPermissions(appletCS).elements(); 106 while (e.hasMoreElements()) 109 while (e.hasMoreElements()) { 107 110 clPermissions.add(e.nextElement()); 111 } 112 113 CodeSource appletCodebaseSource = new CodeSource(JNLPRuntime.getApplication().getJNLPFile().getCodeBase(), (java.security.cert.Certificate[]) null); 114 e = userJnlpPolicy.getPermissions(appletCodebaseSource).elements(); 115 while (e.hasMoreElements()) { 116 clPermissions.add(e.nextElement()); 117 } 108 118 } 109 119 … … 120 130 */ 121 131 public void refresh() { 122 // no op 132 if (userJnlpPolicy != null) { 133 userJnlpPolicy.refresh(); 134 } 123 135 } 124 136 … … 168 180 policy = getInstance("JavaPolicy", new URIParameter(policyUri)); 169 181 } catch (IllegalArgumentException e) { 170 e.printStackTrace();182 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 171 183 } catch (NoSuchAlgorithmException e) { 172 e.printStackTrace();184 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 173 185 } catch (URISyntaxException e) { 174 e.printStackTrace();186 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 175 187 } 176 188 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPProxySelector.java
r348 r429 34 34 35 35 import net.sourceforge.jnlp.config.DeploymentConfiguration; 36 import net.sourceforge.jnlp.util.logging.OutputController; 36 37 37 38 /** … … 83 84 private String overrideHosts = null; 84 85 85 /** 86 * Creates a new JNLPProxySelector. 87 */ 88 public JNLPProxySelector() { 89 parseConfiguration(); 86 public JNLPProxySelector(DeploymentConfiguration config) { 87 parseConfiguration(config); 90 88 } 91 89 … … 93 91 * Initialize this ProxySelector by reading the configuration 94 92 */ 95 private void parseConfiguration() { 96 DeploymentConfiguration config = JNLPRuntime.getConfiguration(); 97 93 private void parseConfiguration(DeploymentConfiguration config) { 98 94 proxyType = Integer.valueOf(config.getProperty(DeploymentConfiguration.KEY_PROXY_TYPE)); 99 95 … … 103 99 autoConfigUrl = new URL(autoConfigString); 104 100 } catch (MalformedURLException e) { 105 e.printStackTrace();101 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 106 102 } 107 103 } … … 165 161 proxyPort = Integer.valueOf(port); 166 162 } catch (NumberFormatException e) { 167 e.printStackTrace();163 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 168 164 } 169 165 } … … 176 172 @Override 177 173 public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 178 ioe.printStackTrace();174 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ioe); 179 175 } 180 176 … … 184 180 @Override 185 181 public List<Proxy> select(URI uri) { 186 if (JNLPRuntime.isDebug()) { 187 System.out.println("Selecting proxy for: " + uri); 188 } 189 182 OutputController.getLogger().log("Selecting proxy for: " + uri); 183 190 184 if (inBypassList(uri)) { 191 185 List<Proxy> proxies = Arrays.asList(new Proxy[] { Proxy.NO_PROXY }); 192 if (JNLPRuntime.isDebug()) { 193 System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray())); 194 } 186 OutputController.getLogger().log("Selected proxies: " + Arrays.toString(proxies.toArray())); 195 187 return proxies; 196 188 } … … 217 209 } 218 210 219 if (JNLPRuntime.isDebug()) { 220 System.out.println("Selected proxies: " + Arrays.toString(proxies.toArray())); 221 } 211 OutputController.getLogger().log("Selected proxies: " + Arrays.toString(proxies.toArray())); 222 212 return proxies; 223 213 } … … 241 231 } 242 232 } else if (scheme.equals("socket")) { 243 String host = uri.get SchemeSpecificPart().split(":")[0];233 String host = uri.getHost(); 244 234 245 235 if (bypassLocal && isLocalHost(host)) { … … 299 289 */ 300 290 private List<Proxy> getFromConfiguration(URI uri) { 291 return getFromArguments(uri, sameProxy, false, 292 proxyHttpsHost, proxyHttpsPort, 293 proxyHttpHost, proxyHttpPort, 294 proxyFtpHost, proxyFtpPort, 295 proxySocks4Host, proxySocks4Port); 296 } 297 298 /** 299 * Returns a list of proxies by using the arguments 300 * 301 * @return a List of Proxy objects 302 */ 303 protected static List<Proxy> getFromArguments(URI uri, 304 boolean sameProxy, boolean sameProxyIncludesSocket, 305 String proxyHttpsHost, int proxyHttpsPort, 306 String proxyHttpHost, int proxyHttpPort, 307 String proxyFtpHost, int proxyFtpPort, 308 String proxySocks4Host, int proxySocks4Port) { 309 301 310 List<Proxy> proxies = new ArrayList<Proxy>(); 302 311 303 312 String scheme = uri.getScheme(); 304 313 314 boolean socksProxyAdded = false; 315 305 316 if (sameProxy) { 306 SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort); 307 Proxy proxy; 308 if (scheme.equals("socket")) { 309 proxy = new Proxy(Type.SOCKS, sa); 310 } else { 311 proxy = new Proxy(Type.HTTP, sa); 312 } 313 proxies.add(proxy); 314 } else if (scheme.equals("http")) { 317 if (proxyHttpHost != null) { 318 SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort); 319 if ((scheme.equals("https") || scheme.equals("http") || scheme.equals("ftp"))) { 320 Proxy proxy = new Proxy(Type.HTTP, sa); 321 proxies.add(proxy); 322 } else if (scheme.equals("socket") && sameProxyIncludesSocket) { 323 Proxy proxy = new Proxy(Type.SOCKS, sa); 324 proxies.add(proxy); 325 socksProxyAdded = true; 326 } 327 } 328 } else if (scheme.equals("http") && proxyHttpHost != null) { 315 329 SocketAddress sa = new InetSocketAddress(proxyHttpHost, proxyHttpPort); 316 330 proxies.add(new Proxy(Type.HTTP, sa)); 317 } else if (scheme.equals("https") ) {331 } else if (scheme.equals("https") && proxyHttpsHost != null) { 318 332 SocketAddress sa = new InetSocketAddress(proxyHttpsHost, proxyHttpsPort); 319 333 proxies.add(new Proxy(Type.HTTP, sa)); 320 } else if (scheme.equals("ftp") ) {334 } else if (scheme.equals("ftp") && proxyFtpHost != null) { 321 335 SocketAddress sa = new InetSocketAddress(proxyFtpHost, proxyFtpPort); 322 336 proxies.add(new Proxy(Type.HTTP, sa)); 323 } else if (scheme.equals("socket")) { 337 } 338 339 if (!socksProxyAdded && (proxySocks4Host != null)) { 324 340 SocketAddress sa = new InetSocketAddress(proxySocks4Host, proxySocks4Port); 325 341 proxies.add(new Proxy(Type.SOCKS, sa)); 326 } else { 342 socksProxyAdded = true; 343 } 344 345 if (proxies.size() == 0) { 327 346 proxies.add(Proxy.NO_PROXY); 328 347 } … … 349 368 proxies.addAll(getProxiesFromPacResult(proxiesString)); 350 369 } catch (MalformedURLException e) { 351 e.printStackTrace();370 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 352 371 proxies.add(Proxy.NO_PROXY); 353 372 } … … 369 388 * @param pacString a string indicating proxies. For example 370 389 * "PROXY foo.bar:3128; DIRECT" 371 * @return a list of Proxy objects represeting the parsed string. 390 * @return a list of Proxy objects representing the parsed string. In 391 * case of malformed input, an empty list may be returned 372 392 */ 373 393 public static List<Proxy> getProxiesFromPacResult(String pacString) { … … 407 427 proxies.add(Proxy.NO_PROXY); 408 428 } else { 409 if (JNLPRuntime.isDebug()) { 410 System.out.println("Unrecognized proxy token: " + token); 411 } 429 OutputController.getLogger().log("Unrecognized proxy token: " + token); 412 430 } 413 431 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
r418 r429 17 17 package net.sourceforge.jnlp.runtime; 18 18 19 import java.io.*; 19 import java.awt.EventQueue; 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.FileOutputStream; 23 import java.io.IOException; 24 import java.lang.reflect.Constructor; 25 import java.lang.reflect.InvocationTargetException; 20 26 import java.net.Authenticator; 27 import java.net.InetAddress; 21 28 import java.net.ProxySelector; 29 import java.net.URL; 30 import java.net.UnknownHostException; 22 31 import java.nio.channels.FileChannel; 23 32 import java.nio.channels.FileLock; 24 import java.awt.*; 25 import java.text.*; 26 import java.util.*; 33 import java.security.AllPermission; 34 import java.security.KeyStore; 35 import java.security.Policy; 36 import java.security.Security; 37 import java.text.MessageFormat; 27 38 import java.util.List; 28 import java.security.*; 29 import javax.jnlp.*; 39 import java.util.ResourceBundle; 40 41 import javax.jnlp.ServiceManager; 30 42 import javax.naming.ConfigurationException; 31 43 import javax.net.ssl.HttpsURLConnection; … … 34 46 import javax.net.ssl.SSLSocketFactory; 35 47 import javax.net.ssl.TrustManager; 48 import javax.swing.JOptionPane; 36 49 import javax.swing.UIManager; 37 50 import javax.swing.text.html.parser.ParserDelegator; 38 51 39 import sun.net.www.protocol.jar.URLJarFile; 40 41 import net.sourceforge.jnlp.*; 52 import net.sourceforge.jnlp.DefaultLaunchHandler; 53 import net.sourceforge.jnlp.GuiLaunchHandler; 54 import net.sourceforge.jnlp.LaunchHandler; 55 import net.sourceforge.jnlp.Launcher; 42 56 import net.sourceforge.jnlp.browser.BrowserAwareProxySelector; 43 import net.sourceforge.jnlp.cache.*; 57 import net.sourceforge.jnlp.cache.CacheUtil; 58 import net.sourceforge.jnlp.cache.DefaultDownloadIndicator; 59 import net.sourceforge.jnlp.cache.DownloadIndicator; 60 import net.sourceforge.jnlp.cache.UpdatePolicy; 44 61 import net.sourceforge.jnlp.config.DeploymentConfiguration; 45 62 import net.sourceforge.jnlp.security.JNLPAuthenticator; 46 63 import net.sourceforge.jnlp.security.KeyStores; 47 64 import net.sourceforge.jnlp.security.SecurityDialogMessageHandler; 48 import net.sourceforge.jnlp.security.VariableX509TrustManager; 49 import net.sourceforge.jnlp.services.*; 50 import net.sourceforge.jnlp.util.*; 65 import net.sourceforge.jnlp.services.XServiceManagerStub; 66 import net.sourceforge.jnlp.util.FileUtils; 67 import net.sourceforge.jnlp.util.logging.JavaConsole; 68 import net.sourceforge.jnlp.util.logging.OutputController; 69 import net.sourceforge.jnlp.util.logging.LogConfig; 70 import sun.net.www.protocol.jar.URLJarFile; 51 71 52 72 /** 73 * <p> 53 74 * Configure and access the runtime environment. This class 54 75 * stores global jnlp properties such as default download 55 76 * indicators, the install/base directory, the default resource 56 77 * update policy, etc. Some settings, such as the base directory, 57 * cannot be changed once the runtime has been initialized.<p> 58 * 78 * cannot be changed once the runtime has been initialized. 79 * </p> 80 * <p> 59 81 * The JNLP runtime can be locked to prevent further changes to 60 82 * the runtime environment except by a specified class. If set, 61 83 * only instances of the <i>exit class</i> can exit the JVM or 62 84 * change the JNLP runtime settings once the runtime has been 63 * initialized.<p> 85 * initialized. 86 * </p> 64 87 * 65 88 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 72 95 } 73 96 97 /** 98 * java-abrt-connector can print out specific application String method, it is good to save visited urls for reproduce purposes. 99 * For javaws we can read the destination jnlp from commandline 100 * However for plugin (url arrive via pipes). Also for plugin we can not be sure which opened tab/window 101 * have caused the crash. Thats why the individual urls are added, not replaced. 102 */ 103 private static String history = ""; 104 74 105 /** the localized resource strings */ 75 106 private static ResourceBundle resources; 76 107 77 private static final DeploymentConfiguration config = new DeploymentConfiguration();78 79 108 /** the security manager */ 80 109 private static JNLPSecurityManager security; … … 110 139 private static boolean debug = false; 111 140 112 /** whether streams should be redirected */ 113 private static boolean redirectStreams = false; 141 /** 142 * whether plugin debug mode is on 143 */ 144 private static Boolean pluginDebug = null; 114 145 115 146 /** mutex to wait on, for initialization */ … … 122 153 private static boolean forksAllowed = true; 123 154 124 /** all security dialogs will be consumed and pretented as be eing verified by user and allowed.*/155 /** all security dialogs will be consumed and pretented as being verified by user and allowed.*/ 125 156 private static boolean trustAll=false; 157 158 /** all security dialogs will be consumed and we will pretend the Sandbox option was chosen */ 159 private static boolean trustNone = false; 160 161 /** allows 301.302.303.307.308 redirects to be followed when downloading resources*/ 162 private static boolean allowRedirect = false;; 163 164 /** when this is true, ITW will not attempt any inet connections and will work only with what is in cache*/ 165 private static boolean offlineForced = false; 166 167 private static Boolean onlineDetected = null; 168 169 170 /** 171 * Header is not checked and so eg 172 * <a href="https://en.wikipedia.org/wiki/Gifar">gifar</a> exploit is 173 * possible.<br/> 174 * However if jar file is a bit corrupted, then it sometimes can work so 175 * this switch can disable the header check. 176 * @see <a href="https://en.wikipedia.org/wiki/Gifar">Gifar attack</a> 177 */ 178 private static boolean ignoreHeaders=false; 126 179 127 180 /** contains the arguments passed to the jnlp runtime */ … … 131 184 private static FileLock fileLock; 132 185 133 public static final String STDERR_FILE = "java.stderr";134 public static final String STDOUT_FILE = "java.stdout";135 136 137 186 /** 138 187 * Returns whether the JNLP runtime environment has been 139 * initialized. 140 * base directory cannot be changed. 188 * initialized. Once initialized, some properties such as the 189 * base directory cannot be changed. Before 141 190 */ 142 191 public static boolean isInitialized() { … … 147 196 * Initialize the JNLP runtime environment by installing the 148 197 * security manager and security policy, initializing the JNLP 149 * standard services, etc.<p> 150 * 151 * This method should be called from the main AppContext/Thread. <p> 152 * 153 * This method cannot be called more than once. Once 198 * standard services, etc. 199 * <p> 200 * This method should be called from the main AppContext/Thread. 201 * </p> 202 * <p> 203 * This method cannot be called more than once. Once 154 204 * initialized, methods that alter the runtime can only be 155 * called by the exit class.<p> 156 * 157 * @param isApplication is true if a webstart application is being initialized 158 * 205 * called by the exit class. 206 * </p> 207 * 208 * @param isApplication is {@code true} if a webstart application is being 209 * initialized 159 210 * @throws IllegalStateException if the runtime was previously initialized 160 211 */ … … 163 214 164 215 try { 165 config.load(); 166 } catch (ConfigurationException e) { 167 /* exit if there is a fatal exception loading the configuration */ 168 if (isApplication) { 169 System.out.println(getMessage("RConfigurationError")); 170 System.exit(1); 171 } 172 } 173 174 KeyStores.setConfiguration(config); 175 176 initializeStreams(); 216 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 217 } catch (Exception e) { 218 OutputController.getLogger().log("Unable to set system look and feel"); 219 } 220 221 if (JavaConsole.canShowOnStartup(isApplication)) { 222 JavaConsole.getConsole().showConsoleLater(); 223 } 224 /* exit if there is a fatal exception loading the configuration */ 225 if (getConfiguration().getLoadingException() != null) { 226 if (getConfiguration().getLoadingException() instanceof ConfigurationException){ 227 // ConfigurationException is thrown only if deployment.config's field 228 // deployment.system.config.mandatory is true, and the destination 229 //where deployment.system.config points is not readable 230 throw new RuntimeException(getConfiguration().getLoadingException()); 231 } 232 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, getMessage("RConfigurationError")+": "+getConfiguration().getLoadingException().getMessage()); 233 } 234 KeyStores.setConfiguration(getConfiguration()); 177 235 178 236 isWebstartApplication = isApplication; … … 191 249 if (handler == null) { 192 250 if (headless) { 193 handler = new DefaultLaunchHandler( System.err);251 handler = new DefaultLaunchHandler(OutputController.getLogger()); 194 252 } else { 195 handler = new GuiLaunchHandler( System.err);253 handler = new GuiLaunchHandler(OutputController.getLogger()); 196 254 } 197 255 } … … 201 259 policy = new JNLPPolicy(); 202 260 security = new JNLPSecurityManager(); // side effect: create JWindow 203 204 try {205 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());206 } catch (Exception e) {207 // ignore it208 }209 261 210 262 doMainAppContextHacks(); … … 224 276 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 225 277 kmf.init(ks, KeyStores.getPassword()); 226 TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() };278 TrustManager[] trust = new TrustManager[] { getSSLSocketTrustManager() }; 227 279 context.init(kmf.getKeyManagers(), trust, null); 228 280 sslSocketFactory = context.getSocketFactory(); … … 230 282 HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); 231 283 } catch (Exception e) { 232 System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway...");233 e.printStackTrace();284 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway..."); 285 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 234 286 } 235 287 236 288 // plug in a custom authenticator and proxy selector 237 289 Authenticator.setDefault(new JNLPAuthenticator()); 238 ProxySelector.setDefault(new BrowserAwareProxySelector()); 290 BrowserAwareProxySelector proxySelector = new BrowserAwareProxySelector(getConfiguration()); 291 proxySelector.initialize(); 292 ProxySelector.setDefault(proxySelector); 239 293 240 294 // Restrict access to netx classes … … 246 300 initialized = true; 247 301 302 } 303 304 public static void reloadPolicy() { 305 policy.refresh(); 306 } 307 308 /** 309 * Returns a TrustManager ideal for the running VM. 310 * 311 * @return TrustManager the trust manager to use for verifying https certificates 312 */ 313 private static TrustManager getSSLSocketTrustManager() throws 314 ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException { 315 316 try { 317 318 Class<?> trustManagerClass; 319 Constructor<?> tmCtor = null; 320 321 if (System.getProperty("java.version").startsWith("1.6")) { // Java 6 322 try { 323 trustManagerClass = Class.forName("net.sourceforge.jnlp.security.VariableX509TrustManagerJDK6"); 324 } catch (ClassNotFoundException cnfe) { 325 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to find class net.sourceforge.jnlp.security.VariableX509TrustManagerJDK6"); 326 return null; 327 } 328 } else { // Java 7 or more (technically could be <= 1.5 but <= 1.5 is unsupported) 329 try { 330 trustManagerClass = Class.forName("net.sourceforge.jnlp.security.VariableX509TrustManagerJDK7"); 331 } catch (ClassNotFoundException cnfe) { 332 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to find class net.sourceforge.jnlp.security.VariableX509TrustManagerJDK7"); 333 return null; 334 } 335 } 336 337 Constructor<?>[] tmCtors = trustManagerClass.getDeclaredConstructors(); 338 tmCtor = tmCtors[0]; 339 340 for (Constructor<?> ctor : tmCtors) { 341 if (tmCtor.getGenericParameterTypes().length == 0) { 342 tmCtor = ctor; 343 break; 344 } 345 } 346 347 return (TrustManager) tmCtor.newInstance(); 348 } catch (RuntimeException e) { 349 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to load JDK-specific TrustManager. Was this version of IcedTea-Web compiled with JDK 6 or 7?"); 350 OutputController.getLogger().log(e); 351 throw e; 352 } 248 353 } 249 354 … … 282 387 } 283 388 284 /** 285 * Initializes the standard output and error streams, redirecting them or 286 * duplicating them as required. 287 */ 288 private static void initializeStreams() { 289 Boolean enableLogging = Boolean.valueOf(config 290 .getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING)); 291 if (redirectStreams || enableLogging) { 292 String logDir = config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR); 293 389 390 391 392 393 394 395 public static boolean isOfflineForced() { 396 return offlineForced; 397 } 398 399 public static void setOnlineDetected(boolean online) { 400 onlineDetected = online; 401 OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "Detected online set to: " + onlineDetected); 402 } 403 404 public static boolean isOnlineDetected() { 405 if (onlineDetected == null) { 406 //"file" protocol do not do online check 407 //sugest online for this case 408 return true; 409 } 410 return onlineDetected; 411 } 412 413 public static boolean isOnline() { 414 if (isOfflineForced()) { 415 return false; 416 } 417 return isOnlineDetected(); 418 } 419 420 public static void detectOnline(URL location) { 421 if (onlineDetected != null) { 422 return; 423 } 424 try { 425 if (location.getProtocol().equals("file")) { 426 return; 427 } 428 //Checks the offline/online status of the system. 429 InetAddress.getByName(location.getHost()); 430 } catch (UnknownHostException ue) { 431 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "The host of " + location.toExternalForm() + " file should be located seems down, or you are simply offline."); 432 JNLPRuntime.setOnlineDetected(false); 433 return; 434 } 435 setOnlineDetected(true); 436 } 437 438 /** 439 * see <a href="https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java">Double-checked locking in Java</a> 440 * for cases how not to do lazy initialization 441 * and <a href="https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom">Initialization on demand holder idiom</a> 442 * for ITW approach 443 */ 444 private static class DeploymentConfigurationHolder { 445 446 private static final DeploymentConfiguration INSTANCE = initConfiguration(); 447 448 private static DeploymentConfiguration initConfiguration() { 449 DeploymentConfiguration config = new DeploymentConfiguration(); 294 450 try { 295 File errFile = new File(logDir, JNLPRuntime.STDERR_FILE);296 FileUtils.createParentDir(errFile);297 FileUtils.createRestrictedFile(errFile, true);298 File outFile = new File(logDir, JNLPRuntime.STDOUT_FILE);299 FileUtils.createParentDir(outFile);300 FileUtils.createRestrictedFile(outFile, true);301 302 if (redirectStreams){303 System.setErr(new PrintStream(new FileOutputStream(errFile)));304 System.setOut(new PrintStream(new FileOutputStream(outFile)));305 } else {306 System.setErr(new TeeOutputStream(new FileOutputStream(errFile), System.err));307 System.setOut(new TeeOutputStream(new FileOutputStream(outFile), System.out));451 config.load(); 452 config.copyTo(System.getProperties()); 453 } catch (ConfigurationException ex) { 454 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("RConfigurationError")); 455 //mark this exceptionas we can die on it later 456 config.setLoadingException(ex); 457 //to be sure - we MUST die - http://docs.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/properties.html 458 }catch(Exception t){ 459 //all exceptions are causing InstantiatizationError so this do it much more readble 460 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, t); 461 OutputController.getLogger().log(OutputController.Level.WARNING_ALL, Translator.R("RFailingToDefault")); 462 if (!JNLPRuntime.isHeadless()){ 463 JOptionPane.showMessageDialog(null, getMessage("RFailingToDefault")+"\n"+t.toString()); 308 464 } 309 } catch (Exception e) { 310 e.printStackTrace(); 311 } 465 //try to survive this unlikely exception 466 config.resetToDefaults(); 467 } finally { 468 OutputController.getLogger().startConsumer(); 469 } 470 return config; 312 471 } 313 472 } … … 315 474 /** 316 475 * Gets the Configuration associated with this runtime 476 * 317 477 * @return a {@link DeploymentConfiguration} object that can be queried to 318 478 * find relevant configuration settings 319 479 */ 320 480 public static DeploymentConfiguration getConfiguration() { 321 return config;481 return DeploymentConfigurationHolder.INSTANCE; 322 482 } 323 483 … … 349 509 * components. In headless mode, client features that use the 350 510 * AWT are disabled such that the client can be used in 351 * headless mode ( <code>java.awt.headless=true</code>).511 * headless mode ({@code java.awt.headless=true}). 352 512 * 353 513 * @throws IllegalStateException if the runtime was previously initialized … … 357 517 headless = enabled; 358 518 } 519 520 public static void setAllowRedirect(boolean enabled) { 521 checkInitialized(); 522 allowRedirect = enabled; 523 } 524 525 public static boolean isAllowRedirect() { 526 return allowRedirect; 527 } 528 359 529 360 530 /** … … 379 549 * applications, and can be used to use netx with other code 380 550 * that uses its own security manager or policy. 381 * 551 * <p> 382 552 * Disabling security is not recommended and should only be 383 * used if the JNLP files opened are trusted. This method can 384 * only be called before initalizing the runtime.<p> 553 * used if the JNLP files opened are trusted. This method can 554 * only be called before initalizing the runtime. 555 * </p> 385 556 * 386 557 * @param enabled whether security should be enabled … … 411 582 * @throws IllegalStateException if caller is not the exit class 412 583 */ 413 public static void setExitClass(Class exitClass) {584 public static void setExitClass(Class<?> exitClass) { 414 585 checkExitClass(); 415 586 security.setExitClass(exitClass); … … 438 609 */ 439 610 public static boolean isDebug() { 611 return isSetDebug() || isPluginDebug() || LogConfig.getLogConfig().isEnableLogging(); 612 } 613 614 public static boolean isSetDebug() { 440 615 return debug; 441 616 } … … 452 627 } 453 628 454 /** 455 * Sets whether the standard output/error streams should be redirected to 456 * the loggging files. 457 * 458 * @throws IllegalStateException if the runtime has already been initialized 459 */ 460 public static void setRedirectStreams(boolean redirect) { 461 checkInitialized(); 462 redirectStreams = redirect; 463 } 464 629 465 630 /** 466 631 * Sets the default update policy. … … 514 679 /** 515 680 * Returns the localized resource string identified by the 516 * specified key. 681 * specified key. If the message is empty, a null is 517 682 * returned. 518 683 */ … … 533 698 534 699 /** 535 * Returns the localized resource string using the specified 536 * arguments. 700 * Returns the localized resource string using the specified arguments. 537 701 * 538 702 * @param args the formatting arguments to the resource string … … 543 707 544 708 /** 545 * Returns trueif the current runtime will fork709 * Returns {@code true} if the current runtime will fork 546 710 */ 547 711 public static boolean getForksAllowed() { … … 555 719 556 720 /** 557 * Throws an exception if called when the runtime is 558 * already initialized. 721 * Throws an exception if called when the runtime is already initialized. 559 722 */ 560 723 private static void checkInitialized() { … … 564 727 565 728 /** 566 * Throws an exception if called with security enabled but 567 * a caller is not the exit class and the runtime has been 568 * initialized. 729 * Throws an exception if called with security enabled but a caller is not 730 * the exit class and the runtime has been initialized. 569 731 */ 570 732 private static void checkExitClass() { … … 599 761 600 762 /** 601 * @return trueif running on Windows763 * @return {@code true} if running on Windows 602 764 */ 603 765 public static boolean isWindows() { … … 607 769 608 770 /** 609 * @return true if running on a Unix or Unix-like system (including Linux610 * and *BSD)771 * @return {@code true} if running on a Unix or Unix-like system (including 772 * Linux and *BSD) 611 773 */ 612 774 public static boolean isUnix() { … … 628 790 629 791 /** 630 * Indicate that netx is running by creating the {@link JNLPRuntime#INSTANCE_FILE} and 792 * Indicate that netx is running by creating the 793 * {@link DeploymentConfiguration#KEY_USER_NETX_RUNNING_FILE} and 631 794 * acquiring a shared lock on it 632 795 */ … … 662 825 663 826 if (fileLock != null && fileLock.isShared()) { 664 if (JNLPRuntime.isDebug()) { 665 System.out.println("Acquired shared lock on " + 827 OutputController.getLogger().log("Acquired shared lock on " + 666 828 netxRunningFile.toString() + " to indicate javaws is running"); 667 }668 829 } 669 830 } catch (IOException e) { 670 e.printStackTrace();671 } 672 673 Runtime.getRuntime().addShutdownHook(new Thread( ) {831 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 832 } 833 834 Runtime.getRuntime().addShutdownHook(new Thread("JNLPRuntimeShutdownHookThread") { 674 835 public void run() { 675 836 markNetxStopped(); … … 681 842 /** 682 843 * Indicate that netx is stopped by releasing the shared lock on 683 * {@link JNLPRuntime#INSTANCE_FILE}.844 * {@link DeploymentConfiguration#KEY_USER_NETX_RUNNING_FILE}. 684 845 */ 685 846 private static void markNetxStopped() { … … 691 852 fileLock.channel().close(); 692 853 fileLock = null; 693 if (JNLPRuntime.isDebug()) { 694 String file = JNLPRuntime.getConfiguration() 695 .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE); 696 System.out.println("Release shared lock on " + file); 697 } 854 OutputController.getLogger().log("Release shared lock on " + JNLPRuntime.getConfiguration() 855 .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE)); 698 856 } catch (IOException e) { 699 e.printStackTrace();857 OutputController.getLogger().log(e); 700 858 } 701 859 } … … 709 867 } 710 868 869 static void setTrustNone(final boolean b) { 870 trustNone = b; 871 } 872 873 public static boolean isTrustNone() { 874 return trustNone; 875 } 876 877 public static boolean isIgnoreHeaders() { 878 return ignoreHeaders; 879 } 880 881 public static void setIgnoreHeaders(boolean ignoreHeaders) { 882 JNLPRuntime.ignoreHeaders = ignoreHeaders; 883 } 884 885 private static boolean isPluginDebug() { 886 if (pluginDebug == null) { 887 try { 888 //there are cases when this itself is not allowed by security manager, and so 889 //throws exception. Under some conditions it can couse deadlock 890 pluginDebug = System.getenv().containsKey("ICEDTEAPLUGIN_DEBUG"); 891 } catch (Exception ex) { 892 pluginDebug = false; 893 OutputController.getLogger().log(ex); 894 } 895 } 896 return pluginDebug; 897 } 898 899 public static void exit(int i) { 900 OutputController.getLogger().close(); 901 System.exit(i); 902 } 903 904 905 public static void saveHistory(String documentBase) { 906 JNLPRuntime.history += " " + documentBase + " "; 907 } 908 909 /** 910 * Used by java-abrt-connector via reflection 911 * @return history 912 */ 913 private static String getHistory() { 914 return history; 915 } 916 917 918 711 919 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
r418 r429 19 19 import static net.sourceforge.jnlp.runtime.Translator.R; 20 20 21 import java.awt.Frame;22 21 import java.awt.Window; 23 import java.lang.ref.WeakReference;24 22 import java.net.SocketPermission; 25 import java.security.AllPermission;26 23 import java.security.AccessControlException; 27 24 import java.security.Permission; 28 import java.security.SecurityPermission;29 25 30 26 import javax.swing.JWindow; 31 27 32 import net.sourceforge.jnlp.JNLPFile;33 28 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 34 29 import net.sourceforge.jnlp.services.ServiceUtil; 30 import net.sourceforge.jnlp.util.logging.OutputController; 35 31 import net.sourceforge.jnlp.util.WeakList; 36 32 import sun.awt.AWTSecurityManager; 37 33 import sun.awt.AppContext; 38 import sun.security.util.SecurityConstants;39 34 40 35 /** 41 * Security manager for JNLP environment. 36 * Security manager for JNLP environment. This security manager 42 37 * cannot be replaced as it always denies attempts to replace the 43 * security manager or policy. <p>44 * 38 * security manager or policy. 39 * <p> 45 40 * The JNLP security manager tracks windows created by an 46 41 * application, allowing those windows to be disposed when the 47 * application exits but the JVM does not. 42 * application exits but the JVM does not. If security is not 48 43 * enabled then the first application to call System.exit will 49 * halt the JVM.<p> 44 * halt the JVM. 45 * </p> 50 46 * 51 47 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 118 114 // called for it (and not disposed). 119 115 120 if (!JNLPRuntime.isHeadless()) 116 if (!JNLPRuntime.isHeadless()) { 121 117 new JWindow().getOwner(); 118 } 122 119 123 120 mainAppContext = AppContext.getAppContext(); … … 137 134 */ 138 135 private boolean isExitClass(Class stack[]) { 139 if (exitClass == null) 136 if (exitClass == null) { 140 137 return true; 141 142 for (int i = 0; i < stack.length; i++) 143 if (stack[i] == exitClass) 138 } 139 140 for (int i = 0; i < stack.length; i++) { 141 if (stack[i] == exitClass) { 144 142 return true; 143 } 144 } 145 145 146 146 return false; … … 154 154 * @throws IllegalStateException if the exit class is already set 155 155 */ 156 public void setExitClass(Class exitClass) throws IllegalStateException {157 if (this.exitClass != null) 156 public void setExitClass(Class<?> exitClass) throws IllegalStateException { 157 if (this.exitClass != null) { 158 158 throw new IllegalStateException(R("RExitTaken")); 159 } 159 160 160 161 this.exitClass = exitClass; … … 181 182 } 182 183 183 if (w == window) 184 if (w == window) { 184 185 return weakApplications.get(i); 186 } 185 187 } 186 188 … … 204 206 } 205 207 206 if (maxDepth <= 0) 208 if (maxDepth <= 0) { 207 209 maxDepth = stack.length; 210 } 208 211 209 212 // this needs to be tightened up … … 230 233 // Since we want to deal with JNLPClassLoader, extract it if this 231 234 // is a codebase loader 232 if (cl instanceof JNLPClassLoader.CodeBaseClassLoader) 235 if (cl instanceof JNLPClassLoader.CodeBaseClassLoader) { 233 236 cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader(); 237 } 234 238 235 239 if (cl instanceof JNLPClassLoader) { … … 245 249 * be determined; otherwise returns super.getThreadGroup() 246 250 */ 251 @Override 247 252 public ThreadGroup getThreadGroup() { 248 253 ApplicationInstance app = getApplication(); 249 if (app == null) 254 if (app == null) { 250 255 return super.getThreadGroup(); 256 } 251 257 252 258 return app.getThreadGroup(); … … 258 264 * permission to change the security manager or policy. 259 265 */ 266 @Override 260 267 public void checkPermission(Permission perm) { 261 268 String name = perm.getName(); … … 264 271 // otherwise. 265 272 // if (true) 266 // System.out.println("Checking permission: " + perm.toString());273 // OutputController.getLogger().log("Checking permission: " + perm.toString()); 267 274 268 275 if (!JNLPRuntime.isWebstartApplication() && 269 ("setPolicy".equals(name) || "setSecurityManager".equals(name))) 276 ("setPolicy".equals(name) || "setSecurityManager".equals(name))) { 270 277 throw new SecurityException(R("RCantReplaceSM")); 278 } 271 279 272 280 try { … … 284 292 super.checkPermission(perm); 285 293 } catch (SecurityException ex) { 286 if (JNLPRuntime.isDebug()) { 287 System.out.println("Denying permission: " + perm); 288 } 294 OutputController.getLogger().log("Denying permission: " + perm); 289 295 throw ex; 290 296 } … … 319 325 cl.addPermission(perm); 320 326 if (JNLPRuntime.isDebug()) { 321 if (cl.getPermissions(null).implies(perm)) 322 System.err.println("Added permission: " + perm.toString()); 323 else 324 System.err.println("Unable to add permission: " + perm.toString()); 327 if (cl.getSecurity() == null) { 328 if (cl.getPermissions(null).implies(perm)){ 329 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Added permission: " + perm.toString()); 330 } else { 331 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to add permission: " + perm.toString()); 332 } 333 } else { 334 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Cannot get permissions for null codesource when classloader security is not null"); 335 } 325 336 } 326 337 } else { 327 if (JNLPRuntime.isDebug()) 328 System.err.println("Unable to add permission: " + perm + ", classloader not JNLP."); 338 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Unable to add permission: " + perm + ", classloader not JNLP."); 329 339 } 330 340 } … … 335 345 * be disposed when the calling application exits. 336 346 */ 347 @Override 337 348 public boolean checkTopLevelWindow(Object window) { 338 349 ApplicationInstance app = getApplication(); … … 342 353 Window w = (Window) window; 343 354 344 if (JNLPRuntime.isDebug()) 345 System.err.println("SM: app: " + app.getTitle() + " is adding a window: " + window + " with appContext " + AppContext.getAppContext()); 355 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "SM: app: " + app.getTitle() + " is adding a window: " + window + " with appContext " + AppContext.getAppContext()); 346 356 347 357 weakWindows.add(w); // for mapping window -> app … … 358 368 359 369 /** 360 * Checks whether the caller can exit the system. 370 * Checks whether the caller can exit the system. This method 361 371 * identifies whether the caller is a real call to Runtime.exec 362 372 * and has special behavior when returning from this method … … 365 375 * stopped and its resources destroyed (when possible), and an 366 376 * exception will be thrown to prevent the JVM from shutting 367 * down. <p>368 * 377 * down. 378 * <p> 369 379 * Calls not from Runtime.exit or with no exit class set will 370 380 * behave normally, and the exit class can always exit the JVM. 371 */ 381 * </p> 382 */ 383 @Override 372 384 public void checkExit(int status) { 373 385 … … 375 387 Class stack[] = getClassContext(); 376 388 if (!exitAllowed) { 377 for (int i = 0; i < stack.length; i++) 378 if (stack[i].getClassLoader() != null) 389 for (int i = 0; i < stack.length; i++) { 390 if (stack[i].getClassLoader() != null) { 379 391 throw new AccessControlException("Applets may not call System.exit()"); 392 } 393 } 380 394 } 381 395 … … 384 398 boolean realCall = (stack[1] == Runtime.class); 385 399 386 if (isExitClass(stack)) // either exitClass called or no exitClass set 387 return; // to Runtime.exit or fake call to see if app has permission 400 if (isExitClass(stack)) { 401 return; 402 } // to Runtime.exit or fake call to see if app has permission 388 403 389 404 // not called from Runtime.exit() … … 414 429 * AWTSecurityManager and if so, call this method to give it a chance to 415 430 * return the appropriate appContext based on the application that is 416 * running. <p>417 * 431 * running. 432 * <p> 418 433 * This can be called from any thread (possibly a swing thread) to find out 419 434 * the AppContext for the thread (which may correspond to a particular 420 435 * applet). 436 * </p> 421 437 */ 422 438 @Override … … 445 461 * permission to accesss the AWT event queue. 446 462 */ 463 @Override 447 464 public void checkAwtEventQueueAccess() { 448 465 /* -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/PacEvaluatorFactory.java
r348 r429 44 44 import java.net.URL; 45 45 import java.util.Properties; 46 import net.sourceforge.jnlp.util.logging.OutputController; 46 47 47 48 … … 61 62 properties.load(in); 62 63 } catch (IOException e) { 63 if (JNLPRuntime.isDebug()) { 64 e.printStackTrace(); 65 } 64 OutputController.getLogger().log(e); 66 65 } finally { 67 66 try { 68 67 in.close(); 69 68 } catch (IOException e) { 70 if (JNLPRuntime.isDebug()) { 71 e.printStackTrace(); 72 } 69 OutputController.getLogger().log(e); 73 70 } 74 71 } … … 89 86 // ignore 90 87 } catch (InstantiationException e) { 91 e.printStackTrace();88 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 92 89 } catch (IllegalAccessException e) { 93 e.printStackTrace();90 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 94 91 } catch (NoSuchMethodException e) { 95 e.printStackTrace();92 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 96 93 } catch (IllegalArgumentException e) { 97 e.printStackTrace();94 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 98 95 } catch (InvocationTargetException e) { 99 96 if (e.getCause() != null) { 100 e.getCause().printStackTrace();97 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e.getCause()); 101 98 } 102 99 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/RhinoBasedPacEvaluator.java
r348 r429 49 49 import java.security.PrivilegedAction; 50 50 import java.security.ProtectionDomain; 51 import java.util.PropertyPermission; 52 import net.sourceforge.jnlp.util.logging.OutputController; 51 53 52 54 import net.sourceforge.jnlp.util.TimedHashMap; … … 60 62 * proxy file to find the proxy for a given url. 61 63 * 62 * @see http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file64 * @see <a href="http://en.wikipedia.org/wiki/Proxy_auto-config#The_PAC_file">The PAC File</a> 63 65 */ 64 66 public class RhinoBasedPacEvaluator implements PacEvaluator { … … 75 77 */ 76 78 public RhinoBasedPacEvaluator(URL pacUrl) { 77 if (JNLPRuntime.isDebug()) { 78 System.err.println("Using the Rhino based PAC evaluator for url " + pacUrl); 79 } 79 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Using the Rhino based PAC evaluator for url " + pacUrl); 80 80 pacHelperFunctionContents = getHelperFunctionContents(); 81 81 this.pacUrl = pacUrl; … … 119 119 private String getProxiesWithoutCaching(URL url) { 120 120 if (pacHelperFunctionContents == null) { 121 System.err.println("Error loading pac functions");121 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Error loading pac functions"); 122 122 return "DIRECT"; 123 123 } … … 125 125 EvaluatePacAction evaluatePacAction = new EvaluatePacAction(pacContents, pacUrl.toString(), 126 126 pacHelperFunctionContents, url); 127 128 // Purposefully giving only these permissions rather than using java.policy. The "evaluatePacAction" 129 // isn't supposed to do very much and so doesn't require all the default permissions given by 130 // java.policy 127 131 Permissions p = new Permissions(); 128 132 p.add(new RuntimePermission("accessClassInPackage.org.mozilla.javascript")); 129 133 p.add(new SocketPermission("*", "resolve")); 134 p.add(new PropertyPermission("java.vm.name", "read")); 135 130 136 ProtectionDomain pd = new ProtectionDomain(null, p); 131 137 AccessControlContext context = new AccessControlContext(new ProtectionDomain[] { pd }); … … 145 151 try { 146 152 while ((line = pacReader.readLine()) != null) { 147 // System.out.println(line);153 // OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, line); 148 154 contents = contents.append(line).append("\n"); 149 155 } … … 175 181 contents = new StringBuilder(); 176 182 while ((line = pacFuncsReader.readLine()) != null) { 177 // System.out.println(line);183 // OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL,line); 178 184 contents = contents.append(line).append("\n"); 179 185 } … … 182 188 } 183 189 } catch (IOException e) { 184 e.printStackTrace();190 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 185 191 contents = null; 186 192 } … … 243 249 Object functionObj = scope.get("FindProxyForURL", scope); 244 250 if (!(functionObj instanceof Function)) { 245 System.err.println("FindProxyForURL not found");251 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "FindProxyForURL not found"); 246 252 return null; 247 253 } else { … … 253 259 } 254 260 } catch (Exception e) { 255 e.printStackTrace();261 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 256 262 return "DIRECT"; 257 263 } finally { -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/CertVerifier.java
r348 r429 1 1 /* CertVerifier.java 2 Copyright (C) 20 09Red Hat, Inc.2 Copyright (C) 2012 Red Hat, Inc. 3 3 4 4 This file is part of IcedTea. … … 40 40 import java.security.cert.CertPath; 41 41 import java.security.cert.Certificate; 42 import java.util. ArrayList;42 import java.util.List; 43 43 44 44 /** 45 * An interface that provides various details about a certificate45 * An interface that provides various details about certificates of an app. 46 46 */ 47 47 … … 59 59 60 60 /** 61 * Return if there are signing issues with the certificate (s) being veried61 * Return if there are signing issues with the certificate being verified 62 62 */ 63 public boolean hasSigningIssues( );63 public boolean hasSigningIssues(CertPath certPath); 64 64 65 65 /** 66 * Return if there are no signing issues with this cert (!hasSigningIssues())66 * Get the details regarding issue with this certificate 67 67 */ 68 public boolean noSigningIssues();68 public List<String> getDetails(CertPath certPath); 69 69 70 70 /** 71 * Get the details regarding issue(s) with this certificate 72 */ 73 public ArrayList<String> getDetails(); 74 75 /** 76 * Return a valid certificate path to this certificate(s) being verified 71 * Return a valid certificate path to this certificate being verified 77 72 * @return The CertPath 78 73 */ 79 public CertPath getCertPath( );74 public CertPath getCertPath(CertPath certPath); 80 75 81 76 /** 82 77 * Returns the application's publisher's certificate. 83 78 */ 84 public abstract Certificate getPublisher( );79 public abstract Certificate getPublisher(CertPath certPath); 85 80 86 81 /** 87 82 * Returns the application's root's certificate. This 88 * may return the same certificate as getPublisher( ) in83 * may return the same certificate as getPublisher(CertPath certPath) in 89 84 * the event that the application is self signed. 90 85 */ 91 public abstract Certificate getRoot(); 92 86 public abstract Certificate getRoot(CertPath certPath); 93 87 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/CertificateUtils.java
r418 r429 46 46 import java.io.PrintStream; 47 47 import java.math.BigInteger; 48 import java.security.InvalidKeyException;49 48 import java.security.Key; 50 49 import java.security.KeyStore; 51 50 import java.security.KeyStoreException; 52 import java.security.NoSuchAlgorithmException;53 import java.security.NoSuchProviderException;54 import java.security.SignatureException;55 51 import java.security.cert.Certificate; 56 52 import java.security.cert.CertificateException; … … 60 56 import java.util.Random; 61 57 62 import net.sourceforge.jnlp.runtime.JNLPRuntime;63 58 import net.sourceforge.jnlp.runtime.Translator; 59 import net.sourceforge.jnlp.util.logging.OutputController; 64 60 import net.sourceforge.jnlp.util.replacements.BASE64Encoder; 65 61 import sun.security.provider.X509Factory; … … 78 74 public static final void addToKeyStore(File file, KeyStore ks) throws CertificateException, 79 75 IOException, KeyStoreException { 80 if (JNLPRuntime.isDebug()) { 81 System.out.println("Importing certificate from " + file + " into " + ks); 82 } 76 77 OutputController.getLogger().log("Importing certificate from " + file + " into " + ks); 83 78 84 79 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); … … 101 96 public static final void addToKeyStore(X509Certificate cert, KeyStore ks) 102 97 throws KeyStoreException { 103 if (JNLPRuntime.isDebug()) { 104 System.out.println("Importing " + cert.getSubjectX500Principal().getName()); 105 } 98 99 OutputController.getLogger().log("Importing " + cert.getSubjectX500Principal().getName()); 106 100 107 101 String alias = null; … … 174 168 175 169 if (c.equals(keyStores[i].getCertificate(alias))) { 176 if (JNLPRuntime.isDebug()) { 177 System.out.println(Translator.R("LCertFoundIn", c.getSubjectX500Principal().getName(), KeyStores.getPathToKeystore(keyStores[i].hashCode()))); 178 } 179 170 OutputController.getLogger().log(Translator.R("LCertFoundIn", c.getSubjectX500Principal().getName(), KeyStores.getPathToKeystore(keyStores[i].hashCode()))); 180 171 return true; 181 172 } // else continue … … 183 174 184 175 } catch (KeyStoreException e) { 185 e.printStackTrace();176 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 186 177 // continue 187 178 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java
r348 r429 53 53 import java.util.Collection; 54 54 import java.util.List; 55 import net.sourceforge.jnlp.util.logging.OutputController; 55 56 56 57 import sun.security.util.DerValue; … … 60 61 public class HttpsCertVerifier implements CertVerifier { 61 62 62 private VariableX509TrustManager tm;63 63 private X509Certificate[] chain; 64 64 private String authType; … … 68 68 private ArrayList<String> details = new ArrayList<String>(); 69 69 70 public HttpsCertVerifier(VariableX509TrustManager tm, 71 X509Certificate[] chain, String authType, 70 public HttpsCertVerifier(X509Certificate[] chain, String authType, 72 71 boolean isTrusted, boolean hostMatched, 73 72 String hostName) { 74 this.tm = tm;75 73 this.chain = chain; 76 74 this.authType = authType; … … 80 78 } 81 79 80 @Override 82 81 public boolean getAlreadyTrustPublisher() { 83 82 return isTrusted; 84 83 } 85 84 86 public CertPath getCertPath() { 85 86 /* XXX: Most of these methods have a CertPath param that should be passed 87 * from the UI dialogs. However, this is not implemented yet so most of 88 * the params are ignored. 89 */ 90 91 @Override 92 public CertPath getCertPath(CertPath certPath) { // Parameter ignored. 87 93 88 94 ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(); … … 95 101 certPaths.add(CertificateFactory.getInstance("X.509").generateCertPath(list)); 96 102 } catch (CertificateException ce) { 97 ce.printStackTrace();103 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ce); 98 104 99 105 // carry on … … 103 109 } 104 110 105 public ArrayList<String> getDetails() { 111 @Override 112 public List<String> getDetails(CertPath certPath) { // Parameter ignored. 106 113 107 114 boolean hasExpiredCert = false; … … 183 190 184 191 } catch (CertificateParsingException cpe) { 185 cpe.printStackTrace();192 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, cpe); 186 193 } catch (IOException ioe) { 187 ioe.printStackTrace();194 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ioe); 188 195 } 189 196 … … 196 203 } 197 204 198 public Certificate getPublisher() { 205 @Override 206 public Certificate getPublisher(CertPath certPath) { // Paramater ignored. 199 207 if (chain.length > 0) 200 208 return (Certificate) chain[0]; … … 202 210 } 203 211 204 public Certificate getRoot() { 212 @Override 213 public Certificate getRoot(CertPath certPath) { // Parameter ignored. 205 214 if (chain.length > 0) 206 215 return (Certificate) chain[chain.length - 1]; … … 211 220 try { 212 221 KeyStore[] caCertsKeyStores = KeyStores.getCAKeyStores(); 213 return CertificateUtils.inKeyStores((X509Certificate) getRoot( ), caCertsKeyStores);222 return CertificateUtils.inKeyStores((X509Certificate) getRoot(null), caCertsKeyStores); 214 223 } catch (Exception e) { 215 224 } … … 217 226 } 218 227 219 public boolean hasSigningIssues() { 228 @Override 229 public boolean hasSigningIssues(CertPath certPath) { 220 230 return false; 221 231 } 222 223 public boolean noSigningIssues() {224 return false;225 }226 227 232 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/KeyStores.java
r418 r429 56 56 import net.sourceforge.jnlp.runtime.Translator; 57 57 import net.sourceforge.jnlp.util.FileUtils; 58 import net.sourceforge.jnlp.util.logging.OutputController; 58 59 59 60 /** 60 * The <code>KeyStores</code>class allows easily accessing the various KeyStores61 * The {@code KeyStores} class allows easily accessing the various KeyStores 61 62 * used. 62 63 */ … … 86 87 private static final String DEFAULT_PASSWORD = "changeit"; 87 88 88 public static finalchar[] getPassword() {89 public static char[] getPassword() { 89 90 return DEFAULT_PASSWORD.toCharArray(); 90 91 } … … 142 143 keystoresPaths.put(ks.hashCode(),location); 143 144 } catch (Exception e) { 144 e.printStackTrace();145 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 145 146 } 146 147 return ks; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialog.java
r418 r429 38 38 package net.sourceforge.jnlp.security; 39 39 40 import java.awt.BorderLayout; 41 import java.awt.event.ActionListener; 42 import java.awt.event.WindowAdapter; 43 import java.awt.event.WindowEvent; 44 import java.security.cert.X509Certificate; 45 import java.util.List; 46 import java.util.concurrent.CopyOnWriteArrayList; 47 48 import javax.swing.JDialog; 49 40 50 import net.sourceforge.jnlp.JNLPFile; 41 import net.sourceforge.jnlp.runtime.JNLP Runtime;51 import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; 42 52 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 43 53 import net.sourceforge.jnlp.security.SecurityDialogs.DialogType; 54 import net.sourceforge.jnlp.security.dialogs.AccessWarningPane; 55 import net.sourceforge.jnlp.security.dialogs.AppletWarningPane; 56 import net.sourceforge.jnlp.security.dialogs.CertWarningPane; 57 import net.sourceforge.jnlp.security.dialogs.CertsInfoPane; 58 import net.sourceforge.jnlp.security.dialogs.MatchingALACAttributePanel; 59 import net.sourceforge.jnlp.security.dialogs.MissingALACAttributePanel; 60 import net.sourceforge.jnlp.security.dialogs.MissingPermissionsAttributePanel; 61 import net.sourceforge.jnlp.security.dialogs.MoreInfoPane; 62 import net.sourceforge.jnlp.security.dialogs.PasswordAuthenticationPane; 63 import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; 64 import net.sourceforge.jnlp.security.dialogs.SingleCertInfoPane; 65 import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningDialog; 44 66 import net.sourceforge.jnlp.util.ImageResources; 45 46 import java.awt.*; 47 48 import javax.swing.*; 49 50 import java.awt.event.*; 51 import java.security.cert.X509Certificate; 52 import java.util.concurrent.CopyOnWriteArrayList; 53 54 import java.util.List; 67 import net.sourceforge.jnlp.util.ScreenFinder; 68 import net.sourceforge.jnlp.util.logging.OutputController; 55 69 56 70 /** … … 214 228 215 229 private void initDialog() { 216 setSystemLookAndFeel();217 218 230 String dialogTitle = ""; 219 231 if (dialogType == DialogType.CERT_WARNING) { … … 230 242 else if (dialogType == DialogType.APPLET_WARNING) 231 243 dialogTitle = "Applet Warning"; 232 else if (dialogType == DialogType. NOTALLSIGNED_WARNING)244 else if (dialogType == DialogType.PARTIALLYSIGNED_WARNING) 233 245 dialogTitle = "Security Warning"; 234 246 else if (dialogType == DialogType.AUTHENTICATION) … … 243 255 244 256 pack(); 257 centerDialog(this); 245 258 246 259 WindowAdapter adapter = new WindowAdapter() { … … 261 274 SecurityDialog dialog = (SecurityDialog) e.getSource(); 262 275 dialog.setResizable(true); 263 centerDialog(dialog);264 276 dialog.setValue(null); 265 277 } … … 268 280 addWindowListener(adapter); 269 281 addWindowFocusListener(adapter); 270 271 282 } 272 283 … … 293 304 294 305 if (dialogType == DialogType.CERT_WARNING) 295 panel = new CertWarningPane(this, this.certVerifier );306 panel = new CertWarningPane(this, this.certVerifier, (SecurityDelegate) extras[0]); 296 307 else if (dialogType == DialogType.MORE_INFO) 297 308 panel = new MoreInfoPane(this, this.certVerifier); … … 304 315 else if (dialogType == DialogType.APPLET_WARNING) 305 316 panel = new AppletWarningPane(this, this.certVerifier); 306 else if (dialogType == DialogType.NOTALLSIGNED_WARNING) 307 panel = new NotAllSignedWarningPane(this); 317 else if (dialogType == DialogType.PARTIALLYSIGNED_WARNING) 318 panel = AppTrustWarningDialog.partiallySigned(this, file, (SecurityDelegate) extras[0]); 319 else if (dialogType == DialogType.UNSIGNED_WARNING) // Only necessary for applets on 'high security' or above 320 panel = AppTrustWarningDialog.unsigned(this, file); 308 321 else if (dialogType == DialogType.AUTHENTICATION) 309 322 panel = new PasswordAuthenticationPane(this, extras); 323 else if (dialogType == DialogType.UNSIGNED_EAS_NO_PERMISSIONS_WARNING) 324 panel = new MissingPermissionsAttributePanel(this, (String) extras[0], (String) extras[1]); 325 else if (dialogType == DialogType.MISSING_ALACA) 326 panel = new MissingALACAttributePanel(this, (String) extras[0], (String) extras[1], (String) extras[2]); 327 else if (dialogType == DialogType.MATCHING_ALACA) 328 panel = new MatchingALACAttributePanel(this, (String) extras[0], (String) extras[1], (String) extras[2]); 310 329 311 330 add(panel, BorderLayout.CENTER); … … 313 332 314 333 private static void centerDialog(JDialog dialog) { 315 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 316 Dimension dialogSize = dialog.getSize(); 317 318 dialog.setLocation((screen.width - dialogSize.width) / 2, 319 (screen.height - dialogSize.height) / 2); 334 ScreenFinder.centerWindowsToCurrentScreen(dialog); 320 335 } 321 336 322 337 private void selectDefaultButton() { 323 338 if (panel == null) { 324 System.out.println("initial value panel is null");339 OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "initial value panel is null"); 325 340 } 326 341 panel.requestFocusOnDefaultButton(); 327 342 } 328 343 329 protected void setValue(Object value) { 330 if (JNLPRuntime.isDebug()) { 331 System.out.println("Setting value:" + value); 332 } 344 public void setValue(Object value) { 345 OutputController.getLogger().log("Setting value:" + value); 333 346 this.value = value; 334 347 } 335 348 336 349 public Object getValue() { 337 if (JNLPRuntime.isDebug()) { 338 System.out.println("Returning value:" + value); 339 } 350 OutputController.getLogger().log("Returning value:" + value); 340 351 return value; 341 352 } … … 351 362 } 352 363 353 /**354 * Updates the look and feel of the window to be the system look and feel355 */356 protected void setSystemLookAndFeel() {357 try {358 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());359 } catch (Exception e) {360 //don't worry if we can't.361 }362 }363 364 364 private final List<ActionListener> listeners = new CopyOnWriteArrayList<ActionListener>(); 365 365 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java
r348 r429 1 /* SecurityDialogMessage.java 2 Copyright (C) 2011 Red Hat, Inc. 3 4 This file is part of IcedTea. 5 6 IcedTea is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 2. 9 10 IcedTea is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with IcedTea; see the file COPYING. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 02110-1301 USA. 19 20 Linking this library statically or dynamically with other modules is 21 making a combined work based on this library. Thus, the terms and 22 conditions of the GNU General Public License cover the whole 23 combination. 24 25 As a special exception, the copyright holders of this library give you 26 permission to link this library with independent modules to produce an 27 executable, regardless of the license terms of these independent 28 modules, and to copy and distribute the resulting executable under 29 terms of your choice, provided that you also meet, for each linked 30 independent module, the terms and conditions of the license of that 31 module. An independent module is a module which is not derived from 32 or based on this library. If you modify this library, you may extend 33 this exception to your version of the library, but you are not 34 obligated to do so. If you do not wish to do so, delete this 35 exception statement from your version. 36 */ 37 1 38 package net.sourceforge.jnlp.security; 2 39 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java
r348 r429 45 45 import sun.awt.AppContext; 46 46 47 import net.sourceforge.jnlp. runtime.JNLPRuntime;47 import net.sourceforge.jnlp.util.logging.OutputController; 48 48 49 49 /** … … 56 56 * their Look and Feel is not affected by the Look and Feel of the 57 57 * applet/application. 58 * </p> 58 59 * <p> 59 60 * This class contains allows a client application to post a … … 61 62 * the queue, it shows a security warning to the user, and sets 62 63 * {@link SecurityDialogMessage#userResponse} to the appropriate value. 64 * </p> 63 65 */ 64 66 public final class SecurityDialogMessageHandler implements Runnable { … … 73 75 @Override 74 76 public void run() { 75 if (JNLPRuntime.isDebug()) { 76 System.out.println("Starting security dialog thread"); 77 } 77 OutputController.getLogger().log("Starting security dialog thread"); 78 78 while (true) { 79 79 try { … … 92 92 * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and 93 93 * {@link SecurityDialogMessage#lock} (in not null) is released. 94 * </p> 94 95 * 95 96 * @param message the message indicating what type of security dialog to … … 128 129 * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and 129 130 * {@link SecurityDialogMessage#lock} (in not null) is released. 131 * </p> 130 132 * 131 133 * @param message indicates the type of security dialog to show … … 135 137 queue.put(message); 136 138 } catch (InterruptedException e) { 137 e.printStackTrace();139 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 138 140 } 139 141 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialogs.java
r418 r429 42 42 import java.awt.event.WindowEvent; 43 43 import java.net.NetPermission; 44 import java.net.URL; 44 45 import java.security.AccessController; 45 46 import java.security.PrivilegedAction; 47 import java.util.Set; 46 48 import java.util.concurrent.Semaphore; 47 49 … … 51 53 import net.sourceforge.jnlp.JNLPFile; 52 54 import net.sourceforge.jnlp.config.DeploymentConfiguration; 55 import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; 53 56 import net.sourceforge.jnlp.runtime.JNLPRuntime; 57 import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction; 58 import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.AppTrustWarningPanel.AppSigningWarningAction; 59 import net.sourceforge.jnlp.util.UrlUtils; 54 60 55 61 /** 56 * A factory for showing many possible types of security warning to the user.<p> 57 * 62 * <p> 63 * A factory for showing many possible types of security warning to the user. 64 * </p> 65 * <p> 58 66 * This contains all the public methods that classes outside this package should 59 67 * use instead of using {@link SecurityDialog} directly. 60 * 68 * </p> 69 * <p> 61 70 * All of these methods post a message to the 62 71 * {@link SecurityDialogMessageHandler} and block waiting for a response. 72 * </p> 63 73 */ 64 74 public class SecurityDialogs { … … 70 80 SINGLE_CERT_INFO, 71 81 ACCESS_WARNING, 72 NOTALLSIGNED_WARNING, 82 PARTIALLYSIGNED_WARNING, 83 UNSIGNED_WARNING, /* requires confirmation with 'high-security' setting */ 73 84 APPLET_WARNING, 74 85 AUTHENTICATION, 86 UNSIGNED_EAS_NO_PERMISSIONS_WARNING, /* when Extended applet security is at High Security and no permission attribute is find, */ 87 MISSING_ALACA, /*alaca - Application-Library-Allowable-Codebase Attribute*/ 88 MATCHING_ALACA 75 89 } 76 90 … … 86 100 VERIFIED, 87 101 UNVERIFIED, 88 NOTALLSIGNED, 102 PARTIALLYSIGNED, 103 UNSIGNED, /* requires confirmation with 'high-security' setting */ 89 104 SIGNING_ERROR 105 } 106 107 public static enum AppletAction { 108 RUN, 109 SANDBOX, 110 CANCEL; 111 public static AppletAction fromInteger(int i) { 112 switch (i) { 113 case 0: 114 return RUN; 115 case 1: 116 return SANDBOX; 117 case 2: 118 return CANCEL; 119 default: 120 return CANCEL; 121 } 122 } 90 123 } 91 124 … … 128 161 Object selectedValue = getUserResponse(message); 129 162 130 if (selectedValue == null) { 131 return false; 132 } else if (selectedValue instanceof Integer) { 133 if (((Integer) selectedValue).intValue() == 0) 134 return true; 135 else 136 return false; 137 } else { 138 return false; 139 } 140 } 141 142 /** 143 * Shows a warning dialog for when the main application jars are signed, 144 * but extensions aren't 163 return getIntegerResponseAsBoolean(selectedValue); 164 } 165 166 /** 167 * Shows a warning dialog for when a plugin applet is unsigned. 168 * This is used with 'high-security' setting. 145 169 * 146 170 * @return true if permission was granted by the user, false otherwise. 147 171 */ 148 public static boolean showNotAllSignedWarningDialog(JNLPFile file) {149 150 if (!shouldPromptUser()) { 151 return false;172 public static AppSigningWarningAction showUnsignedWarningDialog(JNLPFile file) { 173 174 if (!shouldPromptUser()) { 175 return new AppSigningWarningAction(ExecuteAppletAction.NO, false); 152 176 } 153 177 154 178 final SecurityDialogMessage message = new SecurityDialogMessage(); 155 message.dialogType = DialogType. NOTALLSIGNED_WARNING;156 message.accessType = AccessType. NOTALLSIGNED;179 message.dialogType = DialogType.UNSIGNED_WARNING; 180 message.accessType = AccessType.UNSIGNED; 157 181 message.file = file; 158 message.extras = new Object[0]; 159 160 Object selectedValue = getUserResponse(message); 161 162 if (selectedValue == null) { 163 return false; 164 } else if (selectedValue instanceof Integer) { 165 if (((Integer) selectedValue).intValue() == 0) { 166 return true; 167 } else { 168 return false; 169 } 170 } else { 171 return false; 172 } 182 183 return (AppSigningWarningAction) getUserResponse(message); 173 184 } 174 185 175 186 /** 176 187 * Shows a security warning dialog according to the specified type of 177 * access. If <code>type</code> is one of AccessType.VERIFIEDor178 * AccessType.UNVERIFIED, extra details will be available with regards179 * to code signing and signing certificates.188 * access. If {@code accessType} is one of {@link AccessType#VERIFIED} or 189 * {@link AccessType#UNVERIFIED}, extra details will be available with 190 * regards to code signing and signing certificates. 180 191 * 181 192 * @param accessType the type of warning dialog to show … … 183 194 * @param certVerifier the JarCertVerifier used to verify this application 184 195 * 185 * @return true if the user accepted the certificate 186 */ 187 public static boolean showCertWarningDialog(AccessType accessType, 188 JNLPFile file, CertVerifier certVerifier) { 189 190 if (!shouldPromptUser()) { 191 return false; 196 * @return RUN if the user accepted the certificate, SANDBOX if the user 197 * wants the applet to run with only sandbox permissions, or CANCEL if the 198 * user did not accept running the applet 199 */ 200 public static AppletAction showCertWarningDialog(AccessType accessType, 201 JNLPFile file, CertVerifier certVerifier, SecurityDelegate securityDelegate) { 202 203 if (!shouldPromptUser()) { 204 return AppletAction.CANCEL; 192 205 } 193 206 … … 197 210 message.file = file; 198 211 message.certVerifier = certVerifier; 212 message.extras = new Object[] { securityDelegate }; 199 213 200 214 Object selectedValue = getUserResponse(message); 201 215 202 if (selectedValue == null) { 203 return false; 204 } else if (selectedValue instanceof Integer) { 205 if (((Integer) selectedValue).intValue() == 0) 206 return true; 207 else 208 return false; 209 } else { 210 return false; 211 } 216 return getIntegerResponseAsAppletAction(selectedValue); 217 } 218 219 /** 220 * Shows a warning dialog for when an applet or application is partially signed. 221 * 222 * @return true if permission was granted by the user, false otherwise. 223 */ 224 public static AppSigningWarningAction showPartiallySignedWarningDialog(JNLPFile file, CertVerifier certVerifier, 225 SecurityDelegate securityDelegate) { 226 227 if (!shouldPromptUser()) { 228 return new AppSigningWarningAction(ExecuteAppletAction.NO, false); 229 } 230 231 final SecurityDialogMessage message = new SecurityDialogMessage(); 232 message.dialogType = DialogType.PARTIALLYSIGNED_WARNING; 233 message.accessType = AccessType.PARTIALLYSIGNED; 234 message.file = file; 235 message.certVerifier = certVerifier; 236 message.extras = new Object[] { securityDelegate }; 237 238 return (AppSigningWarningAction) getUserResponse(message); 212 239 } 213 240 … … 239 266 240 267 Object response = getUserResponse(message); 241 if (response == null) { 242 return null; 243 } else { 244 return (Object[]) response; 245 } 246 } 247 268 return (Object[]) response; 269 } 270 271 public static boolean showMissingALACAttributePanel(String title, URL codeBase, Set<URL> remoteUrls) { 272 273 if (!shouldPromptUser()) { 274 return false; 275 } 276 277 SecurityDialogMessage message = new SecurityDialogMessage(); 278 message.dialogType = DialogType.MISSING_ALACA; 279 message.extras = new Object[]{title, codeBase.toString(), UrlUtils.setOfUrlsToHtmlList(remoteUrls)}; 280 Object selectedValue = getUserResponse(message); 281 return getIntegerResponseAsBoolean(selectedValue); 282 } 283 284 public static boolean showMatchingALACAttributePanel(String title, URL codeBase, Set<URL> remoteUrls) { 285 286 if (!shouldPromptUser()) { 287 return false; 288 } 289 290 SecurityDialogMessage message = new SecurityDialogMessage(); 291 message.dialogType = DialogType.MATCHING_ALACA; 292 message.extras = new Object[]{title, codeBase.toString(), UrlUtils.setOfUrlsToHtmlList(remoteUrls)}; 293 Object selectedValue = getUserResponse(message); 294 return getIntegerResponseAsBoolean(selectedValue); 295 } 296 248 297 /** 249 298 * FIXME This is unused. Remove it? 250 * @return (0, 1, 2) = >(Yes, No, Cancel)299 * @return (0, 1, 2) => (Yes, No, Cancel) 251 300 */ 252 301 public static int showAppletWarning() { … … 262 311 263 312 // result 0 = Yes, 1 = No, 2 = Cancel 264 if (selectedValue == null) { 265 return 2; 266 } else if (selectedValue instanceof Integer) { 313 if (selectedValue instanceof Integer) { 314 // If the selected value can be cast to Integer, use that value 267 315 return ((Integer) selectedValue).intValue(); 268 316 } else { 317 // Otherwise default to "cancel" 269 318 return 2; 270 319 } 271 320 } 272 321 322 public static boolean showMissingPermissionsAttributeDialogue(String title, URL codeBase) { 323 324 if (!shouldPromptUser()) { 325 return false; 326 } 327 328 SecurityDialogMessage message = new SecurityDialogMessage(); 329 message.dialogType = DialogType.UNSIGNED_EAS_NO_PERMISSIONS_WARNING; 330 message.extras = new Object[]{title, codeBase.toExternalForm()}; 331 Object selectedValue = getUserResponse(message); 332 return SecurityDialogs.getIntegerResponseAsBoolean(selectedValue); 333 } 273 334 /** 274 335 * Posts the message to the SecurityThread and gets the response. Blocks … … 352 413 353 414 /** 415 * Returns true iff the given Object reference can be cast to Integer and that Integer's 416 * intValue is 0. 417 * @param ref the Integer (hopefully) reference 418 * @return whether the given reference is both an Integer type and has intValue of 0 419 */ 420 public static boolean getIntegerResponseAsBoolean(Object ref) { 421 boolean isInteger = ref instanceof Integer; 422 if (isInteger) { 423 Integer i = (Integer) ref; 424 return i.intValue() == 0; 425 } 426 return false; 427 } 428 429 public static AppletAction getIntegerResponseAsAppletAction(Object ref) { 430 if (ref instanceof Integer) { 431 return AppletAction.fromInteger((Integer) ref); 432 } 433 return AppletAction.CANCEL; 434 } 435 436 /** 354 437 * Returns whether the current runtime configuration allows prompting user 355 438 * for security warnings. … … 366 449 }); 367 450 } 368 451 369 452 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityUtil.java
r348 r429 45 45 import net.sourceforge.jnlp.security.KeyStores.Level; 46 46 import net.sourceforge.jnlp.security.KeyStores.Type; 47 import net.sourceforge.jnlp.util.logging.OutputController; 47 48 48 49 public class SecurityUtil { … … 211 212 } 212 213 } catch (Exception e) { 213 e.printStackTrace();214 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 214 215 throw e; 215 216 } finally { -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
r418 r429 38 38 package net.sourceforge.jnlp.security; 39 39 40 import java.lang.reflect.InvocationTargetException; 41 import java.lang.reflect.Method; 42 import java.net.Socket; 40 43 import java.security.AccessController; 41 44 import java.security.KeyStore; … … 48 51 import java.util.List; 49 52 53 import javax.net.ssl.SSLEngine; 54 import javax.net.ssl.SSLSocket; 50 55 import javax.net.ssl.TrustManager; 51 56 import javax.net.ssl.TrustManagerFactory; 52 57 import javax.net.ssl.X509TrustManager; 53 58 59 import net.sourceforge.jnlp.runtime.JNLPRuntime; 60 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 61 import net.sourceforge.jnlp.security.SecurityDialogs.AppletAction; 62 import net.sourceforge.jnlp.util.logging.OutputController; 54 63 import sun.security.util.HostnameChecker; 55 64 import sun.security.validator.ValidatorException; 56 57 import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;58 import net.sourceforge.jnlp.runtime.JNLPRuntime;59 60 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType;61 65 62 66 /** … … 66 70 */ 67 71 68 final public class VariableX509TrustManager extends X509ExtendedTrustManager{72 final public class VariableX509TrustManager { 69 73 70 74 /** TrustManagers containing trusted CAs */ … … 109 113 } 110 114 } catch (Exception e) { 111 e.printStackTrace();115 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 112 116 } 113 117 … … 134 138 } 135 139 } catch (Exception e) { 136 e.printStackTrace();140 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 137 141 } 138 142 … … 158 162 } 159 163 } catch (Exception e) { 160 e.printStackTrace();164 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 161 165 } 162 166 } … … 165 169 * Check if client is trusted (no support for custom here, only system/user) 166 170 */ 167 public void check ClientTrusted(X509Certificate[] chain, String authType,168 String hostName , String algorithm)171 public void checkTrustClient(X509Certificate[] chain, String authType, 172 String hostName) 169 173 throws CertificateException { 170 174 … … 187 191 } 188 192 189 public void checkClientTrusted(X509Certificate[] chain, String authType) 190 throws CertificateException { 191 checkClientTrusted(chain, authType, null, null); 192 } 193 194 public void checkServerTrusted(X509Certificate[] chain, String authType, 195 String hostName, String algorithm) 196 throws CertificateException { 197 checkServerTrusted(chain, authType, hostName, false); 198 } 199 200 public void checkServerTrusted(X509Certificate[] chain, String authType) 201 throws CertificateException { 202 checkServerTrusted(chain, authType, null, null); 203 } 204 205 /** 206 * Check if the server is trusted 193 /** 194 * Check if the server is trusted. 195 * 196 * First, existing stores are checked to see if the certificate is trusted. 197 * Next, if the certificate is not explicitly trusted by the user, a host 198 * name check is performed. The user is them prompted as needed. 207 199 * 208 200 * @param chain The cert chain 209 201 * @param authType The auth type algorithm 210 * @param checkOnly Whether to "check only" i.e. no user prompt, or to prompt for permission 211 */ 212 public synchronized void checkServerTrusted(X509Certificate[] chain, 202 * @param hostName The expected hostName that the server should have 203 * @param socket The SSLSocket in use (may be null) 204 * @param engine The SSLEngine in use (may be null) 205 */ 206 public synchronized void checkTrustServer(X509Certificate[] chain, 213 207 String authType, String hostName, 214 boolean checkOnly) throws CertificateException {208 SSLSocket socket, SSLEngine engine) throws CertificateException { 215 209 CertificateException ce = null; 216 210 boolean trusted = true; 217 boolean CNMatched = true; 218 211 boolean CNMatched = false; 212 213 // Check trust stores 219 214 try { 220 checkAllManagers(chain, authType );215 checkAllManagers(chain, authType, socket, engine); 221 216 } catch (CertificateException e) { 222 217 trusted = false; … … 225 220 226 221 // If the certificate is not explicitly trusted, we 227 // need to prompt the user222 // check host match 228 223 if (!isExplicitlyTrusted(chain, authType)) { 229 230 if (hostName == null) { 231 CNMatched = false; 232 } else { 224 if (hostName != null) { 233 225 try { 234 226 HostnameChecker checker = HostnameChecker 235 227 .getInstance(HostnameChecker.TYPE_TLS); 236 228 237 checker.match(hostName, chain[0]); // only need to match @ 0 for 238 // CN 239 229 checker.match(hostName, chain[0]); // only need to match @ 0 for CN 230 231 CNMatched = true; 240 232 } catch (CertificateException e) { 241 CNMatched = false;242 233 ce = e; 243 234 } 244 235 } 245 } 246 236 } else { 237 // If it is explicitly trusted, just return right away. 238 return; 239 } 240 241 // If it is (not explicitly trusted) AND 242 // ((it is not in store) OR (there is a host mismatch)) 247 243 if (!trusted || !CNMatched) { 248 if (checkOnly) { 249 throw ce; 250 } else { 251 if (!isTemporarilyUntrusted(chain[0])) { 252 boolean b = askUser(chain, authType, trusted, CNMatched, hostName); 253 254 if (b) { 255 temporarilyTrust(chain[0]); 256 } else { 257 temporarilyUntrust(chain[0]); 258 } 259 } 260 261 checkAllManagers(chain, authType); 262 } 263 } 264 } 265 266 /** 267 * Check system, user and custom trust manager 268 */ 269 private void checkAllManagers(X509Certificate[] chain, String authType) throws CertificateException { 244 if (!isTemporarilyUntrusted(chain[0])) { 245 boolean b = askUser(chain, authType, trusted, CNMatched, hostName); 246 247 if (b) { 248 temporarilyTrust(chain[0]); 249 return; 250 } else { 251 temporarilyUntrust(chain[0]); 252 } 253 } 254 255 throw ce; 256 } 257 } 258 259 /** 260 * Check system, user and custom trust manager. 261 * 262 * This method is intended to work with both, JRE6 and JRE7. If socket 263 * and engine are null, it assumes that the call is for JRE6 (i.e. not 264 * javax.net.ssl.X509ExtendedTrustManager which is Java 7 specific). If 265 * either of those are not null, it will assume that the caTrustManagers 266 * are javax.net.ssl.X509ExtendedTrustManager instances and will 267 * invoke their check methods. 268 * 269 * @param chain The certificate chain 270 * @param authType The authentication type 271 * @param socket the SSLSocket being used for the connection 272 * @param engine the SSLEngine being used for the connection 273 */ 274 private void checkAllManagers(X509Certificate[] chain, String authType, Socket socket, SSLEngine engine) throws CertificateException { 275 270 276 // first try CA TrustManagers 271 277 boolean trusted = false; … … 273 279 for (int i = 0; i < caTrustManagers.length; i++) { 274 280 try { 275 caTrustManagers[i].checkServerTrusted(chain, authType); 281 if (socket == null && engine == null) { 282 caTrustManagers[i].checkServerTrusted(chain, authType); 283 } else { 284 285 try { 286 Class<?> x509ETMClass = Class.forName("javax.net.ssl.X509ExtendedTrustManager"); 287 if (engine == null) { 288 Method mcheckServerTrusted = x509ETMClass.getDeclaredMethod("checkServerTrusted", X509Certificate[].class, String.class, Socket.class); 289 mcheckServerTrusted.invoke(caTrustManagers[i], chain, authType, socket); 290 } else { 291 Method mcheckServerTrusted = x509ETMClass.getDeclaredMethod("checkServerTrusted", X509Certificate[].class, String.class, SSLEngine.class); 292 mcheckServerTrusted.invoke(caTrustManagers[i], chain, authType, engine); 293 } 294 } catch (NoSuchMethodException nsme) { 295 throw new ValidatorException(nsme.getMessage()); 296 } catch (InvocationTargetException ite) { 297 throw new ValidatorException(ite.getMessage()); 298 } catch (IllegalAccessException iae) { 299 throw new ValidatorException(iae.getMessage()); 300 } catch (ClassNotFoundException cnfe) { 301 throw new ValidatorException(cnfe.getMessage()); 302 } 303 } 304 276 305 trusted = true; 277 306 break; … … 280 309 } 281 310 } 311 282 312 if (trusted) { 283 313 return; … … 301 331 if (!temporarilyTrusted.contains(chain[0])) { 302 332 if (savedException == null) { 303 // System.out.println("IMPOSSIBLE!");333 // OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, "IMPOSSIBLE!"); 304 334 throw new ValidatorException(ValidatorException.T_SIGNATURE_ERROR, chain[0]); 305 335 } … … 333 363 } 334 364 335 p ublicX509Certificate[] getAcceptedIssuers() {365 protected X509Certificate[] getAcceptedIssuers() { 336 366 List<X509Certificate> issuers = new ArrayList<X509Certificate>(); 337 367 … … 389 419 return true; 390 420 } 391 final VariableX509TrustManager trustManager = this;392 421 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 393 422 @Override … … 395 424 return SecurityDialogs.showCertWarningDialog( 396 425 AccessType.UNVERIFIED, null, 397 new HttpsCertVerifier( trustManager,chain, authType,426 new HttpsCertVerifier(chain, authType, 398 427 isTrusted, hostMatched, 399 hostName));428 hostName), null) == AppletAction.RUN; 400 429 } 401 430 }); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
r418 r429 81 81 import net.sourceforge.jnlp.security.KeyStores.Level; 82 82 import net.sourceforge.jnlp.util.FileUtils; 83 import net.sourceforge.jnlp.util.logging.OutputController; 83 84 84 85 public class CertificatePane extends JPanel { … … 151 152 keyStore = KeyStores.getKeyStore(currentKeyStoreLevel, currentKeyStoreType); 152 153 } catch (Exception e) { 153 e.printStackTrace();154 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 154 155 } 155 156 } 156 157 157 158 //create the GUI here. 158 pr otectedvoid addComponents() {159 private void addComponents() { 159 160 160 161 JPanel main = new JPanel(new BorderLayout()); … … 264 265 while (aliases.hasMoreElements()) { 265 266 Certificate c = keyStore.getCertificate(aliases.nextElement()); 266 if (c instanceof X509Certificate) 267 if (c instanceof X509Certificate) { 267 268 certs.add((X509Certificate) c); 269 } 268 270 } 269 271 … … 279 281 } catch (Exception e) { 280 282 //TODO 281 e.printStackTrace();283 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 282 284 } 283 285 } … … 310 312 JOptionPane.OK_CANCEL_OPTION, 311 313 JOptionPane.INFORMATION_MESSAGE); 312 if (result == JOptionPane.OK_OPTION) 314 if (result == JOptionPane.OK_OPTION) { 313 315 return jpf.getPassword(); 314 else 316 } 317 else { 315 318 return null; 319 } 316 320 } 317 321 … … 328 332 } 329 333 334 @Override 330 335 public String toString() { 331 336 return KeyStores.toDisplayableString(null, type); … … 336 341 private class CertificateTypeListener implements ActionListener { 337 342 @Override 343 @SuppressWarnings("unchecked")//this is just certificateTypeCombo, nothing else 338 344 public void actionPerformed(ActionEvent e) { 339 345 JComboBox source = (JComboBox) e.getSource(); … … 372 378 373 379 private class ImportButtonListener implements ActionListener { 380 @Override 374 381 public void actionPerformed(ActionEvent e) { 375 382 … … 405 412 } catch (Exception ex) { 406 413 // TODO: handle exception 407 ex.printStackTrace();414 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 408 415 } 409 416 } … … 412 419 413 420 private class ExportButtonListener implements ActionListener { 421 @Override 414 422 public void actionPerformed(ActionEvent e) { 415 423 416 JTable table = null;424 final JTable table ; 417 425 if (currentKeyStoreLevel == Level.USER) { 418 426 table = userTable; … … 435 443 if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) { 436 444 char[] password = getPassword(R("CVExportPasswordMessage")); 437 if (password != null) 445 if (password != null) { 438 446 CertificateUtils.dumpPKCS12(alias, chooser.getSelectedFile(), keyStore, password); 447 } 439 448 } else { 440 449 Certificate c = keyStore.getCertificate(alias); … … 447 456 } 448 457 } catch (Exception ex) { 449 // TODO 450 ex.printStackTrace(); 458 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 451 459 } 452 460 } … … 458 466 * Removes a certificate from the keyStore and writes changes to disk. 459 467 */ 468 @Override 460 469 public void actionPerformed(ActionEvent e) { 461 470 462 JTable table = null;471 final JTable table; 463 472 if (currentKeyStoreLevel == Level.USER) { 464 473 table = userTable; … … 492 501 } 493 502 } catch (Exception ex) { 494 // TODO 495 ex.printStackTrace(); 503 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 496 504 } 497 505 … … 504 512 * Shows the details of a trusted certificate. 505 513 */ 514 @Override 506 515 public void actionPerformed(ActionEvent e) { 507 516 508 JTable table = null;517 final JTable table; 509 518 if (currentKeyStoreLevel == Level.USER) { 510 519 table = userTable; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
r418 r429 53 53 import net.sourceforge.jnlp.runtime.JNLPRuntime; 54 54 import net.sourceforge.jnlp.util.ImageResources; 55 import net.sourceforge.jnlp.util.ScreenFinder; 55 56 56 57 public class CertificateViewer extends JDialog { … … 95 96 96 97 private void centerDialog() { 97 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 98 Dimension dialogSize = getSize(); 99 100 setLocation((screen.width - dialogSize.width) / 2, 101 (screen.height - dialogSize.height) / 2); 98 ScreenFinder.centerWindowsToCurrentScreen(this); 102 99 } 103 100 104 101 public static void showCertificateViewer() throws Exception { 105 102 JNLPRuntime.initialize(true); 106 setSystemLookAndFeel();107 103 108 104 CertificateViewer cv = new CertificateViewer(); … … 113 109 } 114 110 115 private static void setSystemLookAndFeel() {116 try {117 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());118 } catch (Exception e) {119 // don't worry if we can't.120 }121 }122 123 111 public static void main(String[] args) throws Exception { 124 112 CertificateViewer.showCertificateViewer(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/ServiceUtil.java
r418 r429 43 43 import net.sourceforge.jnlp.security.SecurityDialogs; 44 44 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 45 import net.sourceforge.jnlp.util.logging.OutputController; 45 46 46 47 /** 47 48 * Provides static methods to interact useful for using the JNLP 48 * services. <p>49 * services. 49 50 * 50 51 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 155 156 * perform. 156 157 */ 157 static Object createPrivilegedProxy(Class iface, final Object receiver) {158 static Object createPrivilegedProxy(Class<?> iface, final Object receiver) { 158 159 return java.lang.reflect.Proxy.newProxyInstance(XServiceManagerStub.class.getClassLoader(), 159 new Class [] { iface },160 new Class<?>[] { iface }, 160 161 new PrivilegedHandler(receiver)); 161 162 } … … 171 172 } 172 173 174 @Override 173 175 public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable { 174 176 if (JNLPRuntime.isDebug()) { 175 System.err.println("call privileged method: " + method.getName()); 176 if (args != null) 177 for (int i = 0; i < args.length; i++) 178 System.err.println(" arg: " + args[i]); 177 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "call privileged method: " + method.getName()); 178 if (args != null) { 179 for (int i = 0; i < args.length; i++) { 180 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, " arg: " + args[i]); 181 } 182 } 179 183 } 180 184 181 185 PrivilegedExceptionAction<Object> invoker = new PrivilegedExceptionAction<Object>() { 186 @Override 182 187 public Object run() throws Exception { 183 188 return method.invoke(receiver, args); … … 188 193 Object result = AccessController.doPrivileged(invoker); 189 194 190 if (JNLPRuntime.isDebug()) 191 System.err.println(" result: " + result); 195 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, " result: " + result); 192 196 193 197 return result; … … 243 247 return false; 244 248 } 245 if (app == null) 249 if (app == null) { 246 250 app = JNLPRuntime.getApplication(); 251 } 247 252 248 253 final AccessType tmpType = type; … … 254 259 //from resources.jar. 255 260 Boolean b = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 261 @Override 256 262 public Boolean run() { 257 263 boolean b = SecurityDialogs.showAccessWarningDialog(tmpType, … … 295 301 public static boolean isSigned(ApplicationInstance app) { 296 302 297 if (app == null) 303 if (app == null) { 298 304 app = JNLPRuntime.getApplication(); 305 } 299 306 300 307 StackTraceElement[] stack = Thread.currentThread().getStackTrace(); … … 302 309 for (int i = 0; i < stack.length; i++) { 303 310 304 Class c = null;311 Class<?> c = null; 305 312 306 313 try { 307 314 c = Class.forName(stack[i].getClassName()); 308 315 } catch (Exception e1) { 316 OutputController.getLogger().log(e1); 309 317 try { 310 318 c = Class.forName(stack[i].getClassName(), false, 311 319 app.getClassLoader()); 312 320 } catch (Exception e2) { 313 System.err.println(e2.getMessage());321 OutputController.getLogger().log(e2); 314 322 } 315 323 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XBasicService.java
r348 r429 34 34 import net.sourceforge.jnlp.runtime.ApplicationInstance; 35 35 import net.sourceforge.jnlp.runtime.JNLPRuntime; 36 import net.sourceforge.jnlp.util.logging.OutputController; 36 37 37 38 /** … … 181 182 return true; 182 183 } catch (IOException ex) { 183 if (JNLPRuntime.isDebug()) 184 ex.printStackTrace(); 184 OutputController.getLogger().log(ex); 185 185 } 186 186 } … … 194 194 initialized = true; 195 195 initializeBrowserCommand(); 196 if (JNLPRuntime.isDebug()) { 197 System.out.println("browser is " + command); 198 } 196 OutputController.getLogger().log("browser is " + command); 199 197 } 200 198 … … 229 227 config.save(); 230 228 } catch (IOException e) { 231 e.printStackTrace();229 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 232 230 } 233 231 break; … … 246 244 config.save(); 247 245 } catch (IOException e) { 248 e.printStackTrace();246 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 249 247 } 250 248 } … … 273 271 return (p.exitValue() == 0); 274 272 } catch (IOException e) { 275 e.printStackTrace();273 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 276 274 return false; 277 275 } catch (InterruptedException e) { 278 e.printStackTrace();276 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 279 277 return false; 280 278 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XDownloadService.java
r348 r429 21 21 import javax.jnlp.*; 22 22 23 import net.sourceforge.jnlp.JARDesc; 24 import net.sourceforge.jnlp.Version; 25 import net.sourceforge.jnlp.cache.CacheUtil; 26 import net.sourceforge.jnlp.runtime.JNLPClassLoader; 27 import net.sourceforge.jnlp.runtime.ManageJnlpResources; 28 import net.sourceforge.jnlp.runtime.JNLPRuntime; 29 23 30 /** 24 31 * The DownloadService JNLP service. … … 29 36 class XDownloadService implements DownloadService { 30 37 31 protected XDownloadService() { 32 } 33 34 // comments copied from DownloadService interface 38 /** 39 * Returns the {@link JNLPClassLoader} of the application 40 * @return the {@link JNLPClassLoader} of the application 41 */ 42 JNLPClassLoader getClassLoader() { 43 return (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader(); 44 } 35 45 36 46 /** 37 47 * Returns a listener that will automatically display download 38 48 * progress to the user. 49 * @return always {@code null} 39 50 */ 40 51 public DownloadServiceListener getDefaultProgressWindow() { … … 47 58 */ 48 59 public boolean isExtensionPartCached(URL ref, String version, String part) { 49 return true; 60 boolean allCached = true; 61 Version resourceVersion = (version == null) ? null : new Version(version); 62 63 JARDesc[] jars = ManageJnlpResources.findJars(this.getClassLoader(), ref, part, resourceVersion); 64 65 if (jars.length <= 0) 66 return false; 67 68 for (int i = 0; i < jars.length && allCached; i++) { 69 allCached = CacheUtil.isCached(jars[i].getLocation(), resourceVersion); 70 } 71 72 return allCached; 50 73 } 51 74 … … 55 78 */ 56 79 public boolean isExtensionPartCached(URL ref, String version, String[] parts) { 57 return true; 80 boolean allCached = true; 81 if (parts.length <= 0) 82 return false; 83 84 for (String eachPart : parts) 85 allCached = this.isExtensionPartCached(ref, version, eachPart); 86 87 return allCached; 58 88 } 59 89 … … 65 95 */ 66 96 public boolean isPartCached(String part) { 67 return true; 97 boolean allCached = true; 98 JARDesc[] jars = ManageJnlpResources.findJars(this.getClassLoader(), null, part, null); 99 100 if (jars.length <= 0) 101 return false; 102 103 for (int i = 0; i < jars.length && allCached; i++) { 104 allCached = CacheUtil.isCached(jars[i].getLocation(), null); 105 } 106 107 return allCached; 68 108 } 69 109 … … 75 115 */ 76 116 public boolean isPartCached(String[] parts) { 77 return true; 117 boolean allCached = true; 118 if (parts.length <= 0) 119 return false; 120 121 for (String eachPart : parts) 122 allCached = this.isPartCached(eachPart); 123 124 return allCached; 78 125 } 79 126 … … 84 131 */ 85 132 public boolean isResourceCached(URL ref, String version) { 86 return true;133 return ManageJnlpResources.isExternalResourceCached(this.getClassLoader(), ref, version); 87 134 } 88 135 … … 93 140 */ 94 141 public void loadExtensionPart(URL ref, String version, String[] parts, DownloadServiceListener progress) throws IOException { 142 for (String eachPart : parts) 143 this.loadExtensionPart(ref, version, eachPart, progress); 95 144 } 96 145 … … 101 150 */ 102 151 public void loadExtensionPart(URL ref, String version, String part, DownloadServiceListener progress) throws IOException { 152 Version resourceVersion = (version == null) ? null : new Version(version); 153 ManageJnlpResources.downloadJars(this.getClassLoader(), ref, part, resourceVersion); 103 154 } 104 155 … … 109 160 */ 110 161 public void loadPart(String[] parts, DownloadServiceListener progress) throws IOException { 162 for (String eachPart : parts) 163 this.loadPart(eachPart, progress); 111 164 } 112 165 … … 117 170 */ 118 171 public void loadPart(String part, DownloadServiceListener progress) throws IOException { 172 ManageJnlpResources.downloadJars(this.getClassLoader(), null, part, null); 119 173 } 120 174 … … 125 179 */ 126 180 public void loadResource(URL ref, String version, DownloadServiceListener progress) throws IOException { 181 ManageJnlpResources.loadExternalResouceToCache(this.getClassLoader(), ref, version); 127 182 } 128 183 … … 134 189 */ 135 190 public void removeExtensionPart(URL ref, String version, String part) throws IOException { 191 Version resourceVersion = (version == null) ? null : new Version(version); 192 JARDesc[] jars = ManageJnlpResources.findJars(this.getClassLoader(), ref, part, resourceVersion); 193 ManageJnlpResources.removeCachedJars(this.getClassLoader(), ref, jars); 136 194 } 137 195 … … 143 201 */ 144 202 public void removeExtensionPart(URL ref, String version, String[] parts) throws IOException { 203 for (String eachPart : parts) 204 this.removeExtensionPart(ref, version, eachPart); 145 205 } 146 206 … … 152 212 */ 153 213 public void removePart(String part) throws IOException { 214 JARDesc[] jars = ManageJnlpResources.findJars(this.getClassLoader(), null, part, null); 215 ManageJnlpResources.removeCachedJars(this.getClassLoader(), null, jars); 154 216 } 155 217 … … 161 223 */ 162 224 public void removePart(String[] parts) throws IOException { 225 for (String eachPart : parts) 226 this.removePart(eachPart); 163 227 } 164 228 … … 170 234 */ 171 235 public void removeResource(URL ref, String version) throws IOException { 236 ManageJnlpResources.removeExternalCachedResource(this.getClassLoader(), ref, version); 172 237 } 173 238 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XFileOpenService.java
r348 r429 92 92 File[] files = chooser.getSelectedFiles(); 93 93 int length = files.length; 94 XFileContents[] xfiles = new XFileContents[length]; 95 for (int i = 0; i < length; i++) 96 xfiles[i] = new XFileContents(files[i]); 97 return (FileContents[]) ServiceUtil.createPrivilegedProxy( 98 FileContents.class, xfiles); 94 FileContents[] result = new FileContents[length]; 95 for (int i = 0; i < length; i++) { 96 XFileContents xfile = new XFileContents(files[i]); 97 result[i] = (FileContents) ServiceUtil.createPrivilegedProxy(FileContents.class, xfile); 98 } 99 return result; 99 100 } else { 100 101 return null; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XPersistenceService.java
r418 r429 26 26 import net.sourceforge.jnlp.runtime.*; 27 27 import net.sourceforge.jnlp.util.FileUtils; 28 import net.sourceforge.jnlp.util.logging.OutputController; 28 29 29 30 /** … … 68 69 requestPath = ""; 69 70 70 if (JNLPRuntime.isDebug()) { 71 System.out.println("codebase path: " + source.getFile()); 72 System.out.println("request path: " + requestPath); 73 } 71 OutputController.getLogger().log("codebase path: " + source.getFile()); 72 OutputController.getLogger().log("request path: " + requestPath); 74 73 75 74 if (!source.getFile().startsWith(requestPath) -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XPrintService.java
r348 r429 48 48 49 49 import net.sourceforge.jnlp.runtime.JNLPRuntime; 50 import net.sourceforge.jnlp.util.logging.OutputController; 50 51 51 52 public class XPrintService implements PrintService { … … 85 86 return true; 86 87 } catch (PrinterException pe) { 87 System.err.println("Could not print: " + pe); 88 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Could not print: " + pe); 89 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, pe); 88 90 return false; 89 91 } … … 103 105 return true; 104 106 } catch (PrinterException pe) { 105 System.err.println("Could not print: " + pe); 107 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Could not print: " + pe); 108 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, pe); 106 109 return false; 107 110 } … … 119 122 "Warning", 120 123 JOptionPane.WARNING_MESSAGE); 121 System.err.println("Unable to print: Unable to find default printer.");124 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Unable to print: Unable to find default printer."); 122 125 } 123 126 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java
r348 r429 25 25 import java.util.LinkedList; 26 26 import java.util.List; 27 import java.util.Map.Entry; 28 import java.util.Set; 27 29 28 30 import javax.jnlp.SingleInstanceListener; … … 30 32 31 33 import net.sourceforge.jnlp.JNLPFile; 34 import net.sourceforge.jnlp.PluginBridge; 32 35 import net.sourceforge.jnlp.runtime.JNLPRuntime; 36 import net.sourceforge.jnlp.util.logging.OutputController; 33 37 34 38 /** … … 61 65 lockFile.createWithPort(listeningSocket.getLocalPort()); 62 66 63 if (JNLPRuntime.isDebug()) { 64 System.out.println("Starting SingleInstanceServer on port" + listeningSocket); 65 } 67 OutputController.getLogger().log("Starting SingleInstanceServer on port" + listeningSocket); 66 68 67 69 while (true) { … … 74 76 } catch (Exception exception) { 75 77 // not much to do here... 76 exception.printStackTrace();78 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, exception); 77 79 } 78 80 79 81 } 80 82 } catch (IOException e) { 81 e.printStackTrace();83 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 82 84 } finally { 83 85 if (listeningSocket != null) { … … 86 88 } catch (IOException e) { 87 89 // Give up. 88 e.printStackTrace();90 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 89 91 } 90 92 } … … 102 104 * Initialize the new SingleInstanceService 103 105 * 104 * @throws Instance AlreadyExistsException if the instance already exists106 * @throws InstanceExistsException if the instance already exists 105 107 */ 106 108 public void initializeSingleInstance() { 107 if (!initialized) { 108 // this is called after the application has started. so safe to use 109 // JNLPRuntime.getApplication() 110 checkSingleInstanceRunning(JNLPRuntime.getApplication().getJNLPFile()); 109 // this is called after the application has started. so safe to use 110 // JNLPRuntime.getApplication() 111 JNLPFile jnlpFile = JNLPRuntime.getApplication().getJNLPFile(); 112 if (!initialized || jnlpFile instanceof PluginBridge) { 113 // Either a new process or a new applet being handled by the plugin. 114 checkSingleInstanceRunning(jnlpFile); 111 115 initialized = true; 112 116 SingleInstanceLock lockFile; 113 JNLPFile jnlpFile = JNLPRuntime.getApplication().getJNLPFile();114 117 lockFile = new SingleInstanceLock(jnlpFile); 115 118 if (!lockFile.isValid()) { … … 128 131 * already exists 129 132 */ 133 @Override 130 134 public void checkSingleInstanceRunning(JNLPFile jnlpFile) { 131 135 SingleInstanceLock lockFile = new SingleInstanceLock(jnlpFile); 132 136 if (lockFile.isValid()) { 133 137 int port = lockFile.getPort(); 134 if (JNLPRuntime.isDebug()) { 135 System.out.println("Lock file is valid (port=" + port + "). Exiting."); 136 } 138 OutputController.getLogger().log("Lock file is valid (port=" + port + "). Exiting."); 139 140 String[] args = null; 141 if (jnlpFile.isApplet()) { 142 // FIXME Proprietary plug-in is unclear about how to handle 143 // applets and their parameters. 144 //Right now better to forward at least something 145 Set<Entry<String, String>> currentParams = jnlpFile.getApplet().getParameters().entrySet(); 146 args = new String[currentParams.size() * 2]; 147 int i = 0; 148 for (Entry<String, String> entry : currentParams) { 149 args[i] = entry.getKey(); 150 args[i+1] = entry.getValue(); 151 i += 2; 152 } 153 } else if (jnlpFile.isInstaller()) { 154 // TODO Implement this once installer service is available. 155 } else { 156 args = jnlpFile.getApplication().getArguments(); 157 } 158 137 159 try { 138 sendProgramArgumentsToExistingApplication(port, jnlpFile.getApplication() 139 .getArguments()); 160 sendProgramArgumentsToExistingApplication(port, args); 140 161 throw new InstanceExistsException(String.valueOf(port)); 141 162 } catch (IOException e) { … … 181 202 182 203 } catch (UnknownHostException unknownHost) { 183 if (JNLPRuntime.isDebug()) { 184 System.out.println("Unable to find localhost"); 185 } 204 OutputController.getLogger().log("Unable to find localhost"); 186 205 throw new RuntimeException(unknownHost); 187 206 } … … 204 223 * Add the specified SingleInstanceListener 205 224 * 206 * @throws InstanceExistsException ,which is likely to terminate the225 * @throws InstanceExistsException which is likely to terminate the 207 226 * application but not guaranteed to 208 227 */ -
trunk/icedtea-web/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java
r418 r429 26 26 package net.sourceforge.jnlp.tools; 27 27 28 import static net.sourceforge.jnlp.runtime.Translator.R; 29 30 import java.io.*; 31 import java.util.*; 32 import java.util.jar.*; 28 import java.io.File; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.security.CodeSigner; 32 import java.security.KeyStore; 33 import java.security.cert.CertPath; 33 34 import java.security.cert.Certificate; 34 35 import java.security.cert.X509Certificate; 35 import java.security.cert.CertPath; 36 import java.security.*; 37 import sun.security.x509.*; 38 import sun.security.util.*; 39 40 import net.sourceforge.jnlp.*; 41 import net.sourceforge.jnlp.cache.*; 42 import net.sourceforge.jnlp.security.*; 36 import java.util.ArrayList; 37 import java.util.Collections; 38 import java.util.Enumeration; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.Vector; 43 import java.util.jar.JarEntry; 44 45 import net.sourceforge.jnlp.JARDesc; 46 import net.sourceforge.jnlp.JNLPFile; 47 import net.sourceforge.jnlp.LaunchException; 48 import net.sourceforge.jnlp.cache.ResourceTracker; 49 import net.sourceforge.jnlp.runtime.JNLPClassLoader.SecurityDelegate; 50 import net.sourceforge.jnlp.security.AppVerifier; 51 import net.sourceforge.jnlp.security.CertVerifier; 52 import net.sourceforge.jnlp.security.CertificateUtils; 53 import net.sourceforge.jnlp.security.KeyStores; 54 import net.sourceforge.jnlp.util.JarFile; 55 import net.sourceforge.jnlp.util.logging.OutputController; 56 import sun.security.util.DerInputStream; 57 import sun.security.util.DerValue; 58 import sun.security.x509.NetscapeCertTypeExtension; 43 59 44 60 /** 45 * <p>The jar certificate verifier utility.46 * 61 * The jar certificate verifier utility. 62 * 47 63 * @author Roland Schemers 48 64 * @author Jan Luehe … … 56 72 private static final String SIG_PREFIX = META_INF + "SIG-"; 57 73 58 private static final long SIX_MONTHS = 180 * 24 * 60 * 60 * 1000L; // milliseconds59 60 static enum verifyResult {74 private static final long SIX_MONTHS = 180 * 24 * 60 * 60 * 1000L; // milliseconds 75 76 static enum VerifyResult { 61 77 UNSIGNED, SIGNED_OK, SIGNED_NOT_OK 62 78 } 63 79 64 // signer's certificate chain (when composing) 65 X509Certificate[] certChain; 66 67 boolean verbose = false; // verbose output when signing/verifying 68 boolean showcerts = false; // show certs when verifying 69 70 private boolean hasExpiredCert = false; 71 private boolean hasExpiringCert = false; 72 private boolean notYetValidCert = false; 73 74 private boolean badKeyUsage = false; 75 private boolean badExtendedKeyUsage = false; 76 private boolean badNetscapeCertType = false; 77 78 private boolean alreadyTrustPublisher = false; 79 private boolean rootInCacerts = false; 80 81 /** 82 * The single certPath used in this JarSiging. We're only keeping 83 * track of one here, since in practice there's only one signer 84 * for a JNLP Application. 85 */ 86 private CertPath certPath = null; 87 88 private boolean noSigningIssues = true; 89 90 private boolean anyJarsSigned = false; 91 92 /** all of the jar files that were verified */ 93 private ArrayList<String> verifiedJars = null; 94 95 /** all of the jar files that were not verified */ 96 private ArrayList<String> unverifiedJars = null; 97 98 /** the certificates used for jar verification */ 99 private HashMap<CertPath, Integer> certs = new HashMap<CertPath, Integer>(); 100 101 /** details of this signing */ 102 private ArrayList<String> details = new ArrayList<String>(); 103 104 private int totalSignableEntries = 0; 105 106 /* (non-Javadoc) 107 * @see net.sourceforge.jnlp.tools.CertVerifier2#getAlreadyTrustPublisher() 108 */ 80 /** All of the jar files that were verified for signing */ 81 private List<String> verifiedJars = new ArrayList<String>(); 82 83 /** All of the jar files that were not verified */ 84 private List<String> unverifiedJars = new ArrayList<String>(); 85 86 /** The certificates used for jar verification linked to their respective information */ 87 private Map<CertPath, CertInformation> certs = new HashMap<CertPath, CertInformation>(); 88 89 /** Temporary cert path hack to be used to keep track of which one a UI dialog is using */ 90 private CertPath currentlyUsed; 91 92 /** Absolute location to jars and the number of entries which are possibly signable */ 93 private Map<String, Integer> jarSignableEntries = new HashMap<String, Integer>(); 94 95 /** The application verifier to use by this instance */ 96 private AppVerifier appVerifier; 97 98 /** 99 * Create a new jar certificate verifier utility that uses the provided verifier for its strategy pattern. 100 * 101 * @param verifier 102 * The application verifier to be used by the new instance. 103 */ 104 public JarCertVerifier(AppVerifier verifier) { 105 appVerifier = verifier; 106 } 107 108 /** 109 * Return true if there are no signable entries in the jar. 110 * This will return false if any of verified jars have content more than just META-INF/. 111 */ 112 public boolean isTriviallySigned() { 113 return getTotalJarEntries(jarSignableEntries) <= 0 114 && certs.size() <= 0; 115 } 116 109 117 public boolean getAlreadyTrustPublisher() { 110 return alreadyTrustPublisher; 111 } 112 113 /* (non-Javadoc) 114 * @see net.sourceforge.jnlp.tools.CertVerifier2#getRootInCacerts() 115 */ 118 boolean allPublishersTrusted = appVerifier.hasAlreadyTrustedPublisher( 119 certs, jarSignableEntries); 120 OutputController.getLogger().log("App already has trusted publisher: " 121 + allPublishersTrusted); 122 return allPublishersTrusted; 123 } 124 116 125 public boolean getRootInCacerts() { 117 return rootInCacerts; 118 } 119 120 public CertPath getCertPath() { 121 return certPath; 122 } 123 124 /* (non-Javadoc) 125 * @see net.sourceforge.jnlp.tools.CertVerifier2#hasSigningIssues() 126 */ 127 public boolean hasSigningIssues() { 128 return hasExpiredCert || notYetValidCert || badKeyUsage 129 || badExtendedKeyUsage || badNetscapeCertType; 130 } 131 132 /* (non-Javadoc) 133 * @see net.sourceforge.jnlp.tools.CertVerifier2#noSigningIssues() 134 */ 135 public boolean noSigningIssues() { 136 return noSigningIssues; 137 } 138 139 public boolean anyJarsSigned() { 140 return anyJarsSigned; 141 } 142 143 /* (non-Javadoc) 144 * @see net.sourceforge.jnlp.tools.CertVerifier2#getDetails() 145 */ 146 public ArrayList<String> getDetails() { 147 return details; 148 } 149 150 /* (non-Javadoc) 151 * @see net.sourceforge.jnlp.tools.CertVerifier2#getCerts() 152 */ 153 public ArrayList<CertPath> getCerts() { 126 boolean allRootCAsTrusted = appVerifier.hasRootInCacerts(certs, 127 jarSignableEntries); 128 OutputController.getLogger().log("App has trusted root CA: " + allRootCAsTrusted); 129 return allRootCAsTrusted; 130 } 131 132 public CertPath getCertPath(CertPath cPath) { // Parameter ignored. 133 return currentlyUsed; 134 } 135 136 public boolean hasSigningIssues(CertPath certPath) { 137 return certs.get(certPath).hasSigningIssues(); 138 } 139 140 public List<String> getDetails(CertPath certPath) { 141 if (certPath != null) { 142 currentlyUsed = certPath; 143 } 144 return certs.get(currentlyUsed).getDetailsAsStrings(); 145 } 146 147 /** 148 * Get a list of the cert paths of all signers across the app. 149 * 150 * @return List of CertPath vars representing each of the signers present on any jar. 151 */ 152 public List<CertPath> getCertsList() { 154 153 return new ArrayList<CertPath>(certs.keySet()); 155 154 } 156 155 157 156 /** 158 * Returns whether or not all entries have a common signer. 159 * 160 * It is possible to create jars where only some entries are signed. In 161 * such cases, we should not prompt the user to accept anything, as the whole 162 * application must be treated as unsigned. This method should be called by a 163 * caller before it is about to ask the user to accept a cert and determine 164 * whether the application is trusted or not. 165 * 166 * @return Whether or not all entries have a common signer 167 */ 168 public boolean isFullySignedByASingleCert() { 169 170 for (CertPath cPath : certs.keySet()) { 171 // If this cert has signed everything, return true 172 if (certs.get(cPath) == totalSignableEntries) 173 return true; 174 } 175 176 // No cert found that signed all entries. Return false. 177 return false; 178 } 179 180 public void verifyJars(List<JARDesc> jars, ResourceTracker tracker) 157 * Find the information the specified cert path has with respect to this application. 158 * 159 * @return All the information the path has with this app. 160 */ 161 public CertInformation getCertInformation(CertPath cPath) { 162 return certs.get(cPath); 163 } 164 165 /** 166 * Returns whether or not the app is considered completely signed. 167 * 168 * An app using a JNLP is considered signed if all of the entries of its jars are signed by at least one common signer. 169 * 170 * An applet on the other hand only needs to have each individual jar be fully signed by a signer. The signers can differ between jars. 171 * 172 * @return Whether or not the app is considered signed. 173 */ 174 // FIXME: Change javadoc once applets do not need entire jars signed. 175 public boolean isFullySigned() { 176 if (isTriviallySigned()) 177 return true; 178 boolean fullySigned = appVerifier.isFullySigned(certs, 179 jarSignableEntries); 180 OutputController.getLogger().log("App already has trusted publisher: " 181 + fullySigned); 182 return fullySigned; 183 } 184 185 public static boolean isJarSigned(JARDesc jar, AppVerifier verifier, ResourceTracker tracker) throws Exception { 186 JarCertVerifier certVerifier = new JarCertVerifier(verifier); 187 List<JARDesc> singleJarList = new ArrayList<JARDesc>(); 188 singleJarList.add(jar); 189 certVerifier.add(singleJarList, tracker); 190 return certVerifier.allJarsSigned(); 191 } 192 193 /** 194 * Update the verifier to consider new jars when verifying. 195 * 196 * @param jars 197 * List of new jars to be verified. 198 * @param tracker 199 * Resource tracker used to obtain the the jars from cache 200 * @throws Exception 201 * Caused by issues with obtaining the jars' entries or interacting with the tracker. 202 */ 203 public void add(List<JARDesc> jars, ResourceTracker tracker) 181 204 throws Exception { 182 183 verifiedJars = new ArrayList<String>(); 184 unverifiedJars = new ArrayList<String>(); 205 verifyJars(jars, tracker); 206 } 207 208 /** 209 * Verify the jars provided and update the state of this instance to match the new information. 210 * 211 * @param jars 212 * List of new jars to be verified. 213 * @param tracker 214 * Resource tracker used to obtain the the jars from cache 215 * @throws Exception 216 * Caused by issues with obtaining the jars' entries or interacting with the tracker. 217 */ 218 private void verifyJars(List<JARDesc> jars, ResourceTracker tracker) 219 throws Exception { 185 220 186 221 for (JARDesc jar : jars) { … … 197 232 198 233 String localFile = jarFile.getAbsolutePath(); 199 verifyResult result = verifyJar(localFile); 200 201 if (result == verifyResult.UNSIGNED) { 234 if (verifiedJars.contains(localFile) 235 || unverifiedJars.contains(localFile)) { 236 continue; 237 } 238 239 VerifyResult result = verifyJar(localFile); 240 241 if (result == VerifyResult.UNSIGNED) { 202 242 unverifiedJars.add(localFile); 203 } else if (result == verifyResult.SIGNED_NOT_OK) { 204 noSigningIssues = false; 243 } else if (result == VerifyResult.SIGNED_NOT_OK) { 205 244 verifiedJars.add(localFile); 206 } else if (result == verifyResult.SIGNED_OK) {245 } else if (result == VerifyResult.SIGNED_OK) { 207 246 verifiedJars.add(localFile); 208 247 } … … 214 253 } 215 254 216 //we really only want the first certPath 217 for (CertPath cPath : certs.keySet()) { 218 219 if (certs.get(cPath) != totalSignableEntries) 220 continue; 221 else 222 certPath = cPath; 223 224 // check if the certs added above are in the trusted path 225 checkTrustedCerts(); 226 227 if (alreadyTrustPublisher || rootInCacerts) 228 break; 229 } 230 231 } 232 233 private verifyResult verifyJar(String jarName) throws Exception { 234 boolean anySigned = false; 235 boolean hasUnsignedEntry = false; 255 for (CertPath certPath : certs.keySet()) 256 checkTrustedCerts(certPath); 257 } 258 259 /** 260 * Checks through all the jar entries of jarName for signers, storing all the common ones in the certs hash map. 261 * 262 * @param jarName 263 * The absolute path to the jar file. 264 * @return The return of {@link JarCertVerifier#verifyJarEntryCerts} using the entries found in the jar located at jarName. 265 * @throws Exception 266 * Will be thrown if there are any problems with the jar. 267 */ 268 private VerifyResult verifyJar(String jarName) throws Exception { 236 269 JarFile jarFile = null; 237 270 … … 248 281 InputStream is = jarFile.getInputStream(je); 249 282 try { 250 int n; 251 while ((n = is.read(buffer, 0, buffer.length)) != -1) { 283 while (is.read(buffer, 0, buffer.length) != -1) { 252 284 // we just read. this will throw a SecurityException 253 // if 285 // if a signature/digest check fails. 254 286 } 255 287 } finally { … … 259 291 } 260 292 } 261 262 if (jarFile.getManifest() != null) { 263 if (verbose) 264 System.out.println(); 265 266 long now = System.currentTimeMillis(); 267 268 for (JarEntry je : entriesVec) { 269 String name = je.getName(); 270 CodeSigner[] signers = je.getCodeSigners(); 271 boolean isSigned = (signers != null); 272 anySigned |= isSigned; 273 274 boolean shouldHaveSignature = !je.isDirectory() 275 && !isMetaInfFile(name); 276 277 hasUnsignedEntry |= shouldHaveSignature && !isSigned; 278 279 if (shouldHaveSignature) 280 totalSignableEntries++; 281 282 if (shouldHaveSignature && isSigned) { 283 for (int i = 0; i < signers.length; i++) { 284 CertPath certPath = signers[i].getSignerCertPath(); 285 if (!certs.containsKey(certPath)) 286 certs.put(certPath, 1); 287 else 288 certs.put(certPath, certs.get(certPath) + 1); 289 290 Certificate cert = signers[i].getSignerCertPath() 291 .getCertificates().get(0); 292 if (cert instanceof X509Certificate) { 293 checkCertUsage((X509Certificate) cert, null); 294 if (!showcerts) { 295 long notBefore = ((X509Certificate) cert) 296 .getNotBefore().getTime(); 297 long notAfter = ((X509Certificate) cert) 298 .getNotAfter().getTime(); 299 300 if (now < notBefore) { 301 notYetValidCert = true; 302 } 303 304 if (notAfter < now) { 305 hasExpiredCert = true; 306 } else if (notAfter < now + SIX_MONTHS) { 307 hasExpiringCert = true; 308 } 309 } 310 } 311 } 312 } 313 } //while e has more elements 314 } else { //if man not null 315 316 // Else increment totalEntries by 1 so that unsigned jars with 317 // no manifests can't sneak in 318 totalSignableEntries++; 319 } 320 321 //Alert the user if any of the following are true. 322 if (!anySigned) { 323 return verifyResult.UNSIGNED; 324 } else { 325 anyJarsSigned = true; 326 327 //warnings 328 if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert || 329 badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || 330 notYetValidCert) { 331 332 addToDetails(R("SRunWithoutRestrictions")); 333 334 if (badKeyUsage) 335 addToDetails(R("SBadKeyUsage")); 336 if (badExtendedKeyUsage) 337 addToDetails(R("SBadExtendedKeyUsage")); 338 if (badNetscapeCertType) 339 addToDetails(R("SBadNetscapeCertType")); 340 if (hasUnsignedEntry) 341 addToDetails(R("SHasUnsignedEntry")); 342 if (hasExpiredCert) 343 addToDetails(R("SHasExpiredCert")); 344 if (hasExpiringCert) 345 addToDetails(R("SHasExpiringCert")); 346 if (notYetValidCert) 347 addToDetails(R("SNotYetValidCert")); 348 } 349 } 293 return verifyJarEntryCerts(jarName, jarFile.getManifest() != null, 294 entriesVec); 295 350 296 } catch (Exception e) { 351 e.printStackTrace();297 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 352 298 throw e; 353 299 } finally { // close the resource … … 356 302 } 357 303 } 358 359 //anySigned does not guarantee that all files were signed. 360 return (anySigned && !(hasUnsignedEntry || hasExpiredCert 361 || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || notYetValidCert)) ? verifyResult.SIGNED_OK : verifyResult.SIGNED_NOT_OK; 362 } 363 364 /** 365 * Checks the user's trusted.certs file and the cacerts file to see 366 * if a publisher's and/or CA's certificate exists there. 367 */ 368 private void checkTrustedCerts() throws Exception { 369 if (certPath != null) { 370 try { 371 X509Certificate publisher = (X509Certificate) getPublisher(); 372 KeyStore[] certKeyStores = KeyStores.getCertKeyStores(); 373 alreadyTrustPublisher = CertificateUtils.inKeyStores(publisher, certKeyStores); 374 X509Certificate root = (X509Certificate) getRoot(); 375 KeyStore[] caKeyStores = KeyStores.getCAKeyStores(); 376 // Check entire cert path for a trusted CA 377 for (Certificate c : certPath.getCertificates()) { 378 if ((rootInCacerts = CertificateUtils.inKeyStores( 379 (X509Certificate) c, caKeyStores))) { 380 break; 304 } 305 306 /** 307 * Checks through all the jar entries for signers, storing all the common ones in the certs hash map. 308 * 309 * @param jarName 310 * The absolute path to the jar file. 311 * @param jarHasManifest 312 * Whether or not the associated jar has a manifest. 313 * @param entries 314 * The list of entries in the associated jar. 315 * @return If there is at least one signable entry that is not signed by a common signer, return UNSIGNED. Otherwise every signable entry is signed by at least one common signer. If the signer has no issues, return SIGNED_OK. If there are any signing issues, return SIGNED_NOT_OK. 316 * @throws Exception 317 * Will be thrown if there are issues with entries. 318 */ 319 VerifyResult verifyJarEntryCerts(String jarName, boolean jarHasManifest, 320 Vector<JarEntry> entries) throws Exception { 321 // Contains number of entries the cert with this CertPath has signed. 322 Map<CertPath, Integer> jarSignCount = new HashMap<CertPath, Integer>(); 323 int numSignableEntriesInJar = 0; 324 325 // Record current time just before checking the jar begins. 326 long now = System.currentTimeMillis(); 327 if (jarHasManifest) { 328 329 for (JarEntry je : entries) { 330 String name = je.getName(); 331 CodeSigner[] signers = je.getCodeSigners(); 332 boolean isSigned = (signers != null); 333 334 boolean shouldHaveSignature = !je.isDirectory() 335 && !isMetaInfFile(name); 336 337 if (shouldHaveSignature) { 338 numSignableEntriesInJar++; 339 } 340 341 if (shouldHaveSignature && isSigned) { 342 for (int i = 0; i < signers.length; i++) { 343 CertPath certPath = signers[i].getSignerCertPath(); 344 345 if (!jarSignCount.containsKey(certPath)) 346 jarSignCount.put(certPath, 1); 347 else 348 jarSignCount.put(certPath, 349 jarSignCount.get(certPath) + 1); 381 350 } 382 351 } 383 } catch (Exception e) { 384 // TODO: Warn user about not being able to 385 // look through their cacerts/trusted.certs 386 // file depending on exception. 387 throw e; 388 } 389 390 if (!rootInCacerts) 391 addToDetails(R("SUntrustedCertificate")); 392 else 393 addToDetails(R("STrustedCertificate")); 394 } 395 } 396 397 /* (non-Javadoc) 398 * @see net.sourceforge.jnlp.tools.CertVerifier2#getPublisher() 399 */ 400 public Certificate getPublisher() { 401 if (certPath != null) { 402 List<? extends Certificate> certList = certPath.getCertificates(); 352 } // while e has more elements 353 } else { // if manifest is null 354 355 // Else increment total entries by 1 so that unsigned jars with 356 // no manifests can't sneak in 357 numSignableEntriesInJar++; 358 } 359 360 jarSignableEntries.put(jarName, numSignableEntriesInJar); 361 362 // Find all signers that have signed every signable entry in this jar. 363 boolean allEntriesSignedBySingleCert = false; 364 for (CertPath certPath : jarSignCount.keySet()) { 365 if (jarSignCount.get(certPath) == numSignableEntriesInJar) { 366 allEntriesSignedBySingleCert = true; 367 368 boolean wasPreviouslyVerified = certs.containsKey(certPath); 369 if (!wasPreviouslyVerified) 370 certs.put(certPath, new CertInformation()); 371 372 CertInformation certInfo = certs.get(certPath); 373 if (wasPreviouslyVerified) 374 certInfo.resetForReverification(); 375 376 certInfo.setNumJarEntriesSigned(jarName, 377 numSignableEntriesInJar); 378 379 Certificate cert = certPath.getCertificates().get(0); 380 if (cert instanceof X509Certificate) { 381 checkCertUsage(certPath, (X509Certificate) cert, null); 382 long notBefore = ((X509Certificate) cert).getNotBefore().getTime(); 383 long notAfter = ((X509Certificate) cert).getNotAfter().getTime(); 384 if (now < notBefore) { 385 certInfo.setNotYetValidCert(); 386 } 387 388 if (notAfter < now) { 389 certInfo.setHasExpiredCert(); 390 } else if (notAfter < now + SIX_MONTHS) { 391 certInfo.setHasExpiringCert(); 392 } 393 } 394 } 395 } 396 397 // Every signable entry of this jar needs to be signed by at least 398 // one signer for the jar to be considered successfully signed. 399 VerifyResult result = null; 400 401 if (numSignableEntriesInJar == 0) { 402 // Allow jars with no signable entries to simply be considered signed. 403 // There should be no security risk in doing so. 404 result = VerifyResult.SIGNED_OK; 405 } else if (allEntriesSignedBySingleCert) { 406 407 // We need to find at least one signer without any issues. 408 for (CertPath entryCertPath : jarSignCount.keySet()) { 409 if (certs.containsKey(entryCertPath) 410 && !hasSigningIssues(entryCertPath)) { 411 result = VerifyResult.SIGNED_OK; 412 break; 413 } 414 } 415 if (result == null) { 416 // All signers had issues 417 result = VerifyResult.SIGNED_NOT_OK; 418 } 419 } else { 420 result = VerifyResult.UNSIGNED; 421 } 422 423 OutputController.getLogger().log("Jar found at " + jarName 424 + "has been verified as " + result); 425 return result; 426 } 427 428 /** 429 * Checks the user's trusted.certs file and the cacerts file to see if a 430 * publisher's and/or CA's certificate exists there. 431 * 432 * @param certPath 433 * The cert path of the signer being checked for trust. 434 */ 435 private void checkTrustedCerts(CertPath certPath) throws Exception { 436 CertInformation info = certs.get(certPath); 437 try { 438 X509Certificate publisher = (X509Certificate) getPublisher(certPath); 439 KeyStore[] certKeyStores = KeyStores.getCertKeyStores(); 440 if (CertificateUtils.inKeyStores(publisher, certKeyStores)) 441 info.setAlreadyTrustPublisher(); 442 KeyStore[] caKeyStores = KeyStores.getCAKeyStores(); 443 // Check entire cert path for a trusted CA 444 for (Certificate c : certPath.getCertificates()) { 445 if (CertificateUtils.inKeyStores((X509Certificate) c, 446 caKeyStores)) { 447 info.setRootInCacerts(); 448 return; 449 } 450 } 451 } catch (Exception e) { 452 // TODO: Warn user about not being able to 453 // look through their cacerts/trusted.certs 454 // file depending on exception. 455 OutputController.getLogger().log("WARNING: Unable to read through cert store files."); 456 throw e; 457 } 458 459 // Otherwise a parent cert was not found to be trusted. 460 info.setUntrusted(); 461 } 462 463 public void setCurrentlyUsedCertPath(CertPath cPath) { 464 currentlyUsed = cPath; 465 } 466 467 public Certificate getPublisher(CertPath cPath) { 468 if (cPath != null) { 469 currentlyUsed = cPath; 470 } 471 if (currentlyUsed != null) { 472 List<? extends Certificate> certList = currentlyUsed 473 .getCertificates(); 403 474 if (certList.size() > 0) { 404 475 return certList.get(0); … … 411 482 } 412 483 413 /* (non-Javadoc) 414 * @see net.sourceforge.jnlp.tools.CertVerifier2#getRoot() 415 */ 416 public Certificate getRoot() { 417 if (certPath != null) { 418 List<? extends Certificate> certList = certPath.getCertificates(); 484 public Certificate getRoot(CertPath cPath) { 485 if (cPath != null) { 486 currentlyUsed = cPath; 487 } 488 if (currentlyUsed != null) { 489 List<? extends Certificate> certList = currentlyUsed 490 .getCertificates(); 419 491 if (certList.size() > 0) { 420 492 return certList.get(certList.size() - 1); … … 427 499 } 428 500 429 private void addToDetails(String detail) {430 if (!details.contains(detail))431 details.add(detail);432 }433 434 501 /** 435 502 * Returns whether a file is in META-INF, and thus does not require signing. 436 * 437 * Signature-related files under META-INF include: 438 * . META-INF/MANIFEST.MF 439 * . META-INF/SIG-* 440 * . META-INF/*.SF 441 * . META-INF/*.DSA 442 * . META-INF/*.RSA 503 * 504 * Signature-related files under META-INF include: . META-INF/MANIFEST.MF . META-INF/SIG-* . META-INF/*.SF . META-INF/*.DSA . META-INF/*.RSA 443 505 */ 444 506 static boolean isMetaInfFile(String name) { … … 449 511 /** 450 512 * Check if userCert is designed to be a code signer 451 * @param userCert the certificate to be examined 452 * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage, 453 * NetscapeCertType has codeSigning flag turned on. 454 * If null, the class field badKeyUsage, badExtendedKeyUsage, 513 * 514 * @param userCert 515 * the certificate to be examined 516 * @param bad 517 * 3 booleans to show if the KeyUsage, ExtendedKeyUsage, 518 * NetscapeCertType has codeSigning flag turned on. If null, 519 * the class field badKeyUsage, badExtendedKeyUsage, 455 520 * badNetscapeCertType will be set. 456 * 457 * Required for verifyJar() 458 */ 459 void checkCertUsage(X509Certificate userCert, boolean[] bad) { 521 * 522 * Required for verifyJar() 523 */ 524 void checkCertUsage(CertPath certPath, X509Certificate userCert, 525 boolean[] bad) { 460 526 461 527 // Can act as a signer? … … 475 541 bad[0] = true; 476 542 } else { 477 badKeyUsage = true;543 certs.get(certPath).setBadKeyUsage(); 478 544 } 479 545 } … … 488 554 bad[1] = true; 489 555 } else { 490 badExtendedKeyUsage = true;556 certs.get(certPath).setBadExtendedKeyUsage(); 491 557 } 492 558 } … … 498 564 try { 499 565 // OID_NETSCAPE_CERT_TYPE 500 byte[] netscapeEx = userCert .getExtensionValue501 566 byte[] netscapeEx = userCert 567 .getExtensionValue("2.16.840.1.113730.1.1"); 502 568 if (netscapeEx != null) { 503 569 DerInputStream in = new DerInputStream(netscapeEx); … … 506 572 .toByteArray(); 507 573 508 NetscapeCertTypeExtension extn = 509 new NetscapeCertTypeExtension(encoded);510 511 Boolean val = (Boolean) extn .get(512 574 NetscapeCertTypeExtension extn = new NetscapeCertTypeExtension( 575 encoded); 576 577 Boolean val = (Boolean) extn 578 .get(NetscapeCertTypeExtension.OBJECT_SIGNING); 513 579 if (!val) { 514 580 if (bad != null) { 515 581 bad[2] = true; 516 582 } else { 517 badNetscapeCertType = true;583 certs.get(certPath).setBadNetscapeCertType(); 518 584 } 519 585 } … … 526 592 /** 527 593 * Returns if all jars are signed. 528 * 594 * 529 595 * @return True if all jars are signed, false if there are one or more unsigned jars 530 596 */ … … 533 599 } 534 600 601 public void checkTrustWithUser(SecurityDelegate securityDelegate, JNLPFile file) throws LaunchException { 602 appVerifier.checkTrustWithUser(securityDelegate, this, file); 603 } 604 605 public Map<String, Integer> getJarSignableEntries() { 606 return Collections.unmodifiableMap(jarSignableEntries); 607 } 608 609 /** 610 * Get the total number of entries in the provided map. 611 * 612 * @return The number of entries. 613 */ 614 public static int getTotalJarEntries(Map<String, Integer> map) { 615 int sum = 0; 616 for (int value : map.values()) { 617 sum += value; 618 } 619 return sum; 620 } 535 621 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java
r418 r429 27 27 28 28 /** 29 * <p> This class provides several utilities to <code>KeyStore</code>.29 * This class provides several utilities to {@link java.security.KeyStore}. 30 30 * 31 31 * @since 1.6.0 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java
r418 r429 38 38 package net.sourceforge.jnlp.util; 39 39 40 import net.sourceforge.jnlp.util.logging.OutputController; 40 41 import static net.sourceforge.jnlp.runtime.Translator.R; 41 42 42 43 import java.awt.BorderLayout; 44 import java.awt.Component; 43 45 import java.awt.Dimension; 44 46 import java.awt.event.ActionEvent; 45 47 import java.awt.event.ActionListener; 46 import java.io.PrintWriter;47 import java.io.StringWriter;48 48 49 49 import javax.swing.BorderFactory; … … 57 57 import javax.swing.JScrollPane; 58 58 import javax.swing.JTextArea; 59 import javax.swing.SwingUtilities; 60 import net.sourceforge.jnlp.controlpanel.CachePane; 61 import net.sourceforge.jnlp.util.logging.JavaConsole; 59 62 60 63 /** … … 63 66 public class BasicExceptionDialog { 64 67 65 private static String exceptionToString(Exception exception) {66 StringWriter stringWriter = new StringWriter();67 PrintWriter printWriter = new PrintWriter(stringWriter);68 exception.printStackTrace(printWriter);69 return stringWriter.toString();70 }71 68 72 69 /** … … 76 73 */ 77 74 public static void show(Exception exception) { 78 String detailsText = exceptionToString(exception);75 String detailsText = OutputController.exceptionToString(exception); 79 76 80 77 final JPanel mainPanel = new JPanel(new BorderLayout()); … … 85 82 errorDialog.setIconImages(ImageResources.INSTANCE.getApplicationImages()); 86 83 87 final JPanel quickInfoPanel = new JPanel(); 88 BoxLayout layout = new BoxLayout(quickInfoPanel, BoxLayout.Y_AXIS); 89 quickInfoPanel.setLayout(layout); 90 mainPanel.add(quickInfoPanel, BorderLayout.PAGE_START); 84 final JPanel quickInfoPanelAll = new JPanel(); 85 final JPanel quickInfoPanelMessage = new JPanel(); 86 final JPanel quickInfoPanelButtons = new JPanel(); 87 BoxLayout layoutAll = new BoxLayout(quickInfoPanelAll, BoxLayout.Y_AXIS); 88 BoxLayout layoutMessage = new BoxLayout(quickInfoPanelMessage, BoxLayout.X_AXIS); 89 BoxLayout layoutButtons = new BoxLayout(quickInfoPanelButtons, BoxLayout.X_AXIS); 90 quickInfoPanelAll.setLayout(layoutAll); 91 quickInfoPanelMessage.setLayout(layoutMessage); 92 quickInfoPanelButtons.setLayout(layoutButtons); 93 mainPanel.add(quickInfoPanelAll, BorderLayout.PAGE_START); 94 quickInfoPanelAll.add(quickInfoPanelMessage); 95 quickInfoPanelAll.add(quickInfoPanelButtons); 91 96 92 97 JLabel errorLabel = new JLabel(exception.getMessage()); 93 98 errorLabel.setAlignmentY(JComponent.LEFT_ALIGNMENT); 94 quickInfoPanel .add(errorLabel);99 quickInfoPanelMessage.add(errorLabel); 95 100 96 101 final JButton viewDetails = new JButton(R("ButShowDetails")); 97 102 viewDetails.setAlignmentY(JComponent.LEFT_ALIGNMENT); 98 103 viewDetails.setActionCommand("show"); 99 quickInfoPanel.add(viewDetails); 104 quickInfoPanelButtons.add(viewDetails); 105 106 final JButton cacheButton = getClearCacheButton(errorDialog); 107 cacheButton.setAlignmentY(JComponent.LEFT_ALIGNMENT); 108 quickInfoPanelButtons.add(cacheButton); 109 110 final JButton consoleButton = getShowButton(errorDialog); 111 consoleButton.setAlignmentY(JComponent.LEFT_ALIGNMENT); 112 quickInfoPanelButtons.add(consoleButton); 113 114 final JPanel fillRest = new JPanel(); 115 fillRest.setAlignmentY(JComponent.LEFT_ALIGNMENT); 116 quickInfoPanelButtons.add(fillRest); 100 117 101 118 JTextArea textArea = new JTextArea(); … … 125 142 errorDialog.pack(); 126 143 errorDialog.setResizable(true); 144 ScreenFinder.centerWindowsToCurrentScreen(errorDialog); 127 145 errorDialog.setVisible(true); 128 146 errorDialog.dispose(); 129 147 } 148 149 public static JButton getShowButton(final Component parent) { 150 JButton consoleButton = new JButton(); 151 consoleButton.setText(R("DPJavaConsole")); 152 consoleButton.addActionListener(new java.awt.event.ActionListener() { 153 154 @Override 155 public void actionPerformed(java.awt.event.ActionEvent evt) { 156 try { 157 JavaConsole.getConsole().showConsoleLater(true); 158 } catch (Exception ex) { 159 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 160 JOptionPane.showConfirmDialog(parent, ex); 161 } 162 } 163 }); 164 if (!JavaConsole.isEnabled()) { 165 consoleButton.setEnabled(false); 166 consoleButton.setToolTipText(R("DPJavaConsoleDisabledHint")); 167 } 168 return consoleButton; 169 } 170 171 public static JButton getClearCacheButton(final Component parent) { 172 JButton clearAllButton = new JButton(); 173 clearAllButton.setText(R("CVCPCleanCache")); 174 clearAllButton.setToolTipText(R("CVCPCleanCacheTip")); 175 clearAllButton.addActionListener(new java.awt.event.ActionListener() { 176 177 @Override 178 public void actionPerformed(java.awt.event.ActionEvent evt) { 179 SwingUtilities.invokeLater(new Runnable() { 180 181 @Override 182 public void run() { 183 try { 184 CachePane.visualCleanCache(parent); 185 } catch (Exception ex) { 186 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, ex); 187 } 188 } 189 }); 190 } 191 }); 192 return clearAllButton; 193 } 130 194 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/FileUtils.java
r396 r429 17 17 package net.sourceforge.jnlp.util; 18 18 19 import java.awt.Component; 19 20 import static net.sourceforge.jnlp.runtime.Translator.R; 20 21 22 import java.awt.Window; 23 import java.io.BufferedReader; 24 import java.io.BufferedWriter; 21 25 import java.io.File; 26 import java.io.FileInputStream; 22 27 import java.io.FileNotFoundException; 28 import java.io.FileOutputStream; 23 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.InputStreamReader; 32 import java.io.OutputStreamWriter; 24 33 import java.io.RandomAccessFile; 34 import java.io.Writer; 25 35 import java.nio.channels.FileChannel; 26 36 import java.nio.channels.FileLock; 37 import java.security.DigestInputStream; 38 import java.security.MessageDigest; 39 import java.security.NoSuchAlgorithmException; 40 import java.util.ArrayList; 41 import java.util.List; 27 42 28 43 import net.sourceforge.jnlp.config.Defaults; 44 import javax.swing.JFrame; 45 import javax.swing.JOptionPane; 46 import javax.swing.SwingUtilities; 47 48 import net.sourceforge.jnlp.config.DirectoryValidator; 49 import net.sourceforge.jnlp.config.DirectoryValidator.DirectoryCheckResults; 29 50 import net.sourceforge.jnlp.runtime.JNLPRuntime; 51 import net.sourceforge.jnlp.util.logging.OutputController; 30 52 31 53 /** … … 36 58 37 59 public final class FileUtils { 60 61 /** 62 * Indicates whether a file was successfully opened. If not, provides specific reasons 63 * along with a general failure case 64 */ 65 public enum OpenFileResult { 66 /** The file was successfully opened */ 67 SUCCESS, 68 /** The file could not be opened, for non-specified reasons */ 69 FAILURE, 70 /** The file could not be opened because it did not exist and could not be created */ 71 CANT_CREATE, 72 /** The file can be opened but in read-only */ 73 CANT_WRITE, 74 /** The specified path pointed to a non-file filesystem object, ie a directory */ 75 NOT_FILE; 76 } 38 77 39 78 /** … … 140 179 if (f.exists()) { 141 180 if (!f.delete()) { 142 System.err.println(R("RCantDeleteFile", eMsg == null ? f : eMsg));181 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RCantDeleteFile", eMsg == null ? f : eMsg)); 143 182 } 144 183 } … … 178 217 } 179 218 219 if (JNLPRuntime.isWindows()) { 220 // remove all permissions 221 if (!tempFile.setExecutable(false, false)) { 222 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveXPermFailed", tempFile)); 223 } 224 if (!tempFile.setReadable(false, false)) { 225 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveRPermFailed", tempFile)); 226 } 227 if (!tempFile.setWritable(false, false)) { 228 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveWPermFailed", tempFile)); 229 } 230 231 // allow owner to read 232 if (!tempFile.setReadable(true, true)) { 233 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetRPermFailed", tempFile)); 234 } 235 236 // allow owner to write 237 if (writableByOwner && !tempFile.setWritable(true, true)) { 238 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetWPermFailed", tempFile)); 239 } 240 241 // allow owner to enter directories 242 if (isDir && !tempFile.setExecutable(true, true)) { 243 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetXPermFailed", tempFile)); 244 } 245 // rename this file. Unless the file is moved/renamed, any program that 246 // opened the file right after it was created might still be able to 247 // read the data. 248 if (!tempFile.renameTo(file)) { 249 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RCantRename", tempFile, file)); 250 } 251 } else { 180 252 // remove all permissions 181 253 if (!Defaults.OS_DOS_LIKE) { … … 205 277 throw new IOException(R("RGetXPermFailed", tempFile)); 206 278 } 207 279 208 280 // rename this file. Unless the file is moved/renamed, any program that 209 281 // opened the file right after it was created might still be able to … … 217 289 throw new IOException(R("RCantRename", tempFile, file)); 218 290 } 219 291 } 292 293 } 294 295 /** 296 * Ensure that the parent directory of the file exists and that we are 297 * able to create and access files within this directory 298 * @param file the {@link File} representing a Java Policy file to test 299 * @return a {@link DirectoryCheckResults} object representing the results of the test 300 */ 301 public static DirectoryCheckResults testDirectoryPermissions(File file) { 302 try { 303 file = file.getCanonicalFile(); 304 } catch (final IOException e) { 305 OutputController.getLogger().log(e); 306 return null; 307 } 308 if (file == null || file.getParentFile() == null || !file.getParentFile().exists()) { 309 return null; 310 } 311 final List<File> policyDirectory = new ArrayList<File>(); 312 policyDirectory.add(file.getParentFile()); 313 final DirectoryValidator validator = new DirectoryValidator(policyDirectory); 314 final DirectoryCheckResults result = validator.ensureDirs(); 315 316 return result; 317 } 318 319 /** 320 * Verify that a given file object points to a real, accessible plain file. 321 * @param file the {@link File} to verify 322 * @return an {@link OpenFileResult} representing the accessibility level of the file 323 */ 324 public static OpenFileResult testFilePermissions(File file) { 325 if (file == null || !file.exists()) { 326 return OpenFileResult.FAILURE; 327 } 328 try { 329 file = file.getCanonicalFile(); 330 } catch (final IOException e) { 331 return OpenFileResult.FAILURE; 332 } 333 final DirectoryCheckResults dcr = FileUtils.testDirectoryPermissions(file); 334 if (dcr != null && dcr.getFailures() == 0) { 335 if (file.isDirectory()) 336 return OpenFileResult.NOT_FILE; 337 try { 338 if (!file.exists() && !file.createNewFile()) { 339 return OpenFileResult.CANT_CREATE; 340 } 341 } catch (IOException e) { 342 return OpenFileResult.CANT_CREATE; 343 } 344 final boolean read = file.canRead(), write = file.canWrite(); 345 if (read && write) 346 return OpenFileResult.SUCCESS; 347 else if (read) 348 return OpenFileResult.CANT_WRITE; 349 else 350 return OpenFileResult.FAILURE; 351 } 352 return OpenFileResult.FAILURE; 353 } 354 355 /** 356 * Show a dialog informing the user that the file is currently read-only 357 * @param frame a {@link JFrame} to act as parent to this dialog 358 */ 359 public static void showReadOnlyDialog(final Component frame) { 360 SwingUtilities.invokeLater(new Runnable() { 361 @Override 362 public void run() { 363 JOptionPane.showMessageDialog(frame, R("RFileReadOnly"), R("Warning"), JOptionPane.WARNING_MESSAGE); 364 } 365 }); 366 } 367 368 /** 369 * Show a generic error dialog indicating the file could not be opened 370 * @param frame a {@link JFrame} to act as parent to this dialog 371 * @param filePath a {@link String} representing the path to the file we failed to open 372 */ 373 public static void showCouldNotOpenFilepathDialog(final Component frame, final String filePath) { 374 showCouldNotOpenDialog(frame, R("RCantOpenFile", filePath)); 375 } 376 377 /** 378 * Show an error dialog indicating the file could not be opened, with a particular reason 379 * @param frame a {@link JFrame} to act as parent to this dialog 380 * @param filePath a {@link String} representing the path to the file we failed to open 381 * @param reason a {@link OpenFileResult} specifying more precisely why we failed to open the file 382 */ 383 public static void showCouldNotOpenFileDialog(final Component frame, final String filePath, final OpenFileResult reason) { 384 final String message; 385 switch (reason) { 386 case CANT_CREATE: 387 message = R("RCantCreateFile", filePath); 388 break; 389 case CANT_WRITE: 390 message = R("RCantWriteFile", filePath); 391 break; 392 case NOT_FILE: 393 message = R("RExpectedFile", filePath); 394 break; 395 default: 396 message = R("RCantOpenFile", filePath); 397 break; 398 } 399 showCouldNotOpenDialog(frame, message); 400 } 401 402 /** 403 * Show a dialog informing the user that the file could not be opened 404 * @param frame a {@link JFrame} to act as parent to this dialog 405 * @param filePath a {@link String} representing the path to the file we failed to open 406 * @param message a {@link String} giving the specific reason the file could not be opened 407 */ 408 public static void showCouldNotOpenDialog(final Component frame, final String message) { 409 SwingUtilities.invokeLater(new Runnable() { 410 @Override 411 public void run() { 412 JOptionPane.showMessageDialog(frame, message, R("Error"), JOptionPane.ERROR_MESSAGE); 413 } 414 }); 220 415 } 221 416 … … 284 479 */ 285 480 public static void recursiveDelete(File file, File base) throws IOException { 286 if (JNLPRuntime.isDebug()) { 287 System.err.println("Deleting: " + file); 288 } 481 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Deleting: " + file); 289 482 290 483 if (!(file.getCanonicalPath().startsWith(base.getCanonicalPath()))) { … … 342 535 } 343 536 } catch (IOException e) { 344 e.printStackTrace();537 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 345 538 } 346 539 return lock; 347 540 } 541 542 /** 543 * helping dummy method to save String as file 544 * 545 * @param content 546 * @param f 547 * @throws IOException 548 */ 549 public static void saveFile(String content, File f) throws IOException { 550 saveFile(content, f, "utf-8"); 551 } 552 553 public static void saveFile(String content, File f, String encoding) throws IOException { 554 Writer output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), encoding)); 555 output.write(content); 556 output.flush(); 557 output.close(); 558 } 559 560 /** 561 * utility method which can read from any stream as one long String 562 * 563 * @param is stream 564 * @param encoding the encoding to use to convert the bytes from the stream 565 * @return stream as string 566 * @throws IOException if connection can't be established or resource does not exist 567 */ 568 public static String getContentOfStream(InputStream is, String encoding) throws IOException { 569 try { 570 BufferedReader br = new BufferedReader(new InputStreamReader(is, encoding)); 571 StringBuilder sb = new StringBuilder(); 572 while (true) { 573 String s = br.readLine(); 574 if (s == null) { 575 break; 576 } 577 sb.append(s).append("\n"); 578 579 } 580 return sb.toString(); 581 } finally { 582 is.close(); 583 } 584 585 } 586 587 /** 588 * utility method which can read from any stream as one long String 589 * 590 * @param is stream 591 * @return stream as string 592 * @throws IOException if connection can't be established or resource does not exist 593 */ 594 public static String getContentOfStream(InputStream is) throws IOException { 595 return getContentOfStream(is, "UTF-8"); 596 597 } 598 599 public static String loadFileAsString(File f) throws IOException { 600 return getContentOfStream(new FileInputStream(f)); 601 } 602 603 public static String loadFileAsString(File f, String encoding) throws IOException { 604 return getContentOfStream(new FileInputStream(f), encoding); 605 } 606 607 public static byte[] getFileMD5Sum(final File file, final String algorithm) throws NoSuchAlgorithmException, 608 FileNotFoundException, IOException { 609 final MessageDigest md5; 610 InputStream is = null; 611 DigestInputStream dis = null; 612 try { 613 md5 = MessageDigest.getInstance(algorithm); 614 is = new FileInputStream(file); 615 dis = new DigestInputStream(is, md5); 616 617 md5.update(getContentOfStream(dis).getBytes()); 618 } finally { 619 if (is != null) { 620 is.close(); 621 } 622 if (dis != null) { 623 dis.close(); 624 } 625 } 626 627 return md5.digest(); 628 } 348 629 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/ImageResources.java
r418 r429 38 38 package net.sourceforge.jnlp.util; 39 39 40 import net.sourceforge.jnlp.util.logging.OutputController; 40 41 import java.awt.Image; 41 42 import java.io.IOException; … … 82 83 return image; 83 84 } catch (IOException ioe) { 84 ioe.printStackTrace();85 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ioe); 85 86 return null; 86 87 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/PropertiesFile.java
r418 r429 17 17 package net.sourceforge.jnlp.util; 18 18 19 import net.sourceforge.jnlp.util.logging.OutputController; 19 20 import java.io.*; 20 21 import java.util.*; … … 24 25 * exceptions. The properties are automatically loaded from the 25 26 * file when the first property is requested, but the save method 26 * must be called before changes are saved to the file. <p>27 * must be called before changes are saved to the file. 27 28 * 28 29 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author … … 139 140 } 140 141 } catch (IOException ex) { 141 ex.printStackTrace();142 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 142 143 } 143 144 } … … 165 166 } 166 167 } catch (IOException ex) { 167 ex.printStackTrace();168 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 168 169 } 169 170 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/Reflect.java
r348 r429 17 17 package net.sourceforge.jnlp.util; 18 18 19 import java.lang.reflect.*; 19 import java.lang.reflect.Method; 20 import net.sourceforge.jnlp.util.logging.OutputController; 21 20 22 21 23 /** 22 24 * Provides simply, convenient methods to invoke methods by 23 * name. 25 * name. This class is used to consolidate reflection needed to 24 26 * access methods specific to Sun's JVM or to remain backward 25 * compatible while supporting method in newer JVMs. <p>26 * 27 * compatible while supporting method in newer JVMs. 28 * <p> 27 29 * Most methods of this class invoke the first method on the 28 30 * specified object that matches the name and number of 29 * parameters. 31 * parameters. The type of the parameters are not considered, so 30 32 * do not attempt to use this class to invoke overloaded 31 * methods.<p> 32 * 33 * Instances of this class are not synchronized.<p> 33 * methods. 34 * </p> 35 * <p> 36 * Instances of this class are not synchronized. 37 * </p> 34 38 * 35 39 * @author <a href="mailto:jon.maxwell@acm.org">Jon A. Maxwell (JAM)</a> - initial author … … 75 79 public Object invokeStatic(String className, String method, Object args[]) { 76 80 try { 77 Class c = Class.forName(className, true, Reflect.class.getClassLoader());81 Class<?> c = Class.forName(className, true, Reflect.class.getClassLoader()); 78 82 79 83 Method m = getMethod(c, method, args); 80 if (m.isAccessible() != accessible) 84 if (m.isAccessible() != accessible) { 81 85 m.setAccessible(accessible); 86 } 82 87 83 88 return m.invoke(null, args); … … 103 108 try { 104 109 Method m = getMethod(object.getClass(), method, args); 105 if (m.isAccessible() != accessible) 110 if (m.isAccessible() != accessible) { 106 111 m.setAccessible(accessible); 112 } 107 113 108 114 return m.invoke(object, args); 109 115 } catch (Exception ex) { // eat 110 ex.printStackTrace();116 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 111 117 return null; 112 118 } … … 117 123 * arguments. 118 124 */ 119 public Method getMethod(Class type, String method, Object args[]) {125 public Method getMethod(Class<?> type, String method, Object args[]) { 120 126 try { 121 for (Class c = type; c != null; c = c.getSuperclass()) {127 for (Class<?> c = type; c != null; c = c.getSuperclass()) { 122 128 Method methods[] = c.getMethods(); 123 129 … … 126 132 Class parameters[] = methods[i].getParameterTypes(); 127 133 128 if (parameters.length == args.length) 134 if (parameters.length == args.length) { 129 135 return methods[i]; 136 } 130 137 } 131 138 } 132 139 } 133 140 } catch (Exception ex) { // eat 134 ex.printStackTrace();141 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 135 142 } 136 143 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/TimedHashMap.java
r348 r429 38 38 package net.sourceforge.jnlp.util; 39 39 40 import net.sourceforge.jnlp.util.logging.OutputController; 40 41 import java.util.HashMap; 41 42 … … 83 84 // Item exists. If it has not expired, renew its access time and return it 84 85 if (age <= expiry) { 85 if (JNLPRuntime.isDebug()) { 86 System.err.println("Returning proxy " + actualMap.get(key) + " from cache for " + key); 87 } 86 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Returning proxy " + actualMap.get(key) + " from cache for " + key); 88 87 timeStamps.put(key, System.nanoTime()); 89 88 return actualMap.get(key); 90 89 } else { 91 if (JNLPRuntime.isDebug()) { 92 System.err.println("Proxy cache for " + key + " has expired (age=" + (age * 1e-9) + " seconds)"); 93 } 90 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Proxy cache for " + key + " has expired (age=" + (age * 1e-9) + " seconds)"); 94 91 } 95 92 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/UrlUtils.java
r348 r429 38 38 package net.sourceforge.jnlp.util; 39 39 40 import net.sourceforge.jnlp.util.logging.OutputController; 41 import java.io.File; 42 import java.io.IOException; 43 import java.io.UnsupportedEncodingException; 44 import java.net.MalformedURLException; 45 import java.net.URI; 46 import java.net.URISyntaxException; 40 47 import java.net.URL; 48 import java.net.URLDecoder; 49 import net.sourceforge.jnlp.JNLPFile; 41 50 42 51 public class UrlUtils { 52 private static final String UTF8 = "utf-8"; 53 54 public static URL normalizeUrlAndStripParams(URL url, boolean encodeFileUrls) { 55 try { 56 String[] urlParts = url.toString().split("\\?"); 57 URL strippedUrl = new URL(urlParts[0]); 58 return normalizeUrl(strippedUrl, encodeFileUrls); 59 } catch (IOException e) { 60 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 61 } catch (URISyntaxException e) { 62 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 63 } 64 return url; 65 } 66 67 public static URL normalizeUrlAndStripParams(URL url) { 68 return normalizeUrlAndStripParams(url, false); 69 } 43 70 44 71 public static boolean isLocalFile(URL url) { … … 51 78 return false; 52 79 } 80 81 /* Decode a percent-encoded URL. Catch checked exceptions and log. */ 82 public static URL decodeUrlQuietly(URL url) { 83 try { 84 return new URL(URLDecoder.decode(url.toString(), UTF8)); 85 } catch (IOException e) { 86 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 87 return url; 88 } 89 } 90 91 /* Use the URI syntax check of 'toURI' to see if it matches RFC2396. 92 * See http://www.ietf.org/rfc/rfc2396.txt */ 93 public static boolean isValidRFC2396Url(URL url) { 94 try { 95 url.toURI(); 96 return true; 97 } catch (URISyntaxException e) { 98 return false; 99 } 100 } 101 102 /* Ensure a URL is properly percent-encoded. 103 * Certain usages require local-file URLs to be encoded, eg for code-base & document-base. */ 104 public static URL normalizeUrl(URL url, boolean encodeFileUrls) throws MalformedURLException, UnsupportedEncodingException, URISyntaxException { 105 if (url == null) { 106 return null; 107 } 108 109 String protocol = url.getProtocol(); 110 boolean shouldEncode = (encodeFileUrls || !"file".equals(protocol)); 111 112 // PR1465: We should not call 'URLDecoder.decode' on RFC2396-compliant URLs 113 if (protocol == null || !shouldEncode || url.getPath() == null || isValidRFC2396Url(url)) { 114 return url; 115 } 116 117 //Decode the URL before encoding 118 URL decodedURL = new URL(URLDecoder.decode(url.toString(), UTF8)); 119 120 //Create URI with the decoded URL 121 URI uri = new URI(decodedURL.getProtocol(), null, decodedURL.getHost(), decodedURL.getPort(), decodedURL.getPath(), decodedURL.getQuery(), null); 122 123 //Returns the encoded URL 124 URL encodedURL = new URL(uri.toASCIIString()); 125 126 return encodedURL; 127 } 128 129 /* Ensure a URL is properly percent-encoded. Does not encode local-file URLs. */ 130 public static URL normalizeUrl(URL url) throws MalformedURLException, UnsupportedEncodingException, URISyntaxException { 131 return normalizeUrl(url, false); 132 } 133 134 /* Ensure a URL is properly percent-encoded. Catch checked exceptions and log. */ 135 public static URL normalizeUrlQuietly(URL url, boolean encodeFileUrls) { 136 try { 137 return normalizeUrl(url, encodeFileUrls); 138 } catch (MalformedURLException e) { 139 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 140 } catch (UnsupportedEncodingException e) { 141 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 142 } catch (URISyntaxException e) { 143 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 144 } 145 return url; 146 } 147 148 /* Ensure a URL is properly percent-encoded. Catch checked exceptions and log. */ 149 public static URL normalizeUrlQuietly(URL url) { 150 return normalizeUrlQuietly(url, false); 151 } 152 153 /* Decode a URL as a file, being tolerant of URLs with mixed encoded & decoded portions. */ 154 public static File decodeUrlAsFile(URL url) { 155 return new File(decodeUrlQuietly(url).getFile()); 156 } 157 158 /** 159 * This function i striping part behind last path delimiter. 160 * 161 * Expected is input like protcol://som.url/some/path/file.suff 162 * Then output will bee protcol://som.url/some/path 163 * 164 * Be aware of input like protcol://som.url/some/path/ 165 * then input will be just protcol://som.url/some/path 166 * 167 * You can use sanitizeLastSlash and see also unittests 168 * Both unix and windows salshes are supported 169 * 170 * @param src 171 * @return 172 */ 173 public static URL removeFileName(final URL src) { 174 URL nsrc = normalizeUrlAndStripParams(src); 175 String s = nsrc.getPath(); 176 int i1 = s.lastIndexOf("/"); 177 int i2 = s.lastIndexOf("\\"); 178 int i = Math.max(i1, i2); 179 if (i < 0) { 180 return src; 181 } 182 s = s.substring(0, i); 183 try { 184 return sanitizeLastSlash(new URL(src.getProtocol(), src.getHost(), src.getPort(), s)); 185 } catch (MalformedURLException ex) { 186 OutputController.getLogger().log(ex); 187 return nsrc; 188 } 189 } 190 191 /** 192 * Small utility function creating li list from collection of urls 193 * @param remoteUrls 194 * @return 195 */ 196 public static String setOfUrlsToHtmlList(Iterable<URL> remoteUrls) { 197 StringBuilder sb = new StringBuilder(); 198 sb.append("<ul>"); 199 for (URL url : remoteUrls) { 200 sb.append("<li>").append(url.toExternalForm()).append("</li>"); 201 } 202 sb.append("</ul>"); 203 return sb.toString(); 204 } 205 206 /** 207 * This function is removing all tailing slashes of url and 208 * both unix and windows salshes are supported. 209 * See tests for valid and invalid inputs/outputs 210 * Shortly protcol://som.url/some/path/ or protcol://som.url/some/path//// 211 * (and same for windows protcol://som.url/some\path\\) will become protcol://som.url/some/path 212 * Even protcol://som.url/ is reduced to protcol://som.url 213 * 214 * 215 * When input is like 216 * @param in 217 * @return 218 * @throws MalformedURLException 219 */ 220 public static URL sanitizeLastSlash(URL in) throws MalformedURLException { 221 if (in == null) { 222 return null; 223 } 224 String s = sanitizeLastSlash(in.toExternalForm()); 225 return new URL(s); 226 } 227 228 public static String sanitizeLastSlash(final String in) { 229 if (in == null) { 230 return null; 231 } 232 String s = in; 233 while (s.endsWith("/") || s.endsWith("\\")) { 234 s = s.substring(0, s.length() - 1); 235 } 236 return s; 237 } 238 239 /** 240 * both urls are processed by sanitizeLastSlash before actual equals. 241 * So protcol://som.url/some/path/ is same as protcol://som.url/some/path. 242 * Even protcol://som.url/some/path\ is same as protcol://som.url/some/path/ 243 * 244 * @param u1 245 * @param u2 246 * @return 247 */ 248 public static boolean equalsIgnoreLastSlash(URL u1, URL u2) { 249 try { 250 if (u1 == null && u2 == null) { 251 return true; 252 } 253 if (u1 == null && u2 != null) { 254 return false; 255 } 256 if (u1 != null && u2 == null) { 257 return false; 258 } 259 return sanitizeLastSlash(u1).equals(sanitizeLastSlash(u2)); 260 } catch (MalformedURLException ex) { 261 throw new RuntimeException(ex); 262 } 263 } 264 265 public static URL guessCodeBase(JNLPFile file) { 266 if (file.getCodeBase() != null) { 267 return file.getCodeBase(); 268 } else { 269 //Fixme: codebase should be the codebase of the Main Jar not 270 //the location. Although, it still works in the current state. 271 return file.getResources().getMainJAR().getLocation(); 272 } 273 } 53 274 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/WeakList.java
r348 r429 26 26 * may return null). The weak references are only removed when 27 27 * the trimToSize method is called so that the indices remain 28 * constant otherwise. <p>28 * constant otherwise. 29 29 * 30 30 * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/XDesktopEntry.java
r348 r429 17 17 package net.sourceforge.jnlp.util; 18 18 19 import net.sourceforge.jnlp.util.logging.OutputController; 20 import java.io.BufferedReader; 19 21 import java.io.File; 20 22 import java.io.FileNotFoundException; 21 23 import java.io.FileOutputStream; 24 import java.io.FileReader; 22 25 import java.io.IOException; 23 26 import java.io.OutputStreamWriter; … … 26 29 import java.net.URL; 27 30 import java.nio.charset.Charset; 31 import java.util.ArrayList; 28 32 import java.util.Arrays; 33 import java.util.Collections; 34 import java.util.Comparator; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Map.Entry; 38 import java.util.Set; 29 39 30 40 import net.sourceforge.jnlp.IconDesc; … … 79 89 String fileContents = "[Desktop Entry]\n"; 80 90 fileContents += "Version=1.0\n"; 81 fileContents += "Name=" + sanitize(file.getTitle()) + "\n";91 fileContents += "Name=" + getDesktopIconName() + "\n"; 82 92 fileContents += "GenericName=Java Web Start Application\n"; 83 93 fileContents += "Comment=" + sanitize(file.getInformation().getDescription()) + "\n"; … … 93 103 } 94 104 95 //Shortcut executes the jnlp from cache and system preferred java..96 fileContents += "Exec=" + "javaws" + " \"" + cacheFile.getAbsolutePath() + "\"\n";105 //Shortcut executes the jnlp as it was with system preferred java. It should work fine offline 106 fileContents += "Exec=" + "javaws" + " \"" + file.getSourceLocation() + "\"\n"; 97 107 98 108 return new StringReader(fileContents); … … 123 133 } 124 134 135 public File getShortcutTmpFile() { 136 String userTmp = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_TMP_DIR); 137 File shortcutFile = new File(userTmp + File.separator + FileUtils.sanitizeFileName(file.getTitle()) + ".desktop"); 138 return shortcutFile; 139 } 140 125 141 /** 126 142 * Set the icon size to use for the desktop shortcut … … 141 157 installDesktopLauncher(); 142 158 } catch (Exception e) { 143 e.printStackTrace();159 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 144 160 } 145 161 } … … 149 165 */ 150 166 private void installDesktopLauncher() { 151 File shortcutFile = new File(JNLPRuntime.getConfiguration() 152 .getProperty(DeploymentConfiguration.KEY_USER_TMP_DIR) 153 + File.separator + FileUtils.sanitizeFileName(file.getTitle()) + ".desktop"); 167 File shortcutFile = getShortcutTmpFile(); 154 168 try { 155 169 … … 183 197 String[] execString = new String[] { "xdg-desktop-icon", "install", "--novendor", 184 198 shortcutFile.getCanonicalPath() }; 185 if (JNLPRuntime.isDebug()) { 186 System.err.println("Execing: " + Arrays.toString(execString)); 187 } 199 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Execing: " + Arrays.toString(execString)); 188 200 Process installer = Runtime.getRuntime().exec(execString); 189 201 new StreamEater(installer.getInputStream()).start(); … … 193 205 installer.waitFor(); 194 206 } catch (InterruptedException e) { 195 e.printStackTrace();207 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 196 208 } 197 209 … … 201 213 202 214 } catch (FileNotFoundException e) { 203 e.printStackTrace();215 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 204 216 } catch (IOException e) { 205 e.printStackTrace();217 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 206 218 } 207 219 } … … 229 241 this.iconLocation = location.substring("file:".length()); 230 242 231 if (JNLPRuntime.isDebug()) { 232 System.err.println("Cached desktop shortcut icon: " + this.iconLocation); 233 } 234 } 235 } 236 243 OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Cached desktop shortcut icon: " + this.iconLocation); 244 } 245 } 246 247 public String getDesktopIconName() { 248 return sanitize(file.getTitle()); 249 } 250 251 public File getLinuxDesktopIconFile() { 252 return new File(findFreedesktopOrgDesktopPathCatch() + "/" + getDesktopIconName() + ".desktop"); 253 } 254 255 private static String findFreedesktopOrgDesktopPathCatch() { 256 try { 257 return findFreedesktopOrgDesktopPath(); 258 } catch (Exception ex) { 259 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); 260 return System.getProperty("user.home") + "/Desktop/"; 261 } 262 } 263 264 /** 265 * Instead of having all this parsing of user-dirs.dirs and replacing 266 * variables we can execute `echo $(xdg-user-dir DESKTOP)` and it will do 267 * all the job in case approaches below become failing 268 * 269 * @return variables (if declared) and quotation marks (unless escaped) free 270 * path 271 * @throws IOException if no file do not exists or key with desktop do not 272 * exists 273 */ 274 private static String findFreedesktopOrgDesktopPath() throws IOException { 275 File userDirs = new File(System.getProperty("user.home") + "/.config/user-dirs.dirs"); 276 if (!userDirs.exists()) { 277 return System.getProperty("user.home") + "/Desktop/"; 278 } 279 return getFreedesktopOrgDesktopPathFrom(userDirs); 280 } 281 282 private static String getFreedesktopOrgDesktopPathFrom(File userDirs) throws IOException { 283 BufferedReader r = new BufferedReader(new FileReader(userDirs)); 284 try { 285 return getFreedesktopOrgDesktopPathFrom(r); 286 } finally { 287 r.close(); 288 } 289 290 } 291 static final String XDG_DESKTOP_DIR = "XDG_DESKTOP_DIR"; 292 293 static String getFreedesktopOrgDesktopPathFrom(BufferedReader r) throws IOException { 294 while (true) { 295 String s = r.readLine(); 296 if (s == null) { 297 throw new IOException("End of user-dirs found, but no " + XDG_DESKTOP_DIR + " key found"); 298 } 299 s = s.trim(); 300 if (s.startsWith(XDG_DESKTOP_DIR)) { 301 if (!s.contains("=")) { 302 throw new IOException(XDG_DESKTOP_DIR + " has no value"); 303 } 304 String[] keyAndValue = s.split("="); 305 keyAndValue[1] = keyAndValue[1].trim(); 306 String filteredQuotes = filterQuotes(keyAndValue[1]); 307 return evaluateLinuxVariables(filteredQuotes); 308 } 309 } 310 } 311 private static final String MIC = "MAGIC_QUOTIN_ITW_CONSTANT_FOR_DUMMIES"; 312 313 private static String filterQuotes(String string) { 314 //get rid of " but not of 315 String s = string.replaceAll("\\\\\"", MIC); 316 s = s.replaceAll("\"", ""); 317 s = s.replaceAll(MIC, "\\\""); 318 return s; 319 } 320 321 private static String evaluateLinuxVariables(String orig) { 322 return evaluateLinuxVariables(orig, System.getenv()); 323 } 324 325 private static String evaluateLinuxVariables(String orig, Map<String, String> variables) { 326 Set<Entry<String, String>> env = variables.entrySet(); 327 List<Entry<String, String>> envVariables = new ArrayList<Entry<String, String>>(env); 328 Collections.sort(envVariables, new Comparator<Entry<String, String>>() { 329 @Override 330 public int compare(Entry<String, String> o1, Entry<String, String> o2) { 331 return o2.getKey().length() - o1.getKey().length(); 332 } 333 }); 334 while (true) { 335 String before = orig; 336 for (Entry<String, String> entry : envVariables) { 337 orig = orig.replaceAll("\\$" + entry.getKey(), entry.getValue()); 338 } 339 if (before.equals(orig)) { 340 return orig; 341 } 342 } 343 344 } 237 345 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/replacements/CharacterEncoder.java
r418 r429 40 40 * data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text) 41 41 * for transmition over text channels such as e-mail and network news. 42 * 42 * <p> 43 43 * The character encoders have been structured around a central theme 44 44 * that, in general, the encoded text has the form: 45 * 46 * <pre> 45 * <pre><code> 47 46 * [Buffer Prefix] 48 47 * [Line Prefix][encoded data atoms][Line Suffix] 49 48 * [Buffer Suffix] 50 * </pre> 51 * 52 * In the CharacterEncoder and CharacterDecoder classes, one complete 53 * chunk of data is referred to as a <i>buffer</i>. Encoded buffers 54 * are all text, and decoded buffers (sometimes just referred to as 55 * buffers) are binary octets. 56 * 57 * To create a custom encoder, you must, at a minimum, overide three 49 * </code></pre> 50 * </p> 51 * <p> 52 * In the {@code CharacterEncoder} and {@link CharacterDecoder} 53 * classes, one complete chunk of data is referred to as a 54 * <i>buffer</i>. Encoded buffers are all text, and decoded buffers 55 * (sometimes just referred to as buffers) are binary octets. 56 * </p> 57 * <p> 58 * To create a custom encoder, you must, at a minimum, overide three 58 59 * abstract methods in this class. 59 * < DL>60 * < DD>bytesPerAtom which tells the encoder how many bytes to60 * <dl> 61 * <dd/>bytesPerAtom which tells the encoder how many bytes to 61 62 * send to encodeAtom 62 * < DD>encodeAtom which encodes the bytes sent to it as text.63 * < DD>bytesPerLine which tells the encoder the maximum number of63 * <dd/>encodeAtom which encodes the bytes sent to it as text. 64 * <dd/>bytesPerLine which tells the encoder the maximum number of 64 65 * bytes per line. 65 * </DL> 66 * 66 * </dl> 67 * </p> 68 * <p> 67 69 * Several useful encoders have already been written and are 68 70 * referenced in the See Also list below. 69 * 71 * </p> 70 72 * @author Chuck McManis 71 * @see CharacterDecoder; 72 * @see UCEncoder 73 * @see UUEncoder 73 * @see CharacterDecoder 74 74 * @see BASE64Encoder 75 75 */ … … 201 201 /** 202 202 * Return a byte array from the remaining bytes in this ByteBuffer. 203 * <P> 204 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 205 * <P> 203 * <p> 204 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 205 * </p> 206 * <p> 206 207 * To avoid an extra copy, the implementation will attempt to return the 207 208 * byte array backing the ByteBuffer. If this is not possible, a 208 209 * new byte array will be created. 210 * </p> 209 211 */ 210 212 private byte [] getBytes(ByteBuffer bb) { … … 248 250 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 249 251 * result to the OutputStream <i>aStream</i>. 250 * <P> 251 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 252 * <p> 253 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 254 * </p> 252 255 */ 253 256 public void encode(ByteBuffer aBuffer, OutputStream aStream) … … 260 263 * A 'streamless' version of encode that simply takes a ByteBuffer 261 264 * and returns a string containing the encoded buffer. 262 * <P> 263 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 265 * <p> 266 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 267 * </p> 264 268 */ 265 269 public String encode(ByteBuffer aBuffer) { … … 332 336 * Encode the <i>aBuffer</i> ByteBuffer and write the encoded 333 337 * result to the OutputStream <i>aStream</i>. 334 * <P> 335 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 338 * <p> 339 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 340 * </p> 336 341 */ 337 342 public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream) … … 344 349 * A 'streamless' version of encode that simply takes a ByteBuffer 345 350 * and returns a string containing the encoded buffer. 346 * <P> 347 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 351 * <p> 352 * The ByteBuffer's position will be advanced to ByteBuffer's limit. 353 * </p> 348 354 */ 349 355 public String encodeBuffer(ByteBuffer aBuffer) { -
trunk/icedtea-web/netx/net/sourceforge/nanoxml/XMLElement.java
r418 r429 35 35 36 36 import net.sourceforge.jnlp.runtime.JNLPRuntime; 37 import net.sourceforge.jnlp.util.logging.OutputController; 37 38 38 39 /** 39 40 * XMLElement is a representation of an XML object. The object is able to parse 40 41 * XML code. 41 * < P><DL>42 * < DT><B>Parsing XML Data</B></DT>43 * < DD>42 * <p><dl> 43 * <dt><b>Parsing XML Data</b></dt> 44 * <dd> 44 45 * You can parse XML data using the following code: 45 * < UL><CODE>46 * XMLElement xml = new XMLElement();<BR>47 * FileReader reader = new FileReader("filename.xml");<BR>48 * 49 * </CODE></UL></DD></DL>50 * < DL><DT><B>Retrieving Attributes</B></DT>51 * < DD>46 * <pre>{@code 47 *XMLElement xml = new XMLElement(); 48 *FileReader reader = new FileReader("filename.xml"); 49 *xml.parseFromReader(reader); 50 *}</pre></dd></dl> 51 * <dl><dt><b>Retrieving Attributes</b></dt> 52 * <dd> 52 53 * You can enumerate the attributes of an element using the method 53 54 * {@link #enumerateAttributeNames() enumerateAttributeNames}. … … 55 56 * {@link #getAttribute(java.lang.String) getAttribute}. 56 57 * The following example shows how to list the attributes of an element: 57 * <UL><CODE> 58 * XMLElement element = ...;<BR> 59 * Enumeration enum = element.enumerateAttributeNames();<BR> 60 * while (enum.hasMoreElements()) {<BR> 61 * String key = (String) enum.nextElement();<BR> 62 * String value = (String) element.getAttribute(key);<BR> 63 * System.out.println(key + " = " + value);<BR> 64 * } 65 * </CODE></UL></DD></DL> 66 * <DL><DT><B>Retrieving Child Elements</B></DT> 67 * <DD> 58 * <pre>{@code 59 *XMLElement element = ...; 60 *Enumeration enum = element.enumerateAttributeNames(); 61 *while (enum.hasMoreElements()) { 62 * String key = (String) enum.nextElement(); 63 * String value = (String) element.getAttribute(key); 64 * System.out.println(key + " = " + value); 65 *}}</pre></dd></dl> 66 * <dl><dt><b>Retrieving Child Elements</b></dt> 67 * <dd> 68 68 * You can enumerate the children of an element using 69 69 * {@link #enumerateChildren() enumerateChildren}. 70 70 * The number of child elements can be retrieved using 71 71 * {@link #countChildren() countChildren}. 72 * </ DD></DL>73 * < DL><DT><B>Elements Containing Character Data</B></DT>74 * < DD>72 * </dd></dl> 73 * <dl><dt><b>Elements Containing Character Data</b></dt> 74 * <dd> 75 75 * If an elements contains character data, like in the following example: 76 * <UL><CODE> 77 * <title>The Title</title> 78 * </CODE></UL> 76 * <pre>{@code <title>The Title</title>}</pre> 79 77 * you can retrieve that data using the method 80 78 * {@link #getContent() getContent}. 81 * </ DD></DL>82 * < DL><DT><B>Subclassing XMLElement</B></DT>83 * < DD>79 * </dd></dl> 80 * <dl><dt><b>Subclassing XMLElement</b></dt> 81 * <dd> 84 82 * When subclassing XMLElement, you need to override the method 85 83 * {@link #createAnotherElement() createAnotherElement} 86 84 * which has to return a new copy of the receiver. 87 * </ DD></DL>88 * < P>85 * </dd></dl> 86 * </p> 89 87 * 90 88 * @see net.sourceforge.nanoxml.XMLParseException … … 100 98 * 101 99 * <dl><dt><b>Invariants:</b></dt><dd> 102 * <ul><li>The field can be empty. 103 * <li>The field is never <code>null</code>.104 * <li>The keys and the values are strings. 100 * <ul><li>The field can be empty.</li> 101 * <li>The field is never {@code null}.</li> 102 * <li>The keys and the values are strings.</li> 105 103 * </ul></dd></dl> 106 104 */ … … 111 109 * 112 110 * <dl><dt><b>Invariants:</b></dt><dd> 113 * <ul><li>The field can be empty. 114 * <li>The field is never <code>null</code>.115 * <li>The elements are instances of <code>XMLElement</code>116 * or a subclass of <code>XMLElement</code>.111 * <ul><li>The field can be empty.</li> 112 * <li>The field is never {@code null}.</li> 113 * <li>The elements are instances of {@code XMLElement} 114 * or a subclass of {@code XMLElement}.</li> 117 115 * </ul></dd></dl> 118 116 */ … … 123 121 * 124 122 * <dl><dt><b>Invariants:</b></dt><dd> 125 * <ul><li>The field is <code>null</code>iff the element is not126 * initialized by either parse or setName.127 * <li>If the field is not <code>null</code>, it's not empty.128 * <li>If the field is not <code>null</code>, it contains a valid129 * XML identifier. 123 * <ul><li>The field is {@code null} iff the element is not 124 * initialized by either parse or {@link #setName setName()}.</li> 125 * <li>If the field is not {@code null}, it's not empty.</li> 126 * <li>If the field is not {@code null}, it contains a valid 127 * XML identifier.</li> 130 128 * </ul></dd></dl> 131 129 */ … … 133 131 134 132 /** 135 * The #PCDATAcontent of the object.133 * The {@code #PCDATA} content of the object. 136 134 * 137 135 * <dl><dt><b>Invariants:</b></dt><dd> 138 * <ul><li>The field is <code>null</code>iff the element is not a139 * #PCDATA element.140 * <li>The field can be any string, including the empty string. 136 * <ul><li>The field is {@code null} iff the element is not a 137 * {@code #PCDATA} element.</li> 138 * <li>The field can be any string, including the empty string.</li> 141 139 * </ul></dd></dl> 142 140 */ … … 148 146 * 149 147 * <dl><dt><b>Invariants:</b></dt><dd> 150 * <ul><li>The field is never <code>null</code>.148 * <ul><li>The field is never {@code null}.</li> 151 149 * <li>The field always contains the following associations: 152 150 * "lt" => "<", "gt" => ">", 153 151 * "quot" => "\"", "apos" => "'", 154 * "amp" => "&" 155 * <li>The keys are strings 156 * <li>The values are char arrays 152 * "amp" => "&"</li> 153 * <li>The keys are strings</li> 154 * <li>The values are char arrays</li> 157 155 * </ul></dd></dl> 158 156 */ … … 163 161 * 164 162 * <dl><dt><b>Invariants:</b></dt><dd> 165 * <ul><li> <code>lineNr >= 0</code>163 * <ul><li>{@code lineNr >= 0}</li> 166 164 * </ul></dd></dl> 167 165 */ … … 169 167 170 168 /** 171 * <code>true</code> if the case of the element and attribute names172 * are caseinsensitive.169 * {@code true} if the case of the element and attribute names are case 170 * insensitive. 173 171 */ 174 172 private boolean ignoreCase; 175 173 176 174 /** 177 * <code>true</code> if the leading and trailing whitespace of #PCDATA175 * {@code true} if the leading and trailing whitespace of {@code #PCDATA} 178 176 * sections have to be ignored. 179 177 */ … … 181 179 182 180 /** 183 * Character read too much. 181 * Character read too much.<br/> 184 182 * This character provides push-back functionality to the input reader 185 183 * without having to use a PushbackReader. 186 * If there is no such character, this field is '\0'.184 * If there is no such character, this field is {@code '\0'}. 187 185 */ 188 186 private char charReadTooMuch; … … 197 195 * 198 196 * <dl><dt><b>Invariants:</b></dt><dd> 199 * <ul><li>The field is not <code>null</code> while the parse method200 * is running.197 * <ul><li>The field is not {@code null} while the parse method is 198 * running.</li> 201 199 * </ul></dd></dl> 202 200 */ … … 207 205 * 208 206 * <dl><dt><b>Invariants:</b></dt><dd> 209 * <ul><li>parserLineNr > 0 while the parse method is running. 207 * <ul><li>parserLineNr > 0 while the parse method is running.</li> 210 208 * </ul></dd></dl> 211 209 */ … … 213 211 214 212 /** 215 * Creates and initializes a new XML element. 213 * Creates and initializes a new XML element.<br/> 216 214 * Calling the construction is equivalent to: 217 * <ul><code>new XMLElement(new Hashtable(), false, true) 218 * </code></ul> 215 * <ul><li>{@code new XMLElement(new Hashtable(), false, true)}</li></ul> 219 216 * 220 217 * <dl><dt><b>Postconditions:</b></dt><dd> 221 * <ul><li>countChildren() => 0 222 * <li>enumerateChildren() => empty enumeration 223 * <li>enumeratePropertyNames() => empty enumeration 224 * <li>getChildren() => empty vector 225 * <li>getContent() => "" 226 * <li>getLineNr() => 0 227 * <li>getName() => null 228 * </ul></dd></dl> 229 * 218 * <ul><li>{@linkplain #countChildren} => 0</li> 219 * <li>{@linkplain #enumerateChildren} => empty enumeration</li> 220 * <li>enumeratePropertyNames() => empty enumeration</li> 221 * <li>getChildren() => empty vector</li> 222 * <li>{@linkplain #getContent} => ""</li> 223 * <li>{@linkplain #getLineNr} => 0</li> 224 * <li>{@linkplain #getName} => null</li> 225 * </ul></dd></dl> 230 226 */ 231 227 public XMLElement() { … … 235 231 /** 236 232 * Creates and initializes a new XML element. 237 * <P> 238 * This constructor should <I>only</I> be called from 239 * {@link #createAnotherElement() createAnotherElement} 240 * to create child elements. 233 * <p> 234 * This constructor should <i>only</i> be called from 235 * {@link #createAnotherElement} to create child elements. 241 236 * 242 237 * @param entities 243 238 * The entity conversion table. 244 239 * @param skipLeadingWhitespace 245 * <code>true</code>if leading and trailing whitespace in PCDATA240 * {@code true} if leading and trailing whitespace in PCDATA 246 241 * content has to be removed. 247 242 * @param fillBasicConversionTable 248 * <code>true</code>if the basic entities need to be added to243 * {@code true} if the basic entities need to be added to 249 244 * the entity list (client code calling this constructor). 250 245 * @param ignoreCase 251 * <code>true</code>if the case of element and attribute names have246 * {@code true} if the case of element and attribute names have 252 247 * to be ignored. 253 248 * 254 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>255 * <ul><li> <code>entities != null</code>256 * <li>if <code>fillBasicConversionTable == false</code>257 * then <code>entities</code>contains at least the following258 * entries: <code>amp</code>, <code>lt</code>, <code>gt</code>,259 * <code>apos</code> and <code>quot</code>249 * <dl><dt><b>Preconditions:</b></dt><dd> 250 * <ul><li>{@code entities != null}</li> 251 * <li>if {@code fillBasicConversionTable == false} 252 * then {@code entities} contains at least the following 253 * entries: {@code amp}, {@code lt}, {@code gt}, {@code apos} and 254 * {@code quot}</li> 260 255 * </ul></dd></dl> 261 256 * 262 257 * <dl><dt><b>Postconditions:</b></dt><dd> 263 * <ul><li>countChildren() => 0 264 * <li>enumerateChildren() => empty enumeration 265 * <li>enumeratePropertyNames() => empty enumeration 266 * <li>getChildren() => empty vector 267 * <li>getContent() => "" 268 * <li>getLineNr() => 0 269 * <li>getName() => null 270 * </ul></dd></dl><dl> 271 * 258 * <ul><li>{@linkplain #countChildren} => 0</li> 259 * <li>{@linkplain #enumerateChildren} => empty enumeration</li> 260 * <li>enumeratePropertyNames() => empty enumeration</li> 261 * <li>getChildren() => empty vector</li> 262 * <li>{@linkplain #getContent} => ""</li> 263 * <li>{@linkplain #getLineNr} => 0</li> 264 * <li>{@linkplain #getName} => null</li> 265 * </ul></dd></dl> 272 266 */ 273 267 protected XMLElement(Hashtable<String, char[]> entities, … … 306 300 * The child element to add. 307 301 * 308 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>309 * <ul><li> <code>child != null</code>310 * <li> <code>child.getName() != null</code>311 * <li> <code>child</code> does not have a parent element302 * <dl><dt><b>Preconditions:</b></dt><dd> 303 * <ul><li>{@code child != null}</li> 304 * <li>{@code child.getName() != null}</li> 305 * <li>{@code child} does not have a parent element</li> 312 306 * </ul></dd></dl> 313 307 * 314 308 * <dl><dt><b>Postconditions:</b></dt><dd> 315 * <ul><li>countChildren() => old.countChildren() + 1 316 * <li>enumerateChildren() => old.enumerateChildren() + child 317 * <li>getChildren() => old.enumerateChildren() + child 318 * </ul></dd></dl><dl> 309 * <ul><li>{@linkplain #countChildren} => old.countChildren() + 1</li> 310 * <li>{@linkplain #enumerateChildren} => old.enumerateChildren() 311 + child</li> 312 * <li>getChildren() => old.enumerateChildren() + child</li> 313 * </ul></dd></dl> 319 314 * 320 315 */ … … 331 326 * The value of the attribute. 332 327 * 333 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>334 * <ul><li> <code>name != null</code>335 * <li> <code>name</code> is a valid XML identifier336 * <li> <code>value != null</code>328 * <dl><dt><b>Preconditions:</b></dt><dd> 329 * <ul><li>{@code name != null}</li> 330 * <li>{@code name} is a valid XML identifier</li> 331 * <li>{@code value != null}</li> 337 332 * </ul></dd></dl> 338 333 * 339 334 * <dl><dt><b>Postconditions:</b></dt><dd> 340 * <ul><li> enumerateAttributeNames()341 * = > old.enumerateAttributeNames() + name342 * <li> getAttribute(name) => value343 * </ul></dd></dl><dl>344 * 335 * <ul><li>{@linkplain #enumerateAttributeNames} 336 * => old.enumerateAttributeNames() + name</li> 337 * <li>{@linkplain #getAttribute(java.lang.String) getAttribute(name)} 338 * => value</li> 339 * </ul></dd></dl> 345 340 */ 346 341 public void setAttribute(String name, … … 356 351 * 357 352 * <dl><dt><b>Postconditions:</b></dt><dd> 358 * <ul><li><code>result >= 0</code> 359 * </ul></dd></dl> 360 * 353 * <ul><li>{@code result >= 0}</li> 354 * </ul></dd></dl> 361 355 */ 362 356 public int countChildren() { … … 368 362 * 369 363 * <dl><dt><b>Postconditions:</b></dt><dd> 370 * <ul><li><code>result != null</code> 371 * </ul></dd></dl> 372 * 373 */ 374 public Enumeration enumerateAttributeNames() { 364 * <ul><li>{@code result != null}</li> 365 * </ul></dd></dl> 366 */ 367 public Enumeration<String> enumerateAttributeNames() { 375 368 return this.attributes.keys(); 376 369 } … … 380 373 * 381 374 * <dl><dt><b>Postconditions:</b></dt><dd> 382 * <ul><li><code>result != null</code> 383 * </ul></dd></dl> 384 * 385 */ 386 public Enumeration enumerateChildren() { 375 * <ul><li>{@code result != null}</li> 376 * </ul></dd></dl> 377 */ 378 public Enumeration<XMLElement> enumerateChildren() { 387 379 return this.children.elements(); 388 380 } … … 390 382 /** 391 383 * Returns the PCDATA content of the object. If there is no such content, 392 * <CODE>null</CODE> is returned. 393 * 384 * {@code null} is returned. 394 385 */ 395 386 public String getContent() { … … 399 390 /** 400 391 * Returns the line nr in the source data on which the element is found. 401 * This method returns <code>0</code>there is no associated source data.392 * This method returns {@code 0} there is no associated source data. 402 393 * 403 394 * <dl><dt><b>Postconditions:</b></dt><dd> 404 * <ul><li> <code>result >= 0</code>395 * <ul><li>{@code result >= 0}</li> 405 396 * </ul></dd></dl> 406 397 */ … … 410 401 411 402 /** 412 * Returns an attribute of the element. 413 * If the attribute doesn't exist, <code>null</code>is returned.403 * Returns an attribute of the element.<br/> 404 * If the attribute doesn't exist, {@code null} is returned. 414 405 * 415 406 * @param name The name of the attribute. 416 407 * 417 * </dl><dl><dt><b>Preconditions:</b></dt><dd> 418 * <ul><li><code>name != null</code> 419 * <li><code>name</code> is a valid XML identifier 420 * </ul></dd></dl><dl> 421 * 408 * <dl><dt><b>Preconditions:</b></dt><dd> 409 * <ul><li>{@code name != null}</li> 410 * <li>{@code name} is a valid XML identifier</li> 411 * </ul></dd></dl> 422 412 */ 423 413 public Object getAttribute(String name) { … … 431 421 /** 432 422 * Returns the name of the element. 433 * 423 * @return this {@code XMLElement} object's name 434 424 */ 435 425 public String getName() { … … 438 428 439 429 /** 440 * Reads one XML element from a java.io.Readerand parses it.430 * Reads one XML element from a {@link java.io.Reader} and parses it. 441 431 * 442 432 * @param reader 443 433 * The reader from which to retrieve the XML data. 444 434 * 445 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>446 * <ul><li> <code>reader != null</code>447 * <li> <code>reader</code> is not closed435 * <dl><dt><b>Preconditions:</b></dt><dd> 436 * <ul><li>{@code reader != null}</li> 437 * <li>{@code reader} is not closed</li> 448 438 * </ul></dd></dl> 449 439 * 450 440 * <dl><dt><b>Postconditions:</b></dt><dd> 451 441 * <ul><li>the state of the receiver is updated to reflect the XML element 452 * parsed from the reader 442 * parsed from the reader</li> 453 443 * <li>the reader points to the first character following the last 454 * '>' character of the XML element455 * </ul></dd></dl> <dl>444 * {@code '>'} character of the XML element</li> 445 * </ul></dd></dl> 456 446 * 457 447 * @throws java.io.IOException … … 473 463 * The line number of the first line in the data. 474 464 * 475 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>476 * <ul><li> <code>reader != null</code>477 * <li> <code>reader</code> is not closed465 * <dl><dt><b>Preconditions:</b></dt><dd> 466 * <ul><li>{@code reader != null}</li> 467 * <li>{@code reader} is not closed</li> 478 468 * </ul></dd></dl> 479 469 * 480 470 * <dl><dt><b>Postconditions:</b></dt><dd> 481 471 * <ul><li>the state of the receiver is updated to reflect the XML element 482 * parsed from the reader 472 * parsed from the reader</li> 483 473 * <li>the reader points to the first character following the last 484 * '>' character of the XML element485 * </ul></dd></dl> <dl>474 * {@code '>'} character of the XML element</li> 475 * </ul></dd></dl> 486 476 * 487 477 * @throws java.io.IOException … … 518 508 /** 519 509 * Creates a new similar XML element. 520 * < P>510 * <p> 521 511 * You should override this method when subclassing XMLElement. 512 * </p> 522 513 */ 523 514 protected XMLElement createAnotherElement() { … … 544 535 * The new name. 545 536 * 546 * </dl><dl><dt><b>Preconditions:</b></dt><dd> 547 * <ul><li><code>name != null</code> 548 * <li><code>name</code> is a valid XML identifier 549 * </ul></dd></dl> 550 * 537 * <dl><dt><b>Preconditions:</b></dt><dd> 538 * <ul><li{@code name != null}</li> 539 * <li>{@code name} is a valid XML identifier</li> 540 * </ul></dd></dl> 551 541 */ 552 542 public void setName(String name) { … … 561 551 * The buffer in which the scanned identifier will be put. 562 552 * 563 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>564 * <ul><li> <code>result != null</code>553 * <dl><dt><b>Preconditions:</b></dt><dd> 554 * <ul><li>{@code result != null}</li> 565 555 * <li>The next character read from the reader is a valid first 566 * character of an XML identifier. 556 * character of an XML identifier.</li> 567 557 * </ul></dd></dl> 568 558 * 569 559 * <dl><dt><b>Postconditions:</b></dt><dd> 570 560 * <ul><li>The next character read from the reader won't be an identifier 571 * character. 572 * </ul></dd></dl> <dl>561 * character.</li> 562 * </ul></dd></dl> 573 563 */ 574 564 protected void scanIdentifier(StringBuffer result) … … 608 598 609 599 /** 610 * This method scans an identifier from the current reader. 611 * The scanned whitespace is appended to <code>result</code>.600 * This method scans an identifier from the current reader.<br/> 601 * The scanned whitespace is appended to {@code result}. 612 602 * 613 603 * @return the next character following the whitespace. 614 604 * 615 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>616 * <ul><li> <code>result != null</code>605 * <dl><dt><b>Preconditions:</b></dt><dd> 606 * <ul><li>{@code result != null}</li> 617 607 * </ul></dd></dl> 618 608 */ … … 636 626 637 627 /** 638 * This method scans a delimited string from the current reader. 639 * The scanned string without delimiters is appended to 640 * <code>string</code>. 641 * 642 * </dl><dl><dt><b>Preconditions:</b></dt><dd> 643 * <ul><li><code>string != null</code> 644 * <li>the next char read is the string delimiter 628 * This method scans a delimited string from the current reader.<br/> 629 * The scanned string without delimiters is appended to {@code string}. 630 * 631 * <dl><dt><b>Preconditions:</b></dt><dd> 632 * <ul><li>{@code string != null}</li> 633 * <li>the next char read is the string delimiter</li> 645 634 * </ul></dd></dl> 646 635 */ … … 664 653 665 654 /** 666 * Scans a #PCDATA element. CDATA sections and entities are resolved. 667 * The next < char is skipped. 668 * The scanned data is appended to <code>data</code>. 669 * 670 * </dl><dl><dt><b>Preconditions:</b></dt><dd> 671 * <ul><li><code>data != null</code> 655 * Scans a {@code #PCDATA} element. CDATA sections and entities are 656 * resolved.<br/> 657 * The next < char is skipped.<br/> 658 * The scanned data is appended to {@code data}. 659 * 660 * <dl><dt><b>Preconditions:</b></dt><dd> 661 * <ul><li>{@code data != null}</li> 672 662 * </ul></dd></dl> 673 663 */ … … 694 684 /** 695 685 * Scans a special tag and if the tag is a CDATA section, append its 696 * content to <code>buf</code>.697 * 698 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>699 * <ul><li> <code>buf != null</code>700 * <li>The first < has already been read. 686 * content to {@code buf}. 687 * 688 * <dl><dt><b>Preconditions:</b></dt><dd> 689 * <ul><li>{@code buf != null}</li> 690 * <li>The first < has already been read.</li> 701 691 * </ul></dd></dl> 702 692 */ … … 751 741 * Skips a comment. 752 742 * 753 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>754 * <ul><li>The first <!-- has already been read. 743 * <dl><dt><b>Preconditions:</b></dt><dd> 744 * <ul><li>The first <!-- has already been read.</li> 755 745 * </ul></dd></dl> 756 746 */ … … 791 781 * already been read. 792 782 * 793 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>794 * <ul><li>The first <! has already been read. 795 * <li> <code>bracketLevel >= 0</code>783 * <dl><dt><b>Preconditions:</b></dt><dd> 784 * <ul><li>The first <! has already been read.</li> 785 * <li>{@code bracketLevel >= 0}</li> 796 786 * </ul></dd></dl> 797 787 */ … … 842 832 843 833 /** 844 * Scans the data for literal text. 834 * Scans the data for literal text.<br/> 845 835 * Scanning stops when a character does not match or after the complete 846 836 * text has been checked, whichever comes first. … … 848 838 * @param literal the literal to check. 849 839 * 850 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>851 * <ul><li> <code>literal != null</code>840 * <dl><dt><b>Preconditions:</b></dt><dd> 841 * <ul><li>{@code literal != null}</li> 852 842 * </ul></dd></dl> 853 843 */ … … 890 880 * @param elt The element that will contain the result. 891 881 * 892 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>893 * <ul><li>The first < has already been read. 894 * <li> <code>elt != null</code>882 * <dl><dt><b>Preconditions:</b></dt><dd> 883 * <ul><li>The first < has already been read.</li> 884 * <li>{@code elt != null}</li> 895 885 * </ul></dd></dl> 896 886 */ … … 996 986 997 987 /** 998 * Resolves an entity. The name of the entity is read from the reader. 999 * The value of the entity is appended to <code>buf</code>.988 * Resolves an entity. The name of the entity is read from the reader.<br/> 989 * The value of the entity is appended to {@code buf}. 1000 990 * 1001 991 * @param buf Where to put the entity value. 1002 992 * 1003 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1004 * <ul><li>The first & has already been read. 1005 * <li> <code>buf != null</code>993 * <dl><dt><b>Preconditions:</b></dt><dd> 994 * <ul><li>The first & has already been read.</li> 995 * <li>{@code buf != null}</li> 1006 996 * </ul></dd></dl> 1007 997 */ … … 1043 1033 * @param ch The character to push back. 1044 1034 * 1045 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1046 * <ul><li>The read-back buffer is empty. 1047 * <li> <code>ch != '\0'</code>1035 * <dl><dt><b>Preconditions:</b></dt><dd> 1036 * <ul><li>The read-back buffer is empty.</li> 1037 * <li>{@code ch != '\0'}</li> 1048 1038 * </ul></dd></dl> 1049 1039 */ … … 1058 1048 * @param name The name of the entity. 1059 1049 * 1060 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1061 * <ul><li> <code>name != null</code>1050 * <dl><dt><b>Preconditions:</b></dt><dd> 1051 * <ul><li>{@code name != null}</li> 1062 1052 * </ul></dd></dl> 1063 1053 */ … … 1074 1064 * @param value The value of the entity. 1075 1065 * 1076 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1077 * <ul><li> <code>name != null</code>1078 * <li> <code>value != null</code>1066 * <dl><dt><b>Preconditions:</b></dt><dd> 1067 * <ul><li>{@code name != null}</li> 1068 * <li>{@code value != null}</li> 1079 1069 * </ul></dd></dl> 1080 1070 */ … … 1100 1090 * @param context The context in which the error occured. 1101 1091 * 1102 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1103 * <ul><li> <code>context != null</code>1104 * <li> <code>context.length() > 0</code>1092 * <dl><dt><b>Preconditions:</b></dt><dd> 1093 * <ul><li>{@code context != null}</li> 1094 * <li>{@code context.length() > 0}</li> 1105 1095 * </ul></dd></dl> 1106 1096 */ … … 1117 1107 * expected. 1118 1108 * 1119 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1120 * <ul><li> <code>charSet != null</code>1121 * <li> <code>charSet.length() > 0</code>1109 * <dl><dt><b>Preconditions:</b></dt><dd> 1110 * <ul><li>{@code charSet != null}</li> 1111 * <li>{@code charSet.length() > 0}</li> 1122 1112 * </ul></dd></dl> 1123 1113 */ … … 1134 1124 * expected. 1135 1125 * @param ch The character that was received instead. 1136 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1137 * <ul><li> <code>charSet != null</code>1138 * <li> <code>charSet.length() > 0</code>1126 * <dl><dt><b>Preconditions:</b></dt><dd> 1127 * <ul><li>{@code charSet != null}</li> 1128 * <li>{@code charSet.length() > 0}</li> 1139 1129 * </ul></dd></dl> 1140 1130 */ … … 1149 1139 * @param name The name of the entity. 1150 1140 * 1151 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>1152 * <ul><li> <code>name != null</code>1153 * <li> <code>name.length() > 0</code>1141 * <dl><dt><b>Preconditions:</b></dt><dd> 1142 * <ul><li>{@code name != null}</li> 1143 * <li>{@code name.length() > 0}</li> 1154 1144 * </ul></dd></dl> 1155 1145 */ … … 1163 1153 * xml code. 1164 1154 * 1165 * @param isr The reader of the InputStreamcontaining the xml.1166 * @param pout The PipedOutputStream that will be receiving the filtered1167 * xml file.1155 * @param isr The reader of the {@link InputStream} containing the xml. 1156 * @param pout The {@link PipedOutputStream} that will be receiving the 1157 * filtered xml file. 1168 1158 */ 1169 1159 public void sanitizeInput(Reader isr, OutputStream pout) { … … 1205 1195 if (JNLPRuntime.isDebug()) { 1206 1196 if (ch == 10) { 1207 System.out.println();1208 System.out.print("line: " + newline + " ");1197 OutputController.getLogger().printOutLn(""); 1198 OutputController.getLogger().printOut("line: " + newline + " "); 1209 1199 newline++; 1210 1200 } else { 1211 System.out.print(ch);1201 OutputController.getLogger().printOut(ch+""); 1212 1202 } 1213 1203 } … … 1236 1226 this.sanitizeCharReadTooMuch = ch; 1237 1227 if (JNLPRuntime.isDebug()) { 1238 System.out.print('<');1239 System.out.print('!');1240 System.out.print('-');1228 OutputController.getLogger().printOut("<"); 1229 OutputController.getLogger().printOut("!"); 1230 OutputController.getLogger().printOut("-"); 1241 1231 } 1242 1232 } … … 1246 1236 this.sanitizeCharReadTooMuch = ch; 1247 1237 if (JNLPRuntime.isDebug()) { 1248 System.out.print('<');1249 System.out.print('!');1238 OutputController.getLogger().printOut("<"); 1239 OutputController.getLogger().printOut("!"); 1250 1240 } 1251 1241 } … … 1256 1246 if (JNLPRuntime.isDebug()) { 1257 1247 if (ch == 10) { 1258 System.out.println();1259 System.out.print("line: " + newline + " ");1248 OutputController.getLogger().printOutLn(""); 1249 OutputController.getLogger().printOut("line: " + newline + " "); 1260 1250 newline++; 1261 1251 } else { 1262 System.out.print(ch);1252 OutputController.getLogger().printOut(ch+""); 1263 1253 } 1264 1254 } … … 1272 1262 // Print the stack trace here -- xml.parseFromReader() will 1273 1263 // throw the ParseException if something goes wrong. 1274 e.printStackTrace();1264 OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); 1275 1265 } 1276 1266 } -
trunk/icedtea-web/netx/net/sourceforge/nanoxml/XMLParseException.java
r348 r429 32 32 * An XMLParseException is thrown when an error occures while parsing an XML 33 33 * string. 34 * < P>35 * $Revision: 1.1 $< BR>36 * $Date: 2002/08/03 04:05:32 $< P>34 * <p> 35 * $Revision: 1.1 $<br/> 36 * $Date: 2002/08/03 04:05:32 $</p> 37 37 * 38 38 * @see net.sourceforge.nanoxml.XMLElement … … 54 54 * 55 55 * <dl><dt><b>Invariants:</b></dt><dd> 56 * <ul><li> <code>lineNr > 0 || lineNr == NO_LINE</code>56 * <ul><li>{@code lineNr > 0 || lineNr == NO_LINE} 57 57 * </ul></dd></dl> 58 58 */ … … 65 65 * @param message A message describing what went wrong. 66 66 * 67 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>68 * <ul><li> <code>message != null</code>67 * <dl><dt><b>Preconditions:</b></dt><dd> 68 * <ul><li>{@code message != null}</li> 69 69 * </ul></dd></dl> 70 70 * 71 71 * <dl><dt><b>Postconditions:</b></dt><dd> 72 * <ul><li> getLineNr() => NO_LINE73 * </ul></dd></dl> <dl>72 * <ul><li>{@code getLineNr() => NO_LINE}</li> 73 * </ul></dd></dl> 74 74 */ 75 75 public XMLParseException(String name, … … 89 89 * @param message A message describing what went wrong. 90 90 * 91 * < /dl><dl><dt><b>Preconditions:</b></dt><dd>92 * <ul><li> <code>message != null</code>93 * <li> <code>lineNr > 0</code>91 * <dl><dt><b>Preconditions:</b></dt><dd> 92 * <ul><li>{@code message != null}</li> 93 * <li>{@code lineNr > 0}</li> 94 94 * </ul></dd></dl> 95 95 * 96 96 * <dl><dt><b>Postconditions:</b></dt><dd> 97 * <ul><li> getLineNr() => lineNr98 * </ul></dd></dl> <dl>97 * <ul><li>{@code getLineNr() => lineNr}</li> 98 * </ul></dd></dl> 99 99 */ 100 100 public XMLParseException(String name, … … 109 109 110 110 /** 111 * Where the error occurred, or <code>NO_LINE</code>if the line number is111 * Where the error occurred, or {@code NO_LINE} if the line number is 112 112 * unknown. 113 113 * … … 117 117 return this.lineNr; 118 118 } 119 120 119 }
Note:
See TracChangeset
for help on using the changeset viewer.