/* java.beans.Beans
   Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.beans;

import gnu.java.beans.DummyAppletStub;
import gnu.java.io.ClassLoaderObjectInputStream;

import java.applet.Applet;
import java.beans.beancontext.BeanContext;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.URL;

/**
 * <code>Beans</code> provides some helper methods that allow the basic
 * operations of Bean-ness.
 *
 * @author John Keiser
 * @author Robert Schuster
 *
 * @since 1.1
 * @status updated to 1.4
 *
 */
public class Beans
{
  static boolean designTime = false;
  static boolean guiAvailable = true;

  /**
   * Once again, we have a java.beans class with only
   * static methods that can be instantiated.  When
   * will the madness end? :)
   */
  public Beans()
  {
    // Does intentionally nothing here.
  }

   /** Creates a bean.
    * <p>This is a convenience method that calls <code>instantiate(cl, beanName, null, null)</code>.</p>
    *
    * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
    * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
    * @param beanName Name of a serialized bean or class name.
    * @return A newly created bean.
    * @throws IOException If access of an IO resource failed.
    * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
    */
    public static Object instantiate(ClassLoader cl, String beanName)
        throws IOException, ClassNotFoundException
    {
        return instantiate(cl, beanName, null, null);
    }

   /** Creates a bean.
    *
    * <p>This is a convenience method that calls <code>instantiate(cl, beanName, beanContext, null)</code>.</p>
    *
    * @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
    * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
    * @param beanName Name of a serialized bean or class name.
    * @param beanContext Context to which the newly created Bean should be added.
    * @return A newly created bean.
    * @throws IOException If access of an IO resource failed.
    * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
    */
    public static Object instantiate(
        ClassLoader cl,
        String beanName,
        BeanContext beanContext)
        throws IOException, ClassNotFoundException
    {
        return instantiate(cl, beanName, beanContext, null);
    }

   /** Instantiates a bean according to Beans 1.0.
    *
    * <p>In Beans 1.0 the instantiation scheme is as follows:</p>
    * <p>The name should be dot-separated (e.g "place.for.beans.myBean") and indicate either a
    * serialized object or a class name. In the first case all dots in the name are replaced with
    * slashes ('/') and ".ser" is appended ("place.for.beans.myBean" becomes "place/for/beans/myBean.ser").
    * The bean is then loaded as an application or system resource depending on whether a
    * <code>ClassLoader</code> was provided.</p>
    *
    * <p>If no such resource exists or if it contains no bean the name is interpreted as a class name of
    * which an instance is then created.</p>
    *
    * <p>If a <code>BeanContext</code> instance is available the created bean is added to it.</p>
    *
    * <p>If the created Bean is an <code>Applet</code> or subclass and an <code>AppletInitializer</code>
    * instance is available the applet is initialized and afterwards activated using the initializer. Additionally
    * every instantiated <code>Applet</code> bean is initialized using the {@link Applet.init} method.
    * Furthermore every applet gets a default <code>AppletStub</code>. The <code>Applet</code>'s
    * document base is the location of the ".ser" file if it was deserialized or the location of its class
    * file if it was instantiated.</p>
    *
    * <p>A <code>ClassNotFoundException</code> is not only thrown when a class name was unknown
    * but even when the class has public no-argument constructor
    * (<code>IllegalAccessException</code> is wrapped) or an exception is thrown while
    * invoking such a constructor (causing exception is wrapped).</p>
    *
    * @param cl ClassLoader to be used or <code>null</code> for the system classloader.
    * @param beanName Name of a serialized bean or class name.
    * @param beanContext Context to which the newly created Bean should be added.
    * @param initializer The AppletInitializer which is used for initializing <code>Applet</code> beans.
    * @return A newly created bean.
    * @throws IOException If access of an IO resource failed.
    * @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
    */
   public static Object instantiate(
        ClassLoader cl,
        String beanName,
        BeanContext beanContext,
        AppletInitializer initializer)
        throws IOException, ClassNotFoundException
   {
        Object bean = null;
        URL beanLocation = null;
        URL classLocation = null;

        // Converts bean name into a resource name (eg. "a.b.c" -> "a/b/c").
        String resourceName = beanName.replace('.', '/');

        /* Tries to get an input stream of the Bean, reading it as a system resource
         * if no ClassLoader is present or as an application resource if a classloader
         * is given.
         */
        beanLocation =
            (cl == null)
                ? ClassLoader.getSystemResource(resourceName + ".ser")
                : cl.getResource(resourceName + ".ser");

        // Reads the serialized Bean from the returned URL.
        if (beanLocation != null)
        {
            // Deserializes the bean instance.
            ObjectInputStream ois =
                (cl == null)
                    ? new ObjectInputStream(beanLocation.openStream())
                    : new ClassLoaderObjectInputStream(
                        beanLocation.openStream(),
                        cl);

            bean = ois.readObject();

            /* Implementation note: The result of ObjectInputStream.readObject()
            * may have been null at this point (its a valid value to deserialize)
            * and we explicitly want to try instantiation in such a case
            * (this is important for compatibility).
            */
        }

        // Instantiates the Bean using reflective instantiation if it has not been created yet.
        if (bean == null)
        {
            // Makes sure that the deserialization was NOT done.
            beanLocation = null;

            Class beanClass;
            if (cl == null)
            {
                beanClass = Class.forName(beanName);
                classLocation =
                    ClassLoader.getSystemResource(resourceName + ".class");
            }
            else
            {
                beanClass = cl.loadClass(beanName);
                classLocation = cl.getResource(resourceName + ".class");
            }

            // Instantiates and optionally registers the new bean.
            try
            {
                bean = beanClass.newInstance();
            }
            catch(Exception e) {
                /* Wraps all kinds of Exceptions in a ClassNotFoundException (this behavior
                 * matches with official >= 1.5, this was different for <=1.4)
                 */
                throw new ClassNotFoundException(null, e);
            }
        }

        /* Applet beans are treated in the following way:
         * - all AppletS get a default AppletStub
         * - all AppletS are initialized using the AppletInitializer instance (if it is available)
         * - as every other Bean Applets are added to a BeanContext if one is available
         * - each instantiated Applet is initialized using Applet.init() (this is not done for deserialized ones)
         * - finally AppletS get activated using the AppletInitializerS activate-Method
         *
         * The order of operations is important for compatibility.
         */
        Applet applet = null;
        if (bean instanceof Applet)
        {
            // Makes a second instanceof call unneccessary (instanceof is expensive).
            applet = (Applet) bean;

            /* The AppletStub's code and document base is set as follows:
             * The code base is always the URL from where the class data originated
             * (without the package name).
             * If the Applet was deserialized the document base is the location of
             * the serialized instance (usually the ".ser" file) otherwise its the URL
             * from where the class data originated (usually the absolute directory
             * location of the ".class" file).
             */
            applet.setStub(
                new DummyAppletStub(
                    applet
                        .getClass()
                        .getProtectionDomain()
                        .getCodeSource()
                        .getLocation(),
                    (beanLocation == null) ? classLocation : beanLocation));

            // Runs the Applet's initialization using an AppletInitializer.
            if (initializer != null)
            {
                initializer.initialize(applet, beanContext);
            }
        }

        // Adds the new bean to its BeanContext.
        if (beanContext != null)
        {
            beanContext.add(bean);
        }

        if (applet != null)
        {

            // Initializes an instantiated (not deserialized) Applet using its own method.
            if (beanLocation == null)
            {
                applet.init();
            }

            // Runs the Applet's activation using an AppletInitializer.
            if (initializer != null)
            {
                initializer.activate(applet);
            }
        }

        return bean;
   }

   /**
    * Returns the Bean as a different class type.
    * This should be used instead of casting to get a new
    * type view of a Bean, because in the future there may
    * be new types of Bean, even Beans spanning multiple
    * Objects.
    *
    * @param bean the Bean to cast.
    * @param newClass the Class to cast it to.
    *
    * @return the Bean as a new view, or if the operation
    *         could not be performed, the Bean itself.
    */
   public static Object getInstanceOf(Object bean, Class<?> newClass)
   {
        return bean;
   }

   /**
    * Determines whether the Bean can be cast to a different
    * class type.
    * This should be used instead of instanceof to determine
    * a Bean's castability, because in the future there may
    * be new types of Bean, even Beans spanning multiple
    * Objects.
    *
    * @param bean the Bean to cast.
    * @param newBeanClass the Class to cast it to.
    *
    * @return whether the Bean can be cast to the class type
    *         in question.
    */
   public static boolean isInstanceOf(Object bean, Class<?> newBeanClass)
   {
       return newBeanClass.isInstance(bean);
   }

   /**
    * Returns whether the GUI is available to use.
    * <p>Defaults to true.</p>
    *
    * @return whether the GUI is available to use.
    */
   public static boolean isGuiAvailable()
   {
       return guiAvailable;
   }

   /**
    * Returns whether it is design time.  Design time means
    * we are in a RAD tool.
    * <p>Defaults to false.</p>
    *
    * @return whether it is design time.
    */
   public static boolean isDesignTime()
   {
       return designTime;
   }

   /**
    * Sets whether the GUI is available to use.
    *
    * @param guiAvailable whether the GUI is available to use.
    */
   public static void setGuiAvailable(boolean guiAvailable)
       throws SecurityException
   {
        Beans.guiAvailable = guiAvailable;
   }

   /**
    * Sets whether it is design time.  Design time means we
    * are in a RAD tool.
    *
    * @param designTime whether it is design time.
    */
   public static void setDesignTime(boolean designTime)
       throws SecurityException
   {
       Beans.designTime = designTime;
   }

}
