1 /*Copyright (C) 2013 Red Hat, Inc. 2 3 This file is part of IcedTea. 4 5 IcedTea is free software; you can redistribute it and/or 6 modify it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 IcedTea is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with IcedTea; see the file COPYING. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 02110-1301 USA. 18 19 Linking this library statically or dynamically with other modules is 20 making a combined work based on this library. Thus, the terms and 21 conditions of the GNU General Public License cover the whole 22 combination. 23 24 As a special exception, the copyright holders of this library give you 25 permission to link this library with independent modules to produce an 26 executable, regardless of the license terms of these independent 27 modules, and to copy and distribute the resulting executable under 28 terms of your choice, provided that you also meet, for each linked 29 independent module, the terms and conditions of the license of that 30 module. An independent module is a module which is not derived from 31 or based on this library. If you modify this library, you may extend 32 this exception to your version of the library, but you are not 33 obligated to do so. If you do not wish to do so, delete this 34 exception statement from your version. 35 */ 36 37 package net.sourceforge.jnlp.runtime; 38 39 import static net.sourceforge.jnlp.util.FileTestUtils.assertNoFileLeak; 40 import static org.junit.Assert.assertEquals; 41 import static org.junit.Assert.assertFalse; 42 import static org.junit.Assert.fail; 43 44 import java.io.File; 45 import java.util.Arrays; 46 import java.util.jar.Attributes; 47 import java.util.jar.Manifest; 48 49 import net.sourceforge.jnlp.LaunchException; 50 import net.sourceforge.jnlp.cache.UpdatePolicy; 51 import net.sourceforge.jnlp.config.DeploymentConfiguration; 52 import net.sourceforge.jnlp.mock.DummyJNLPFileWithJar; 53 import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel; 54 import net.sourceforge.jnlp.security.appletextendedsecurity.AppletStartupSecuritySettings; 55 import net.sourceforge.jnlp.util.FileTestUtils; 56 import net.sourceforge.jnlp.util.logging.NoStdOutErrTest; 57 import org.junit.AfterClass; 58 import org.junit.Assert; 59 import org.junit.BeforeClass; 60 61 import org.junit.Test; 62 63 public class JNLPClassLoaderTest extends NoStdOutErrTest{ 64 65 private static AppletSecurityLevel level; 66 public static String askUser; 67 68 69 @BeforeClass setPermissions()70 public static void setPermissions() { 71 level = AppletStartupSecuritySettings.getInstance().getSecurityLevel(); 72 JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_LEVEL, AppletSecurityLevel.ALLOW_UNSIGNED.toChars()); 73 } 74 75 @AfterClass resetPermissions()76 public static void resetPermissions() { 77 JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_LEVEL, level.toChars()); 78 } 79 @BeforeClass noDialogs()80 public static void noDialogs(){ 81 askUser = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_SECURITY_PROMPT_USER); 82 JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_PROMPT_USER, Boolean.toString(false)); 83 } 84 85 @AfterClass restoreDialogs()86 public static void restoreDialogs(){ 87 JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_PROMPT_USER, askUser); 88 } 89 /* Note: Only does file leak testing for now. */ 90 @Test constructorFileLeakTest()91 public void constructorFileLeakTest() throws Exception { 92 File tempDirectory = FileTestUtils.createTempDirectory(); 93 File jarLocation = new File(tempDirectory, "test.jar"); 94 FileTestUtils.createJarWithContents(jarLocation /* no contents*/); 95 96 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 97 98 assertNoFileLeak( new Runnable () { 99 @Override 100 public void run() { 101 try { 102 new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 103 } catch (LaunchException e) { 104 fail(e.toString()); 105 } 106 } 107 }); 108 } 109 110 /* Note: We should create a JNLPClassLoader with an invalid jar to test isInvalidJar with. 111 * However, it is tricky without it erroring-out. */ 112 @Test isInvalidJarTest()113 public void isInvalidJarTest() throws Exception { 114 File tempDirectory = FileTestUtils.createTempDirectory(); 115 File jarLocation = new File(tempDirectory, "test.jar"); 116 FileTestUtils.createJarWithContents(jarLocation /* no contents*/); 117 118 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 119 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 120 121 assertNoFileLeak( new Runnable () { 122 @Override 123 public void run() { 124 assertFalse(classLoader.isInvalidJar(jnlpFile.getJarDesc())); 125 } 126 }); 127 } 128 129 @Test getMainClassNameTest()130 public void getMainClassNameTest() throws Exception { 131 File tempDirectory = FileTestUtils.createTempDirectory(); 132 File jarLocation = new File(tempDirectory, "test.jar"); 133 134 /* Test with main-class in manifest */ { 135 Manifest manifest = new Manifest(); 136 manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "DummyClass"); 137 FileTestUtils.createJarWithContents(jarLocation, manifest); 138 139 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 140 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 141 142 assertNoFileLeak(new Runnable() { 143 @Override 144 public void run() { 145 assertEquals("DummyClass", classLoader.getMainClassName(jnlpFile.getJarLocation())); 146 } 147 }); 148 } 149 } 150 151 @Test getMainClassNameTestEmpty()152 public void getMainClassNameTestEmpty() throws Exception { 153 /* Test with-out any main-class specified */ { 154 File tempDirectory = FileTestUtils.createTempDirectory(); 155 File jarLocation = new File(tempDirectory, "test.jar"); 156 FileTestUtils.createJarWithContents(jarLocation /* No contents */); 157 158 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 159 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 160 161 assertNoFileLeak(new Runnable() { 162 @Override 163 public void run() { 164 assertEquals(null, classLoader.getMainClassName(jnlpFile.getJarLocation())); 165 } 166 }); 167 } 168 } 169 170 /* Note: Although it does a basic check, this mainly checks for file-descriptor leak */ 171 @Test checkForMainFileLeakTest()172 public void checkForMainFileLeakTest() throws Exception { 173 File tempDirectory = FileTestUtils.createTempDirectory(); 174 File jarLocation = new File(tempDirectory, "test.jar"); 175 FileTestUtils.createJarWithContents(jarLocation /* No contents */); 176 177 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 178 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 179 assertNoFileLeak(new Runnable() { 180 @Override 181 public void run() { 182 try { 183 classLoader.checkForMain(Arrays.asList(jnlpFile.getJarDesc())); 184 } catch (LaunchException e) { 185 fail(e.toString()); 186 } 187 } 188 }); 189 assertFalse(classLoader.hasMainJar()); 190 } 191 192 @Test getCustomAtributes()193 public void getCustomAtributes() throws Exception { 194 File tempDirectory = FileTestUtils.createTempDirectory(); 195 File jarLocation = new File(tempDirectory, "testX.jar"); 196 197 /* Test with attributes in manifest */ 198 Manifest manifest = new Manifest(); 199 manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "DummyClass"); 200 manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_TITLE, "it"); 201 manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VENDOR, "rh"); 202 FileTestUtils.createJarWithContents(jarLocation, manifest); 203 204 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 205 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 206 207 assertNoFileLeak(new Runnable() { 208 @Override 209 public void run() { 210 assertEquals("rh", classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.IMPLEMENTATION_VENDOR)); 211 assertEquals("DummyClass", classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.MAIN_CLASS)); 212 assertEquals("it", classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.IMPLEMENTATION_TITLE)); 213 } 214 }); 215 } 216 217 @Test getCustomAtributesEmpty()218 public void getCustomAtributesEmpty() throws Exception { 219 File tempDirectory = FileTestUtils.createTempDirectory(); 220 File jarLocation = new File(tempDirectory, "testX.jar"); 221 222 /* Test with-out any attribute specified specified */ 223 FileTestUtils.createJarWithContents(jarLocation /* No contents */); 224 225 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 226 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 227 228 assertNoFileLeak(new Runnable() { 229 @Override 230 public void run() { 231 assertEquals(null, classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.IMPLEMENTATION_VENDOR)); 232 assertEquals(null, classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.MAIN_CLASS)); 233 assertEquals(null, classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.IMPLEMENTATION_TITLE)); 234 } 235 }); 236 } 237 238 @Test checkOrderWhenReadingAttributes()239 public void checkOrderWhenReadingAttributes() throws Exception { 240 File tempDirectory = FileTestUtils.createTempDirectory(); 241 File jarLocation1 = new File(tempDirectory, "test1.jar"); 242 File jarLocation2 = new File(tempDirectory, "test2.jar"); 243 File jarLocation3 = new File(tempDirectory, "test3.jar"); 244 File jarLocation4 = new File(tempDirectory, "test4.jar"); 245 File jarLocation5 = new File(tempDirectory, "test5.jar"); 246 247 /* Test with various attributes in manifest!s! */ 248 Manifest manifest1 = new Manifest(); 249 manifest1.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "DummyClass1"); //two times, but one in main jar, see DummyJNLPFileWithJar constructor with int 250 251 Manifest manifest2 = new Manifest(); 252 manifest2.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VENDOR, "rh1"); //two times, both in not main jar, see DummyJNLPFileWithJar constructor with int 253 254 Manifest manifest3 = new Manifest(); 255 manifest3.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_TITLE, "it"); //jsut once in not main jar, see DummyJNLPFileWithJar constructor with int 256 manifest3.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VENDOR, "rh2"); 257 258 Manifest manifest4 = new Manifest(); 259 manifest4.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "DummyClass2"); //see jnlpFile.setMainJar(3); 260 manifest4.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_URL, "some url2"); //see DummyJNLPFileWithJar constructor with int 261 262 //first jar 263 Manifest manifest5 = new Manifest(); 264 manifest5.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_URL, "some url1"); //see DummyJNLPFileWithJar constructor with int 265 266 267 FileTestUtils.createJarWithContents(jarLocation1, manifest1); 268 FileTestUtils.createJarWithContents(jarLocation2, manifest2); 269 FileTestUtils.createJarWithContents(jarLocation3, manifest3); 270 FileTestUtils.createJarWithContents(jarLocation4, manifest4); 271 FileTestUtils.createJarWithContents(jarLocation5, manifest5); 272 273 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(3, jarLocation5, jarLocation3, jarLocation4, jarLocation1, jarLocation2); //jar 1 should be main 274 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 275 276 assertNoFileLeak(new Runnable() { 277 @Override 278 public void run() { 279 //defined twice 280 assertEquals(null, classLoader.checkForAttributeInJars(Arrays.asList(jnlpFile.getJarDescs()), Attributes.Name.IMPLEMENTATION_VENDOR)); 281 //defined twice, but one in main jar 282 assertEquals("DummyClass1", classLoader.checkForAttributeInJars(Arrays.asList(jnlpFile.getJarDescs()), Attributes.Name.MAIN_CLASS)); 283 //defined not in main jar 284 assertEquals("it", classLoader.checkForAttributeInJars(Arrays.asList(jnlpFile.getJarDescs()), Attributes.Name.IMPLEMENTATION_TITLE)); 285 //not deffined 286 assertEquals(null, classLoader.checkForAttributeInJars(Arrays.asList(jnlpFile.getJarDescs()), Attributes.Name.IMPLEMENTATION_VENDOR_ID)); 287 //deffined in first jar 288 assertEquals("some url1", classLoader.checkForAttributeInJars(Arrays.asList(jnlpFile.getJarDescs()), Attributes.Name.IMPLEMENTATION_URL)); 289 } 290 }); 291 } 292 293 294 @Test tryNullManifest()295 public void tryNullManifest() throws Exception { 296 File tempDirectory = FileTestUtils.createTempDirectory(); 297 File jarLocation = new File(tempDirectory, "test-npe.jar"); 298 File dummyContent = File.createTempFile("dummy", "context", tempDirectory); 299 jarLocation.deleteOnExit(); 300 301 /* Test with-out any attribute specified specified */ 302 FileTestUtils.createJarWithoutManifestContents(jarLocation, dummyContent); 303 304 final Exception[] exs = new Exception[2]; 305 final DummyJNLPFileWithJar jnlpFile = new DummyJNLPFileWithJar(jarLocation); 306 try { 307 final JNLPClassLoader classLoader = new JNLPClassLoader(jnlpFile, UpdatePolicy.ALWAYS); 308 assertNoFileLeak(new Runnable() { 309 @Override 310 public void run() { 311 try { 312 assertEquals(null, classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.MAIN_CLASS)); 313 assertEquals(null, classLoader.getManifestAttribute(jnlpFile.getJarLocation(), Attributes.Name.IMPLEMENTATION_TITLE)); 314 } catch (Exception e) { 315 exs[0] = e; 316 } 317 } 318 }); 319 } catch (Exception e) { 320 exs[1] = e; 321 } 322 Assert.assertNotNull(exs); 323 Assert.assertNull(exs[0]); 324 Assert.assertNull(exs[1]); 325 } 326 } 327