/* NameParser.java --
   Copyright (C) 2005, 2006 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.NamingService;

import gnu.CORBA.Minor;
import gnu.CORBA.OrbFunctional;
import gnu.CORBA.IOR;
import gnu.CORBA.Unexpected;
import gnu.CORBA.Version;

import gnu.java.lang.CPStringBuilder;

import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.DATA_CONVERSION;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CORBA.portable.Delegate;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming._NamingContextStub;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.StringTokenizer;

/**
 * Parses the alternative IOR representations into our IOR structure.
 * 
 * TODO This parser currently supports only one address per target string. A
 * string with the multiple addresses will be accepted, but only the last
 * address will be taken into consideration. The fault tolerance is not yet
 * implemented.
 * 
 * The key string is filtered using {@link java.net.URLDecoder} that replaces
 * the agreed escape sequences by the corresponding non alphanumeric characters.
 * 
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class NameParser
  extends NameTransformer
{
  /**
   * The corbaloc prefix.
   */
  public static final String pxCORBALOC = "corbaloc";

  /**
   * The corbaname prefix.
   */
  public static final String pxCORBANAME = "corbaname";

  /**
   * The IOR prefix.
   */
  public static final String pxIOR = "ior";
  
  /**
   * The file:// prefix.
   */
  public static final String pxFILE = "file://";
  
  /**
   * The ftp:// prefix.
   */
  public static final String pxFTP = "ftp://";
  
  /**
   * The http:// prefix.
   */
  public static final String pxHTTP = "http://";

  /**
   * Marks iiop protocol.
   */
  public static final String IIOP = "iiop";

  /**
   * Marks rir protocol.
   */
  public static final String RIR = "rir";

  /**
   * The default port value, as specified in OMG documentation.
   */
  public static final int DEFAULT_PORT = 2809;

  /**
   * The default name.
   */
  public static final String DEFAULT_NAME = "NameService";

  /**
   * The string to name converter, initialized on demand.
   */
  static NameTransformer converter;

  /**
   * The current position.
   */
  int p;

  /**
   * The address being parsed, splitted into tokens.
   */
  String[] t;

  /**
   * Parse CORBALOC.
   * 
   * The expected format is: <br>
   * 1. corbaloc:[iiop][version.subversion@]:host[:port]/key <br>
   * 2. corbaloc:rir:[/key] <br>
   * 3. corbaname:[iiop][version.subversion@]:host[:port]/key <br>
   * 4. corbaname:rir:[/key] <br>
   * 5. file://[file name]<br>
   * 6. http://[url]<br>
   * 7. ftp://[url]<br>
   * 
   * Protocol defaults to IOP, the object key defaults to the NameService.
   * 
   * @param corbaloc the string to parse.
   * @param orb the ORB, needed to create IORs and resolve rir references.
   * 
   * @return the resolved object.
   */
  public synchronized org.omg.CORBA.Object corbaloc(String corbaloc,
    OrbFunctional orb)
    throws BAD_PARAM
  {
    return corbaloc(corbaloc, orb, 0);
  }
  
  /**
   * Parse controlling against the infinite recursion loop.
   */
  private org.omg.CORBA.Object corbaloc(String corbaloc,
    OrbFunctional orb, int recursion)
  {
    // The used CORBA specification does not state how many times we should to
    //redirect, but the infinite loop may be used to knock out the system.
    // by malicious attempt.
    if (recursion > 10)
      throw new DATA_CONVERSION("More than 10 redirections");
    
    if (corbaloc.startsWith(pxFILE))
      return corbaloc(readFile(corbaloc.substring(pxFILE.length())), orb, recursion+1);
    else if (corbaloc.startsWith(pxHTTP))
      return corbaloc(readUrl(corbaloc), orb, recursion+1);
    else if (corbaloc.startsWith(pxFTP))
      return corbaloc(readUrl(corbaloc), orb, recursion+1);

    boolean corbaname;

    // The version numbers with default values.
    int major = 1;
    int minor = 0;

    // The host address.
    String host;

    // The port.
    int port = DEFAULT_PORT;

    // The object key as string.
    String key;

    StringTokenizer st = new StringTokenizer(corbaloc, ":@/.,#", true);

    t = new String[st.countTokens()];

    for (int i = 0; i < t.length; i++)
      {
        t[i] = st.nextToken();
      }

    p = 0;

    if (t[p].startsWith(pxCORBANAME))
      corbaname = true;
    else if (t[p].equalsIgnoreCase(pxCORBALOC))
      corbaname = false;
    else if (t[p].equalsIgnoreCase(pxIOR))
      {
        IOR ior = IOR.parse(corbaloc);
        return orb.ior_to_object(ior);
      }
    else
      throw new DATA_CONVERSION("Unsupported protocol: '" + t[p] + "'");

    p++;

    if (!t[p++].equals(":"))
      throw new BAD_PARAM("Syntax (':' expected after name prefix)");

    // Check for rir:
    if (t[p].equals(RIR))
      {
        p++;
        if (!t[p++].equals(":"))
          throw new BAD_PARAM("':' expected after 'rir'");

        key = readKey("/");

        Object object;
        try
          {
            object = orb.resolve_initial_references(key);
            return corbaname ? resolve(object) : object;
          }
        catch (InvalidName e)
          {
            throw new BAD_PARAM("Unknown initial reference '" + key + "'");
          }
      }
    else
    // Check for iiop.
    if (t[p].equals(IIOP) || t[p].equals(":"))
      {
        IOR ior = new IOR();

        Addresses: do
          { // Read addresses.
            if (t[p].equals(":"))
              {
                p++;
              }
            else
              {
                p++;
                if (!t[p++].equals(":"))
                  throw new BAD_PARAM("':' expected after 'iiop'");
                // Check if version is present.
                if (t[p + 1].equals("."))
                  if (t[p + 3].equals("@"))
                    {
                      // Version info present.
                      try
                        {
                          major = Integer.parseInt(t[p++]);
                        }
                      catch (NumberFormatException e)
                        {
                          throw new BAD_PARAM("Major version number '"
                            + t[p - 1] + "'");
                        }
                      p++; // '.' at this point.
                      try
                        {
                          minor = Integer.parseInt(t[p++]);
                        }
                      catch (NumberFormatException e)
                        {
                          throw new BAD_PARAM("Major version number '"
                            + t[p - 1] + "'");
                        }
                      p++; // '@' at this point.
                    }
              }

            ior.Internet.version = new Version(major, minor);

            // Then host data goes till '/' or ':'.
            CPStringBuilder bhost = new CPStringBuilder(corbaloc.length());
            while (!t[p].equals(":") && !t[p].equals("/") && !t[p].equals(","))
              bhost.append(t[p++]);

            host = bhost.toString();

            ior.Internet.host = host;

            if (t[p].equals(":"))
              {
                // Port specified.
                p++;
                try
                  {
                    port = Integer.parseInt(t[p++]);
                  }
                catch (NumberFormatException e)
                  {
                    throw new BAD_PARAM("Invalid port '" + t[p - 1] + "'");
                  }
              }

            ior.Internet.port = port;

            // Id is not listed.
            ior.Id = "";

            if (t[p].equals(","))
              p++;
            else
              break Addresses;
          }
        while (true);

        key = readKey("/");
        ior.key = key.getBytes();

        org.omg.CORBA.Object object = orb.ior_to_object(ior);
        return corbaname ? resolve(object) : object;
      }

    else
      throw new DATA_CONVERSION("Unsupported protocol '" + t[p] + "'");
  }
  
  /**
   * Read IOR from the file in the local file system.
   */
  String readFile(String file)
  {
    File f = new File(file);
    if (!f.exists())
      {
        DATA_CONVERSION err = new DATA_CONVERSION(f.getAbsolutePath()
          + " does not exist.");
        err.minor = Minor.Missing_IOR;
      }
    try
      {
        char[] c = new char[(int) f.length()];
        FileReader fr = new FileReader(f);
        fr.read(c);
        fr.close();
        return new String(c).trim();
      }
    catch (IOException ex)
      {
        DATA_CONVERSION d = new DATA_CONVERSION();
        d.initCause(ex);
        d.minor = Minor.Missing_IOR;
        throw (d);
      }
  }
  
  /**
   * Read IOR from the remote URL.
   */
  String readUrl(String url)
  {
    URL u;
    try
      {
        u = new URL(url);
      }
    catch (MalformedURLException mex)
      {
        throw new BAD_PARAM("Malformed URL: '" + url + "'");
      }

    try
      {
        InputStreamReader r = new InputStreamReader(u.openStream());

        CPStringBuilder b = new CPStringBuilder();
        int c;

        while ((c = r.read()) > 0)
          b.append((char) c);

        return b.toString().trim();
      }
    catch (Exception exc)
      {
        DATA_CONVERSION d = new DATA_CONVERSION("Reading " + url + " failed.");
        d.minor = Minor.Missing_IOR;
        throw d;
      }
  }

  private org.omg.CORBA.Object resolve(org.omg.CORBA.Object object)
  {
    NamingContext ns;
    String key = "?";
    try
      {
        if (object instanceof NamingContext)
          ns = (NamingContext) object;
        else
          {
            Delegate delegate = ((ObjectImpl) object)._get_delegate();
            ns = new _NamingContextStub();
            ((_NamingContextStub) ns)._set_delegate(delegate);
          }
      }
    catch (Exception ex)
      {
        BAD_PARAM bad = new BAD_PARAM("The CORBANAME target " + object
          + " is not a NamingContext");
        bad.minor = 10;
        bad.initCause(ex);
        throw bad;
      }

    if (converter == null)
      converter = new NameTransformer();

    try
      {
        key = readKey("#");
        object = ns.resolve(converter.toName(key));
        return object;
      }
    catch (Exception ex)
      {
        BAD_PARAM bad = new BAD_PARAM("Wrong CORBANAME '" + key + "'");
        bad.minor = 10;
        bad.initCause(ex);
        throw bad;
      }
  }

  private String readKey(String delimiter)
    throws BAD_PARAM
  {
    if (p < t.length)
      if (!t[p].equals(delimiter))
        {
          if (t[p].equals("#"))
            return DEFAULT_NAME;
          else
            throw new BAD_PARAM("'" + delimiter + "String' expected '" + t[p]
              + "' found");
        }

    CPStringBuilder bKey = new CPStringBuilder();
    p++;

    while (p < t.length && !t[p].equals("#"))
      bKey.append(t[p++]);

    if (bKey.length() == 0)
      return DEFAULT_NAME;

    try
      {
        return URLDecoder.decode(bKey.toString(), "UTF-8");
      }
    catch (UnsupportedEncodingException e)
      {
        throw new Unexpected("URLDecoder does not support UTF-8", e);
      }
  }

  static NameParser n = new NameParser();

  static void corbalocT(String ior, OrbFunctional orb)
  {
    System.out.println(ior);
    System.out.println(n.corbaloc(ior, orb));
    System.out.println();
  }

  public static void main(String[] args)
  {
    try
      {
        OrbFunctional orb = (OrbFunctional) ORB.init(args, null);
        corbalocT("corbaloc:iiop:1.3@155axyz.com/Prod/aTradingService", orb);
        corbalocT("corbaloc:iiop:2.7@255bxyz.com/Prod/bTradingService", orb);
        corbalocT("corbaloc:iiop:355cxyz.com/Prod/cTradingService", orb);
        corbalocT("corbaloc:iiop:2.7@255bxyz.com/Prod/bTradingService", orb);
        corbalocT("corbaloc:iiop:355cxyz.com:7777/Prod/cTradingService", orb);

        corbalocT("corbaloc::556xyz.com:80/Dev/NameService", orb);
        corbalocT("corbaloc:iiop:1.2@host1:3076/0", orb);

        corbalocT("corbaloc:rir:/NameService", orb);
        corbalocT("corbaloc:rir:/", orb);
        corbalocT("corbaloc:rir:", orb);

        corbalocT("corbaloc:rir:/NameService", orb);
        corbalocT("corbaloc:rir:/", orb);
        corbalocT("corbaloc:rir:", orb);

        corbalocT("corbaloc::555xyz.com,:556xyz.com:80/Dev/NameService", orb);
      }
    catch (BAD_PARAM e)
      {
        e.printStackTrace(System.out);
      }
  }
}
