/**
   * Instantiate a JavaBean.
   *
   * @param classLoader the class-loader from which we should create the bean. If this is null, then
   *     the system class-loader is used.
   * @param beanName the name of the bean within the class-loader. For example "sun.beanbox.foobah"
   * @exception java.lang.ClassNotFoundException if the class of a serialized object could not be
   *     found.
   * @exception java.io.IOException if an I/O error occurs.
   */
  public static Object instantiate(ClassLoader cls, String beanName)
      throws java.io.IOException, ClassNotFoundException {
    java.io.InputStream ins;
    java.io.ObjectInputStream oins = null;
    Object result = null;
    boolean serialized = false;
    java.io.IOException serex = null;
    // If the given classloader is null, we check if an
    // system classloader is available and (if so)
    // use that instead.
    // Note that calls on the system class loader will
    // look in the bootstrap class loader first.
    if (cls == null) {
      try {
        cls = ClassLoader.getSystemClassLoader();
      } catch (SecurityException ex) { // We're not allowed to access the system class loader.
        // Drop through.
      }
    }
    // Try to find a serialized object with this name
    final String serName = beanName.replace('.', '/').concat(".ser");
    final ClassLoader loader = cls;
    ins =
        (InputStream)
            java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction() {
                  public Object run() {
                    if (loader == null) return ClassLoader.getSystemResourceAsStream(serName);
                    else return loader.getResourceAsStream(serName);
                  }
                });
    if (ins != null) {
      try {
        if (cls == null) {
          oins = new ObjectInputStream(ins);
        } else {
          oins = new ObjectInputStreamWithLoader(ins, cls);
        }
        result = oins.readObject();
        serialized = true;
        oins.close();
      } catch (java.io.IOException ex) {
        ins.close();
        // Drop through and try opening the class.  But remember
        // the exception in case we can't find the class either.
        serex = ex;
      } catch (ClassNotFoundException ex) {
        ins.close();
        throw ex;
      }
    }
    if (result == null) {
      // No serialized object, try just instantiating the class
      Class cl;
      try {
        if (cls == null) {
          cl = Class.forName(beanName);
        } else {
          cl = cls.loadClass(beanName);
        }
      } catch (ClassNotFoundException ex) {
        // There is no appropriate class.  If we earlier tried to
        // deserialize an object and got an IO exception, throw that,
        // otherwise rethrow the ClassNotFoundException.
        if (serex != null) {
          throw serex;
        }
        throw ex;
      }
      /*
       * Try to instantiate the class.
       */

      try {
        result = cl.newInstance();
      } catch (Exception ex) {
        // We have to remap the exception to one in our signature.
        // But we pass extra information in the detail message.
        throw new ClassNotFoundException("" + cl + " : " + ex);
      }
    }
    if (result != null) { // Ok, if the result is an applet initialize it.
      AppletStub stub = null;

      if (result instanceof Applet) {
        Applet applet = (Applet) result;

        // Figure our the codebase and docbase URLs.  We do this
        // by locating the URL for a known resource, and then
        // massaging the URL.

        // First find the "resource name" corresponding to the bean
        // itself.  So a serialzied bean "a.b.c" would imply a
        // resource name of "a/b/c.ser" and a classname of "x.y"
        // would imply a resource name of "x/y.class".

        final String resourceName;

        if (serialized) {
          // Serialized bean
          resourceName = beanName.replace('.', '/').concat(".ser");
        } else {
          // Regular class
          resourceName = beanName.replace('.', '/').concat(".class");
        }

        URL objectUrl = null;
        URL codeBase = null;
        URL docBase = null;

        // Now get the URL correponding to the resource name.

        final ClassLoader cloader = cls;
        objectUrl =
            (URL)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction() {
                      public Object run() {
                        if (cloader == null) return ClassLoader.getSystemResource(resourceName);
                        else return cloader.getResource(resourceName);
                      }
                    });

        // If we found a URL, we try to locate the docbase by taking
        // of the final path name component, and the code base by taking
        // of the complete resourceName.
        // So if we had a resourceName of "a/b/c.class" and we got an
        // objectURL of "file://bert/classes/a/b/c.class" then we would
        // want to set the codebase to "file://bert/classes/" and the
        // docbase to "file://bert/classes/a/b/"

        if (objectUrl != null) {
          String s = objectUrl.toExternalForm();

          if (s.endsWith(resourceName)) {
            int ix = s.length() - resourceName.length();
            codeBase = new URL(s.substring(0, ix));
            docBase = codeBase;

            ix = s.lastIndexOf('/');

            if (ix >= 0) {
              docBase = new URL(s.substring(0, ix + 1));
            }
          }
        }

        // Setup a default context and stub.
        BeansAppletContext context = new BeansAppletContext(applet);

        stub = (AppletStub) new BeansAppletStub(applet, context, codeBase, docBase);
        applet.setStub(stub);

        // If it was deserialized then it was already init-ed.
        // Otherwise we need to initialize it.

        if (!serialized) {
          // We need to set a reasonable initial size, as many
          // applets are unhappy if they are started without
          // having been explicitly sized.
          applet.setSize(100, 100);
          applet.init();
        }
        ((BeansAppletStub) stub).active = true;
      }
    }
    return result;
  }
Example #2
0
  /**
   * Execute applet events. Here is the state transition diagram
   *
   * <pre>{@literal
   *   Note: (XXX) is the action
   *         APPLET_XXX is the state
   *  (applet code loaded) --> APPLET_LOAD -- (applet init called)--> APPLET_INIT --
   *  (applet start called) --> APPLET_START -- (applet stop called) --> APPLET_STOP --
   *  (applet destroyed called) --> APPLET_DESTROY --> (applet gets disposed) -->
   *   APPLET_DISPOSE --> ...
   * }</pre>
   *
   * In the legacy lifecycle model. The applet gets loaded, inited and started. So it stays in the
   * APPLET_START state unless the applet goes away(refresh page or leave the page). So the applet
   * stop method called and the applet enters APPLET_STOP state. Then if the applet is revisited, it
   * will call applet start method and enter the APPLET_START state and stay there.
   *
   * <p>In the modern lifecycle model. When the applet first time visited, it is same as legacy
   * lifecycle model. However, when the applet page goes away. It calls applet stop method and
   * enters APPLET_STOP state and then applet destroyed method gets called and enters APPLET_DESTROY
   * state.
   *
   * <p>This code is also called by AppletViewer. In AppletViewer "Restart" menu, the applet is jump
   * from APPLET_STOP to APPLET_DESTROY and to APPLET_INIT .
   *
   * <p>Also, the applet can jump from APPLET_INIT state to APPLET_DESTROY (in Netscape/Mozilla
   * case). Same as APPLET_LOAD to APPLET_DISPOSE since all of this are triggered by browser.
   */
  @Override
  public void run() {

    Thread curThread = Thread.currentThread();
    if (curThread == loaderThread) {
      // if we are in the loader thread, cause
      // loading to occur.  We may exit this with
      // status being APPLET_DISPOSE, APPLET_ERROR,
      // or APPLET_LOAD
      runLoader();
      return;
    }

    boolean disposed = false;
    while (!disposed && !curThread.isInterrupted()) {
      AppletEvent evt;
      try {
        evt = getNextEvent();
      } catch (InterruptedException e) {
        showAppletStatus("bail");
        return;
      }

      // showAppletStatus("EVENT = " + evt.getID());
      try {
        switch (evt.getID()) {
          case APPLET_LOAD:
            if (!okToLoad()) {
              break;
            }
            // This complexity allows loading of applets to be
            // interruptable.  The actual thread loading runs
            // in a separate thread, so it can be interrupted
            // without harming the applet thread.
            // So that we don't have to worry about
            // concurrency issues, the main applet thread waits
            // until the loader thread terminates.
            // (one way or another).
            if (loaderThread == null) {
              setLoaderThread(new Thread(null, this, "AppletLoader", 0, false));
              loaderThread.start();
              // we get to go to sleep while this runs
              loaderThread.join();
              setLoaderThread(null);
            } else {
              // REMIND: issue an error -- this case should never
              // occur.
            }
            break;

          case APPLET_INIT:
            // AppletViewer "Restart" will jump from destroy method to
            // init, that is why we need to check status w/ APPLET_DESTROY
            if (status != APPLET_LOAD && status != APPLET_DESTROY) {
              showAppletStatus("notloaded");
              break;
            }
            applet.resize(defaultAppletSize);

            if (PerformanceLogger.loggingEnabled()) {
              PerformanceLogger.setTime("Applet Init");
              PerformanceLogger.outputLog();
            }
            applet.init();

            // Need the default(fallback) font to be created in this AppContext
            Font f = getFont();
            if (f == null
                || "dialog".equals(f.getFamily().toLowerCase(Locale.ENGLISH))
                    && f.getSize() == 12
                    && f.getStyle() == Font.PLAIN) {
              setFont(new Font(Font.DIALOG, Font.PLAIN, 12));
            }

            // Validate the applet in event dispatch thread
            // to avoid deadlock.
            try {
              final AppletPanel p = this;
              Runnable r =
                  new Runnable() {
                    @Override
                    public void run() {
                      p.validate();
                    }
                  };
              AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
            } catch (InterruptedException ie) {
            } catch (InvocationTargetException ite) {
            }

            status = APPLET_INIT;
            showAppletStatus("inited");
            break;

          case APPLET_START:
            {
              if (status != APPLET_INIT && status != APPLET_STOP) {
                showAppletStatus("notinited");
                break;
              }
              applet.resize(currentAppletSize);
              applet.start();

              // Validate and show the applet in event dispatch thread
              // to avoid deadlock.
              try {
                final AppletPanel p = this;
                final Applet a = applet;
                Runnable r =
                    new Runnable() {
                      @Override
                      public void run() {
                        p.validate();
                        a.setVisible(true);

                        // Fix for BugTraq ID 4041703.
                        // Set the default focus for an applet.
                        if (hasInitialFocus()) {
                          setDefaultFocus();
                        }
                      }
                    };
                AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
              } catch (InterruptedException ie) {
              } catch (InvocationTargetException ite) {
              }

              status = APPLET_START;
              showAppletStatus("started");
              break;
            }

          case APPLET_STOP:
            if (status != APPLET_START) {
              showAppletStatus("notstarted");
              break;
            }
            status = APPLET_STOP;

            // Hide the applet in event dispatch thread
            // to avoid deadlock.
            try {
              final Applet a = applet;
              Runnable r =
                  new Runnable() {
                    @Override
                    public void run() {
                      a.setVisible(false);
                    }
                  };
              AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
            } catch (InterruptedException ie) {
            } catch (InvocationTargetException ite) {
            }

            // During Applet.stop(), any AccessControlException on an involved Class remains in
            // the "memory" of the AppletClassLoader.  If the same instance of the ClassLoader is
            // reused, the same exception will occur during class loading.  Set the
            // AppletClassLoader's
            // exceptionStatusSet flag to allow recognition of what had happened
            // when reusing AppletClassLoader object.
            try {
              applet.stop();
            } catch (java.security.AccessControlException e) {
              setExceptionStatus(e);
              // rethrow exception to be handled as it normally would be.
              throw e;
            }
            showAppletStatus("stopped");
            break;

          case APPLET_DESTROY:
            if (status != APPLET_STOP && status != APPLET_INIT) {
              showAppletStatus("notstopped");
              break;
            }
            status = APPLET_DESTROY;

            // During Applet.destroy(), any AccessControlException on an involved Class remains in
            // the "memory" of the AppletClassLoader.  If the same instance of the ClassLoader is
            // reused, the same exception will occur during class loading.  Set the
            // AppletClassLoader's
            // exceptionStatusSet flag to allow recognition of what had happened
            // when reusing AppletClassLoader object.
            try {
              applet.destroy();
            } catch (java.security.AccessControlException e) {
              setExceptionStatus(e);
              // rethrow exception to be handled as it normally would be.
              throw e;
            }
            showAppletStatus("destroyed");
            break;

          case APPLET_DISPOSE:
            if (status != APPLET_DESTROY && status != APPLET_LOAD) {
              showAppletStatus("notdestroyed");
              break;
            }
            status = APPLET_DISPOSE;

            try {
              final Applet a = applet;
              Runnable r =
                  new Runnable() {
                    @Override
                    public void run() {
                      remove(a);
                    }
                  };
              AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
            } catch (InterruptedException ie) {
            } catch (InvocationTargetException ite) {
            }
            applet = null;
            showAppletStatus("disposed");
            disposed = true;
            break;

          case APPLET_QUIT:
            return;
        }
      } catch (Exception e) {
        status = APPLET_ERROR;
        if (e.getMessage() != null) {
          showAppletStatus("exception2", e.getClass().getName(), e.getMessage());
        } else {
          showAppletStatus("exception", e.getClass().getName());
        }
        showAppletException(e);
      } catch (ThreadDeath e) {
        showAppletStatus("death");
        return;
      } catch (Error e) {
        status = APPLET_ERROR;
        if (e.getMessage() != null) {
          showAppletStatus("error2", e.getClass().getName(), e.getMessage());
        } else {
          showAppletStatus("error", e.getClass().getName());
        }
        showAppletException(e);
      }
      clearLoadAbortRequest();
    }
  }