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