/* ObjectCreator.java --
   Copyright (C) 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 gnu.CORBA;

import gnu.CORBA.CDR.UnknownExceptionCtxHandler;
import gnu.CORBA.CDR.BufferredCdrInput;
import gnu.CORBA.CDR.BufferedCdrOutput;
import gnu.CORBA.CDR.AbstractCdrInput;
import gnu.CORBA.GIOP.ServiceContext;
import gnu.CORBA.typecodes.RecordTypeCode;
import gnu.classpath.VMStackWalker;

import org.omg.CORBA.Any;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.CompletionStatusHelper;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.UNKNOWN;
import org.omg.CORBA.UserException;
import org.omg.CORBA.portable.IDLEntity;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.ValueBase;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;

import javax.rmi.CORBA.Util;

/**
 * Creates java objects from the agreed IDL names for the simple case when the
 * CORBA object is directly mapped into the locally defined java class.
 * 
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 */
public class ObjectCreator
{
  /**
   * The standard OMG prefix.
   */
  public static final String OMG_PREFIX = "omg.org/";

  /**
   * The standard java prefix.
   */
  public static final String JAVA_PREFIX = "org.omg.";

  /**
   * The prefix for classes that are placed instide the gnu.CORBA namespace.
   */
  public static final String CLASSPATH_PREFIX = "gnu.CORBA.";

  /**
   * Maps classes to they IDL or RMI names. Computing RMI name is an expensive
   * operations, so frequently used RMI keys are reused. The map must be weak to
   * ensure that the class can be unloaded, when applicable.
   */
  public static Map m_names = new WeakHashMap();

  /**
   * Maps IDL strings into known classes. The map must be weak to ensure that
   * the class can be unloaded, when applicable.
   */
  public static Map m_classes = new WeakHashMap();

  /**
   * Maps IDL types to they helpers.
   */
  public static Map m_helpers = new WeakHashMap();

  /**
   * Try to instantiate an object with the given IDL name. The object must be
   * mapped to the local java class. The omg.org domain must be mapped into the
   * object in either org/omg or gnu/CORBA namespace.
   * 
   * @param IDL name
   * @return instantiated object instance or null if no such available.
   */
  public static java.lang.Object createObject(String idl, String suffix)
  {
    synchronized (m_classes)
      {
        Class known = (Class) (suffix == null ? m_classes.get(idl)
          : m_classes.get(idl + 0xff + suffix));
        Object object;

        if (known != null)
          {
            try
              {
                return known.newInstance();
              }
            catch (Exception ex)
              {
                RuntimeException rex = new RuntimeException(idl + " suffix "
                  + suffix, ex);
                throw rex;
              }
          }
        else
          {
            if (suffix == null)
              suffix = "";
            try
              {
                known = forName(toClassName(JAVA_PREFIX, idl) + suffix);
                object = known.newInstance();
              }
            catch (Exception ex)
              {
                try
                  {
                    known = forName(toClassName(CLASSPATH_PREFIX, idl)
                      + suffix);
                    object = known.newInstance();
                  }
                catch (Exception exex)
                  {
                    return null;
                  }
              }
            m_classes.put(idl + 0xff + suffix, known);
            return object;
          }
      }
  }

  /**
   * Read the system exception from the given stream.
   * 
   * @param input the CDR stream to read from.
   * @param contexts the service contexts in request/reply header/
   * 
   * @return the exception that has been stored in the stream (IDL name, minor
   * code and completion status).
   */
  public static SystemException readSystemException(InputStream input,
    ServiceContext[] contexts)
  {
    SystemException exception;

    String idl = input.read_string();
    int minor = input.read_ulong();
    CompletionStatus completed = CompletionStatusHelper.read(input);

    try
      {
        exception = (SystemException) createObject(idl, null);
        exception.minor = minor;
        exception.completed = completed;
      }
    catch (Exception ex)
      {
        UNKNOWN u = new UNKNOWN("Unsupported system exception " + idl, minor,
          completed);
        u.initCause(ex);
        throw u;
      }

    try
      {
        // If UnknownExceptionInfo is present in the contexts, read it and
        // set as a cause of this exception.
        ServiceContext uEx = ServiceContext.find(
          ServiceContext.UnknownExceptionInfo, contexts);

        if (uEx != null)
          {
            BufferredCdrInput in = new BufferredCdrInput(uEx.context_data);
            in.setOrb(in.orb());
            if (input instanceof AbstractCdrInput)
              {
                ((AbstractCdrInput) input).cloneSettings(in);
              }

            Throwable t = UnknownExceptionCtxHandler.read(in, contexts);
            exception.initCause(t);
          }
      }
    catch (Exception ex)
      {
        // Unsupported context format. Do not terminate as the user program may
        // not need it.
      }

    return exception;
  }

  /**
   * Reads the user exception, having the given Id, from the input stream. The
   * id is expected to be in the form like
   * 'IDL:test/org/omg/CORBA/ORB/communication/ourUserException:1.0'
   * 
   * @param idl the exception idl name.
   * @param input the stream to read from.
   * 
   * @return the loaded exception.
   * @return null if the helper class cannot be found.
   */
  public static UserException readUserException(String idl, InputStream input)
  {
    try
      {
        Class helperClass = findHelper(idl);

        Method read = helperClass.getMethod("read",
          new Class[] { org.omg.CORBA.portable.InputStream.class });

        return (UserException) read.invoke(null, new Object[] { input });
      }
    catch (MARSHAL mex)
      {
        // This one is ok to throw
        throw mex;
      }
    catch (Exception ex)
      {
        ex.printStackTrace();
        return null;
      }
  }

  /**
   * Gets the helper class name from the string like
   * 'IDL:test/org/omg/CORBA/ORB/communication/ourUserException:1.0'
   * 
   * @param IDL the idl name.
   */
  public static String toHelperName(String IDL)
  {
    String s = IDL;
    int a = s.indexOf(':') + 1;
    int b = s.lastIndexOf(':');

    s = IDL.substring(a, b);

    if (s.startsWith(OMG_PREFIX))
      s = JAVA_PREFIX + s.substring(OMG_PREFIX.length());

    return s.replace('/', '.') + "Helper";
  }

  /**
   * Writes the system exception data to CDR output stream.
   * 
   * @param output a stream to write data to.
   * @param ex an exception to write.
   */
  public static void writeSystemException(OutputStream output,
    SystemException ex)
  {
    String exIDL = getRepositoryId(ex.getClass());
    output.write_string(exIDL);
    output.write_ulong(ex.minor);
    CompletionStatusHelper.write(output, ex.completed);
  }

  /**
   * Converts the given IDL name to class name.
   * 
   * @param IDL the idl name.
   * 
   */
  protected static String toClassName(String prefix, String IDL)
  {
    String s = IDL;
    int a = s.indexOf(':') + 1;
    int b = s.lastIndexOf(':');

    s = IDL.substring(a, b);

    if (s.startsWith(OMG_PREFIX))
      s = prefix + s.substring(OMG_PREFIX.length());

    return s.replace('/', '.');
  }

  /**
   * Converts the given IDL name to class name and tries to load the matching
   * class. The OMG prefix (omg.org) is replaced by the java prefix org.omg. No
   * other prefixes are added.
   * 
   * @param IDL the idl name.
   * 
   * @return the matching class or null if no such is available.
   */
  public static Class Idl2class(String IDL)
  {
    synchronized (m_classes)
      {
        Class c = (Class) m_classes.get(IDL);

        if (c != null)
          return c;
        else
          {
            String s = IDL;
            int a = s.indexOf(':') + 1;
            int b = s.lastIndexOf(':');

            s = IDL.substring(a, b);

            if (s.startsWith(OMG_PREFIX))
              s = JAVA_PREFIX + s.substring(OMG_PREFIX.length());

            String cn = s.replace('/', '.');

            try
              {
                c = forName(cn);
                m_classes.put(IDL, c);
                return c;
              }
            catch (ClassNotFoundException ex)
              {
                return null;
              }
          }
      }
  }

  /**
   * Converts the given IDL name to class name, tries to load the matching class
   * and create an object instance with parameterless constructor. The OMG
   * prefix (omg.org) is replaced by the java prefix org.omg. No other prefixes
   * are added.
   * 
   * @param IDL the idl name.
   * 
   * @return instantiated object instance or null if such attempt was not
   * successful.
   */
  public static java.lang.Object Idl2Object(String IDL)
  {
    Class cx = Idl2class(IDL);

    try
      {
        if (cx != null)
          return cx.newInstance();
        else
          return null;
      }
    catch (Exception ex)
      {
        return null;
      }
  }

  /**
   * Convert the class name to IDL or RMI name (repository id). If the class
   * inherits from IDLEntity, ValueBase or SystemException, returns repository
   * Id in the IDL:(..) form. If it does not, returns repository Id in the
   * RMI:(..) form.
   * 
   * @param cx the class for that the name must be computed.
   * 
   * @return the idl or rmi name.
   */
  public static synchronized String getRepositoryId(Class cx)
  {
    String name = (String) m_names.get(cx);
    if (name != null)
      return name;

    String cn = cx.getName();
    if (!(IDLEntity.class.isAssignableFrom(cx)
      || ValueBase.class.isAssignableFrom(cx) || SystemException.class.isAssignableFrom(cx)))
      {
        // Not an IDL entity.
        name = Util.createValueHandler().getRMIRepositoryID(cx);
      }
    else
      {
        if (cn.startsWith(JAVA_PREFIX))
          cn = OMG_PREFIX
            + cn.substring(JAVA_PREFIX.length()).replace('.', '/');
        else if (cn.startsWith(CLASSPATH_PREFIX))
          cn = OMG_PREFIX
            + cn.substring(CLASSPATH_PREFIX.length()).replace('.', '/');

        name = "IDL:" + cn + ":1.0";
      }
    m_names.put(cx, name);
    return name;
  }

  /**
   * Insert the passed parameter into the given Any, assuming that the helper
   * class is available. The helper class must have the "Helper" suffix and be
   * in the same package as the class of the object being inserted.
   * 
   * @param into the target to insert.
   * 
   * @param object the object to insert. It can be any object as far as the
   * corresponding helper is provided.
   * 
   * @return true on success, false otherwise.
   */
  public static boolean insertWithHelper(Any into, Object object)
  {
    try
      {
        String helperClassName = object.getClass().getName() + "Helper";
        Class helperClass = forName(helperClassName);

        Method insert = helperClass.getMethod("insert", new Class[] {
          Any.class, object.getClass() });

        insert.invoke(null, new Object[] { into, object });

        return true;
      }
    catch (Exception exc)
      {
        // Failed due some reason.
        return false;
      }
  }

  /**
   * Insert the system exception into the given Any.
   */
  public static boolean insertSysException(Any into, SystemException exception)
  {
    try
      {
        BufferedCdrOutput output = new BufferedCdrOutput();

        String m_exception_id = getRepositoryId(exception.getClass());
        output.write_string(m_exception_id);
        output.write_ulong(exception.minor);
        CompletionStatusHelper.write(output, exception.completed);

        String name = getDefaultName(m_exception_id);

        GeneralHolder h = new GeneralHolder(output);

        into.insert_Streamable(h);

        RecordTypeCode r = new RecordTypeCode(TCKind.tk_except);
        r.setId(m_exception_id);
        r.setName(name);
        into.type(r);

        return true;
      }
    catch (Exception ex)
      {
        ex.printStackTrace();
        return false;
      }
  }

  /**
   * Get the type name from the IDL string.
   */
  public static String getDefaultName(String idl)
  {
    int f1 = idl.lastIndexOf("/");
    int p1 = (f1 < 0) ? 0 : f1;
    int p2 = idl.indexOf(":", p1);
    if (p2 < 0)
      p2 = idl.length();

    String name = idl.substring(f1 + 1, p2);
    return name;
  }

  /**
   * Insert this exception into the given Any. On failure, insert the UNKNOWN
   * exception.
   */
  public static void insertException(Any into, Throwable exception)
  {
    boolean ok = false;
    if (exception instanceof SystemException)
      ok = insertSysException(into, (SystemException) exception);
    else if (exception instanceof UserException)
      ok = insertWithHelper(into, exception);

    if (!ok)
      ok = insertSysException(into, new UNKNOWN());
    if (!ok)
      throw new InternalError("Exception wrapping broken");
  }

  /**
   * Find helper for the class with the given name.
   */
  public static Class findHelper(String idl)
  {
    synchronized (m_helpers)
      {
        Class c = (Class) m_helpers.get(idl);
        if (c != null)
          return c;
        try
          {
            String helper = toHelperName(idl);
            c = forName(helper);

            m_helpers.put(idl, c);
            return c;
          }
        catch (Exception ex)
          {
            return null;
          }
      }
  }
  
  /**
   * Load the class with the given name. This method tries to use the context
   * class loader first. If this fails, it searches for the suitable class
   * loader in the caller stack trace. This method is a central point where all
   * requests to find a class by name are delegated.
   */
  public static Class forName(String className) throws ClassNotFoundException
  {
    try
      {
        return Class.forName(className, true,
                             Thread.currentThread().getContextClassLoader());
      }
    catch (ClassNotFoundException nex)
      {
        /**
         * Returns the first user defined class loader on the call stack, or
         * null when no non-null class loader was found.
         */
        Class[] ctx = VMStackWalker.getClassContext();
        for (int i = 0; i < ctx.length; i++)
          {
            // Since we live in a class loaded by the bootstrap
            // class loader, getClassLoader is safe to call without
            // needing to be wrapped in a privileged action.
            ClassLoader cl = ctx[i].getClassLoader();
            try
              {
                if (cl != null)
                  return Class.forName(className, true, cl);
              }
            catch (ClassNotFoundException nex2)
              {
                // Try next.
              }
          }
      }
    throw new ClassNotFoundException(className);
  }
}