120 */
121 protected void addJar(String name) throws IOException {
122 URL url;
123 try {
124 url = new URL(base, name);
125 } catch (MalformedURLException e) {
126 throw new IllegalArgumentException("name");
127 }
128 addURL(url);
129 // DEBUG
130 //URL[] urls = getURLs();
131 //for (int i = 0; i < urls.length; i++) {
132 // System.out.println("url[" + i + "] = " + urls[i]);
133 //}
134 }
135
136 /*
137 * Override loadClass so that class loading errors can be caught in
138 * order to print better error messages.
139 */
140 public synchronized Class loadClass(String name, boolean resolve)
141 throws ClassNotFoundException
142 {
143 // First check if we have permission to access the package. This
144 // should go away once we've added support for exported packages.
145 int i = name.lastIndexOf('.');
146 if (i != -1) {
147 SecurityManager sm = System.getSecurityManager();
148 if (sm != null)
149 sm.checkPackageAccess(name.substring(0, i));
150 }
151 try {
152 return super.loadClass(name, resolve);
153 } catch (ClassNotFoundException e) {
154 //printError(name, e.getException());
155 throw e;
156 } catch (RuntimeException e) {
157 //printError(name, e);
158 throw e;
159 } catch (Error e) {
160 //printError(name, e);
161 throw e;
162 }
163 }
164
165 /*
166 * Finds the applet class with the specified name. First searches
167 * loaded JAR files then the applet code base for the class.
168 */
169 protected Class findClass(String name) throws ClassNotFoundException {
170
171 int index = name.indexOf(';');
172 String cookie = "";
173 if(index != -1) {
174 cookie = name.substring(index, name.length());
175 name = name.substring(0, index);
176 }
177
178 // check loaded JAR files
179 try {
180 return super.findClass(name);
181 } catch (ClassNotFoundException e) {
182 }
183
184 // Otherwise, try loading the class from the code base URL
185
186 // 4668479: Option to turn off codebase lookup in AppletClassLoader
187 // during resource requests. [stanley.ho]
188 if (codebaseLookup == false)
189 throw new ClassNotFoundException(name);
190
191 // final String path = name.replace('.', '/').concat(".class").concat(cookie);
192 String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false);
193 final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString();
194 try {
195 byte[] b = (byte[]) AccessController.doPrivileged(
196 new PrivilegedExceptionAction() {
197 public Object run() throws IOException {
198 try {
199 URL finalURL = new URL(base, path);
200
201 // Make sure the codebase won't be modified
202 if (base.getProtocol().equals(finalURL.getProtocol()) &&
203 base.getHost().equals(finalURL.getHost()) &&
204 base.getPort() == finalURL.getPort()) {
205 return getBytes(finalURL);
206 }
207 else {
208 return null;
209 }
210 } catch (Exception e) {
211 return null;
212 }
213 }
214 }, acc);
215
216 if (b != null) {
217 return defineClass(name, b, 0, b.length, codesource);
539 *
540 * The same connection should be reused to avoid multiple
541 * HTTP connections
542 */
543
544 // our best guess for the other cases
545 InputStream is = conn.getInputStream();
546 is.close();
547 }
548 } catch (Exception ex) {
549 ok = false;
550 }
551 return ok;
552 }
553
554 /*
555 * Returns an enumeration of all the applet resources with the specified
556 * name. First checks loaded JAR files then the applet code base for all
557 * available resources.
558 */
559 public Enumeration findResources(String name) throws IOException {
560
561 final Enumeration e = super.findResources(name);
562
563 // 6215746: Disable META-INF/* lookup from codebase in
564 // applet/plugin classloader. [stanley.ho]
565 if (name.startsWith("META-INF/"))
566 return e;
567
568 // 4668479: Option to turn off codebase lookup in AppletClassLoader
569 // during resource requests. [stanley.ho]
570 if (codebaseLookup == false)
571 return e;
572
573 URL u = new URL(base, ParseUtil.encodePath(name, false));
574 if (!resourceExists(u)) {
575 u = null;
576 }
577
578 final URL url = u;
579 return new Enumeration() {
580 private boolean done;
581 public Object nextElement() {
582 if (!done) {
583 if (e.hasMoreElements()) {
584 return e.nextElement();
585 }
586 done = true;
587 if (url != null) {
588 return url;
589 }
590 }
591 throw new NoSuchElementException();
592 }
593 public boolean hasMoreElements() {
594 return !done && (e.hasMoreElements() || url != null);
595 }
596 };
597 }
598
599 /*
600 * Load and resolve the file specified by the applet tag CODE
601 * attribute. The argument can either be the relative path
602 * of the class file itself or just the name of the class.
603 */
604 Class loadCode(String name) throws ClassNotFoundException {
605 // first convert any '/' or native file separator to .
606 name = name.replace('/', '.');
607 name = name.replace(File.separatorChar, '.');
608
609 // deal with URL rewriting
610 String cookie = null;
611 int index = name.indexOf(';');
612 if(index != -1) {
613 cookie = name.substring(index, name.length());
614 name = name.substring(0, index);
615 }
616
617 // save that name for later
618 String fullName = name;
619 // then strip off any suffixes
620 if (name.endsWith(".class") || name.endsWith(".java")) {
621 name = name.substring(0, name.lastIndexOf('.'));
622 }
623 try {
624 if(cookie != null)
629 // then if it didn't end with .java or .class, or in the
630 // really pathological case of a class named class or java
631 if(cookie != null)
632 fullName = (new StringBuffer(fullName)).append(cookie).toString();
633
634 return loadClass(fullName);
635 }
636
637 /*
638 * The threadgroup that the applets loaded by this classloader live
639 * in. In the sun.* implementation of applets, the security manager's
640 * (AppletSecurity) getThreadGroup returns the thread group of the
641 * first applet on the stack, which is the applet's thread group.
642 */
643 private AppletThreadGroup threadGroup;
644 private AppContext appContext;
645
646 public ThreadGroup getThreadGroup() {
647 synchronized (threadGroupSynchronizer) {
648 if (threadGroup == null || threadGroup.isDestroyed()) {
649 AccessController.doPrivileged(new PrivilegedAction() {
650 public Object run() {
651 threadGroup = new AppletThreadGroup(base + "-threadGroup");
652 // threadGroup.setDaemon(true);
653 // threadGroup is now destroyed by AppContext.dispose()
654
655 // Create the new AppContext from within a Thread belonging
656 // to the newly created ThreadGroup, and wait for the
657 // creation to complete before returning from this method.
658 AppContextCreator creatorThread = new AppContextCreator(threadGroup);
659
660 // Since this thread will later be used to launch the
661 // applet's AWT-event dispatch thread and we want the applet
662 // code executing the AWT callbacks to use their own class
663 // loader rather than the system class loader, explicitly
664 // set the context class loader to the AppletClassLoader.
665 creatorThread.setContextClassLoader(AppletClassLoader.this);
666
667 creatorThread.start();
668 try {
669 synchronized(creatorThread.syncObject) {
753 * not dispose the AppContext. PluginClassLoader does not
754 * use UsageCount to decide whether to dispose AppContext
755 *
756 * @return previous AppContext
757 */
758 protected AppContext resetAppContext() {
759 AppContext tempAppContext = null;
760
761 synchronized(threadGroupSynchronizer) {
762 // Store app context in temp variable
763 tempAppContext = appContext;
764 usageCount = 0;
765 appContext = null;
766 threadGroup = null;
767 }
768 return tempAppContext;
769 }
770
771
772 // Hash map to store applet compatibility info
773 private HashMap jdk11AppletInfo = new HashMap();
774 private HashMap jdk12AppletInfo = new HashMap();
775
776 /**
777 * Set applet target level as JDK 1.1.
778 *
779 * @param clazz Applet class.
780 * @param bool true if JDK is targeted for JDK 1.1;
781 * false otherwise.
782 */
783 void setJDK11Target(Class clazz, boolean bool)
784 {
785 jdk11AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
786 }
787
788 /**
789 * Set applet target level as JDK 1.2.
790 *
791 * @param clazz Applet class.
792 * @param bool true if JDK is targeted for JDK 1.2;
793 * false otherwise.
794 */
795 void setJDK12Target(Class clazz, boolean bool)
796 {
797 jdk12AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
798 }
799
800 /**
801 * Determine if applet is targeted for JDK 1.1.
802 *
803 * @param applet Applet class.
804 * @return TRUE if applet is targeted for JDK 1.1;
805 * FALSE if applet is not;
806 * null if applet is unknown.
807 */
808 Boolean isJDK11Target(Class clazz)
809 {
810 return (Boolean) jdk11AppletInfo.get(clazz.toString());
811 }
812
813 /**
814 * Determine if applet is targeted for JDK 1.2.
815 *
816 * @param applet Applet class.
817 * @return TRUE if applet is targeted for JDK 1.2;
818 * FALSE if applet is not;
819 * null if applet is unknown.
820 */
821 Boolean isJDK12Target(Class clazz)
822 {
823 return (Boolean) jdk12AppletInfo.get(clazz.toString());
824 }
825
826 private static AppletMessageHandler mh =
827 new AppletMessageHandler("appletclassloader");
828
829 /*
830 * Prints a class loading error message.
831 */
832 private static void printError(String name, Throwable e) {
833 String s = null;
834 if (e == null) {
835 s = mh.getMessage("filenotfound", name);
836 } else if (e instanceof IOException) {
837 s = mh.getMessage("fileioexception", name);
838 } else if (e instanceof ClassFormatError) {
839 s = mh.getMessage("fileformat", name);
840 } else if (e instanceof ThreadDeath) {
841 s = mh.getMessage("filedeath", name);
842 } else if (e instanceof Error) {
843 s = mh.getMessage("fileerror", e.toString(), name);
|
120 */
121 protected void addJar(String name) throws IOException {
122 URL url;
123 try {
124 url = new URL(base, name);
125 } catch (MalformedURLException e) {
126 throw new IllegalArgumentException("name");
127 }
128 addURL(url);
129 // DEBUG
130 //URL[] urls = getURLs();
131 //for (int i = 0; i < urls.length; i++) {
132 // System.out.println("url[" + i + "] = " + urls[i]);
133 //}
134 }
135
136 /*
137 * Override loadClass so that class loading errors can be caught in
138 * order to print better error messages.
139 */
140 public synchronized Class<?> loadClass(String name, boolean resolve)
141 throws ClassNotFoundException
142 {
143 // First check if we have permission to access the package. This
144 // should go away once we've added support for exported packages.
145 int i = name.lastIndexOf('.');
146 if (i != -1) {
147 SecurityManager sm = System.getSecurityManager();
148 if (sm != null)
149 sm.checkPackageAccess(name.substring(0, i));
150 }
151 try {
152 return super.loadClass(name, resolve);
153 } catch (ClassNotFoundException e) {
154 //printError(name, e.getException());
155 throw e;
156 } catch (RuntimeException e) {
157 //printError(name, e);
158 throw e;
159 } catch (Error e) {
160 //printError(name, e);
161 throw e;
162 }
163 }
164
165 /*
166 * Finds the applet class with the specified name. First searches
167 * loaded JAR files then the applet code base for the class.
168 */
169 protected Class<?> findClass(String name) throws ClassNotFoundException {
170
171 int index = name.indexOf(';');
172 String cookie = "";
173 if(index != -1) {
174 cookie = name.substring(index, name.length());
175 name = name.substring(0, index);
176 }
177
178 // check loaded JAR files
179 try {
180 return super.findClass(name);
181 } catch (ClassNotFoundException e) {
182 }
183
184 // Otherwise, try loading the class from the code base URL
185
186 // 4668479: Option to turn off codebase lookup in AppletClassLoader
187 // during resource requests. [stanley.ho]
188 if (codebaseLookup == false)
189 throw new ClassNotFoundException(name);
190
191 // final String path = name.replace('.', '/').concat(".class").concat(cookie);
192 String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false);
193 final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString();
194 try {
195 byte[] b = AccessController.doPrivileged(
196 new PrivilegedExceptionAction<byte[]>() {
197 public byte[] run() throws IOException {
198 try {
199 URL finalURL = new URL(base, path);
200
201 // Make sure the codebase won't be modified
202 if (base.getProtocol().equals(finalURL.getProtocol()) &&
203 base.getHost().equals(finalURL.getHost()) &&
204 base.getPort() == finalURL.getPort()) {
205 return getBytes(finalURL);
206 }
207 else {
208 return null;
209 }
210 } catch (Exception e) {
211 return null;
212 }
213 }
214 }, acc);
215
216 if (b != null) {
217 return defineClass(name, b, 0, b.length, codesource);
539 *
540 * The same connection should be reused to avoid multiple
541 * HTTP connections
542 */
543
544 // our best guess for the other cases
545 InputStream is = conn.getInputStream();
546 is.close();
547 }
548 } catch (Exception ex) {
549 ok = false;
550 }
551 return ok;
552 }
553
554 /*
555 * Returns an enumeration of all the applet resources with the specified
556 * name. First checks loaded JAR files then the applet code base for all
557 * available resources.
558 */
559 @Override
560 public Enumeration<URL> findResources(String name) throws IOException {
561
562 final Enumeration<URL> e = super.findResources(name);
563
564 // 6215746: Disable META-INF/* lookup from codebase in
565 // applet/plugin classloader. [stanley.ho]
566 if (name.startsWith("META-INF/"))
567 return e;
568
569 // 4668479: Option to turn off codebase lookup in AppletClassLoader
570 // during resource requests. [stanley.ho]
571 if (codebaseLookup == false)
572 return e;
573
574 URL u = new URL(base, ParseUtil.encodePath(name, false));
575 if (!resourceExists(u)) {
576 u = null;
577 }
578
579 final URL url = u;
580 return new Enumeration<URL>() {
581 private boolean done;
582 public URL nextElement() {
583 if (!done) {
584 if (e.hasMoreElements()) {
585 return e.nextElement();
586 }
587 done = true;
588 if (url != null) {
589 return url;
590 }
591 }
592 throw new NoSuchElementException();
593 }
594 public boolean hasMoreElements() {
595 return !done && (e.hasMoreElements() || url != null);
596 }
597 };
598 }
599
600 /*
601 * Load and resolve the file specified by the applet tag CODE
602 * attribute. The argument can either be the relative path
603 * of the class file itself or just the name of the class.
604 */
605 Class<?> loadCode(String name) throws ClassNotFoundException {
606 // first convert any '/' or native file separator to .
607 name = name.replace('/', '.');
608 name = name.replace(File.separatorChar, '.');
609
610 // deal with URL rewriting
611 String cookie = null;
612 int index = name.indexOf(';');
613 if(index != -1) {
614 cookie = name.substring(index, name.length());
615 name = name.substring(0, index);
616 }
617
618 // save that name for later
619 String fullName = name;
620 // then strip off any suffixes
621 if (name.endsWith(".class") || name.endsWith(".java")) {
622 name = name.substring(0, name.lastIndexOf('.'));
623 }
624 try {
625 if(cookie != null)
630 // then if it didn't end with .java or .class, or in the
631 // really pathological case of a class named class or java
632 if(cookie != null)
633 fullName = (new StringBuffer(fullName)).append(cookie).toString();
634
635 return loadClass(fullName);
636 }
637
638 /*
639 * The threadgroup that the applets loaded by this classloader live
640 * in. In the sun.* implementation of applets, the security manager's
641 * (AppletSecurity) getThreadGroup returns the thread group of the
642 * first applet on the stack, which is the applet's thread group.
643 */
644 private AppletThreadGroup threadGroup;
645 private AppContext appContext;
646
647 public ThreadGroup getThreadGroup() {
648 synchronized (threadGroupSynchronizer) {
649 if (threadGroup == null || threadGroup.isDestroyed()) {
650 AccessController.doPrivileged(new PrivilegedAction<Object>() {
651 public Object run() {
652 threadGroup = new AppletThreadGroup(base + "-threadGroup");
653 // threadGroup.setDaemon(true);
654 // threadGroup is now destroyed by AppContext.dispose()
655
656 // Create the new AppContext from within a Thread belonging
657 // to the newly created ThreadGroup, and wait for the
658 // creation to complete before returning from this method.
659 AppContextCreator creatorThread = new AppContextCreator(threadGroup);
660
661 // Since this thread will later be used to launch the
662 // applet's AWT-event dispatch thread and we want the applet
663 // code executing the AWT callbacks to use their own class
664 // loader rather than the system class loader, explicitly
665 // set the context class loader to the AppletClassLoader.
666 creatorThread.setContextClassLoader(AppletClassLoader.this);
667
668 creatorThread.start();
669 try {
670 synchronized(creatorThread.syncObject) {
754 * not dispose the AppContext. PluginClassLoader does not
755 * use UsageCount to decide whether to dispose AppContext
756 *
757 * @return previous AppContext
758 */
759 protected AppContext resetAppContext() {
760 AppContext tempAppContext = null;
761
762 synchronized(threadGroupSynchronizer) {
763 // Store app context in temp variable
764 tempAppContext = appContext;
765 usageCount = 0;
766 appContext = null;
767 threadGroup = null;
768 }
769 return tempAppContext;
770 }
771
772
773 // Hash map to store applet compatibility info
774 private HashMap<String, Boolean> jdk11AppletInfo = new HashMap<>();
775 private HashMap<String, Boolean> jdk12AppletInfo = new HashMap<>();
776
777 /**
778 * Set applet target level as JDK 1.1.
779 *
780 * @param clazz Applet class.
781 * @param bool true if JDK is targeted for JDK 1.1;
782 * false otherwise.
783 */
784 void setJDK11Target(Class<?> clazz, boolean bool)
785 {
786 jdk11AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
787 }
788
789 /**
790 * Set applet target level as JDK 1.2.
791 *
792 * @param clazz Applet class.
793 * @param bool true if JDK is targeted for JDK 1.2;
794 * false otherwise.
795 */
796 void setJDK12Target(Class<?> clazz, boolean bool)
797 {
798 jdk12AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
799 }
800
801 /**
802 * Determine if applet is targeted for JDK 1.1.
803 *
804 * @param applet Applet class.
805 * @return TRUE if applet is targeted for JDK 1.1;
806 * FALSE if applet is not;
807 * null if applet is unknown.
808 */
809 Boolean isJDK11Target(Class<?> clazz)
810 {
811 return jdk11AppletInfo.get(clazz.toString());
812 }
813
814 /**
815 * Determine if applet is targeted for JDK 1.2.
816 *
817 * @param applet Applet class.
818 * @return TRUE if applet is targeted for JDK 1.2;
819 * FALSE if applet is not;
820 * null if applet is unknown.
821 */
822 Boolean isJDK12Target(Class<?> clazz)
823 {
824 return jdk12AppletInfo.get(clazz.toString());
825 }
826
827 private static AppletMessageHandler mh =
828 new AppletMessageHandler("appletclassloader");
829
830 /*
831 * Prints a class loading error message.
832 */
833 private static void printError(String name, Throwable e) {
834 String s = null;
835 if (e == null) {
836 s = mh.getMessage("filenotfound", name);
837 } else if (e instanceof IOException) {
838 s = mh.getMessage("fileioexception", name);
839 } else if (e instanceof ClassFormatError) {
840 s = mh.getMessage("fileformat", name);
841 } else if (e instanceof ThreadDeath) {
842 s = mh.getMessage("filedeath", name);
843 } else if (e instanceof Error) {
844 s = mh.getMessage("fileerror", e.toString(), name);
|