/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) ESO - European Southern Observatory, 2011
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
package alma.acs.util;
import java.util.Hashtable;
import java.util.Vector;
/**
* Code provided by msekoran, mschilli added method parse(String).
*/
public class IorParser {
private IorParser() {}
//
// ==================== Sample usage ========================
//
/**
* Prints info on the specified IOR. If no IOR is given, a demo IOR will be used.
*/
public static void main (String[] args) {
// String defaultIOR =
// "IOR:012020202100000049444c3a434f5242416e65742f526f6f6d496e666f726d6174696f6e3a312e3000202020020000000153495670000000010101200500000073756e6700202020d7000000010000004e00000001504d43000000002100000049444c3a434f5242416e65742f526f6f6d496e666f726d6174696f6e3a312e30002020201a000000564953494f5242202d20494f4e414f52422054455354494e4700202000000000000000006a000000010100200c0000003139322e3136382e312e3300600420204e00000001504d43000000002100000049444c3a434f5242416e65742f526f6f6d496e666f726d6174696f6e3a312e30002020201a000000564953494f5242202d20494f4e414f52422054455354494e4700";
String maciManagerIOR = "IOR:000000000000001C49444C3A696A732E73692F6D6163692F4D616E616765723A312E300000000002000000000000006C000102000000000E3133342E3137312E34302E3139000BB8000000164F52422F4D616E61676572504F412F4D616E616765720000000000020000000000000008000000004A414300000000010000001C00000000000100010000000105010001000101090000000105010001000000010000002C0000000000000001000000010000001C00000000000100010000000105010001000101090000000105010001";
if (args.length == 0) {
System.err.println("Usage: (this) IOR:0123456789...");
System.exit(2);
}
String hexIOR = args[0];
new IOR(hexIOR).print();
String[] result = parse(hexIOR);
System.out.println("\n host / port: " + result[0] + " / " + result[1]);
}
//
// ========================= API ==============================
//
/**
* Parses the specified hex-IOR and returns info about it. If parsing fails for
* any reason (be it even an algorithmic bug), an IllegalArgumentException will be thrown.
*
* @return a string array (host, port)
* @throws IllegalArgumentException If parsing fails
*/
public static String[] parse (String hexIOR) throws IllegalArgumentException {
String host = null;
String port = null;
IOR ior = null;
try {
ior = new IOR(hexIOR);
} catch (Exception exc) {
throw new IllegalArgumentException("parsing failed: " + exc);
}
if (ior == null || ior._profiles == null) {
throw new IllegalArgumentException("parsing failed for unknown reason");
}
try {
// ior._profiles vector = (tag, hashtable, tag, hashtable, ...)
for (int i = 0; i < ior._numProfiles; i++) {
int tag = ((Long) ior._profiles.elementAt(i * 2)).intValue();
Hashtable profile_data = (Hashtable) ior._profiles.elementAt(i * 2 + 1);
if (tag == IOR.TAG_INTERNET_IOP) {
host = String.valueOf(profile_data.get("ProfileBody.host"));
port = String.valueOf(profile_data.get("ProfileBody.port"));
break;
}
}
} catch (Exception exc) {
throw new IllegalArgumentException("parsing failed: " + exc);
}
if (host == null || port == null) {
throw new IllegalArgumentException("parsing failed, host or port not found in IOR");
}
return new String[]{host, port};
}
//
// ============================================================
//
private static class CDR {
protected boolean _byteOrder;
protected int _byteLen;
protected int _bytePos = 1;
protected char[] _CDRArray;
public char getChar () {
return _CDRArray[_bytePos++];
}
public long getULong () {
skip(4);
return getBytes(4);
}
public int getUShort () {
skip(2);
return (int) getBytes(2);
}
public char[] getSequence () {
char[] sequence;
double seqLen;
seqLen = getULong();
sequence = new char[(int) seqLen];
for (int i = 0; i < seqLen; i++)
sequence[i] = _CDRArray[_bytePos++];
return sequence;
}
public String getString () {
// In IDL an unsigned long is a 32-bit unsigned integer. In Java a long
// is a 64-bit signed two's-complement integer.
double stringLen;
stringLen = getULong();
_bytePos += (int) stringLen;
return new String(_CDRArray, _bytePos - (int) stringLen, (int) stringLen - 1);
}
public void parseByteArray (char[] sequence) {
_CDRArray = sequence;
init();
}
public void parseHexString (String hexCDRString) {
char cdrByte;
_byteLen = hexCDRString.length() / 2;
_CDRArray = new char[_byteLen];
for (int i = 0; i < _byteLen * 2; i += 2) {
cdrByte = hex2dual(hexCDRString.charAt(i));
cdrByte = (char) (cdrByte << 4);
cdrByte |= hex2dual(hexCDRString.charAt(i + 1));
_CDRArray[i / 2] = cdrByte;
}
init();
}
public String toHexString () {
return new String();
}
// Protected methods.
protected long getBytes (int count) {
// Copy the octets depending on the server's byte order. Java Virtual
// Machine uses ordering in big-endian (IOR flag is 0 = false).
long buff = 0;
if (_byteOrder) {
// Server's ordering is little-endian (IOR flag is 1 = true).
for (int i = count - 1; i >= 0; i--) {
buff += _CDRArray[_bytePos + i];
if (i != 0)
buff = (buff << 8);
}
_bytePos += count;
/*
* for ( int i = 0; i < count; i++) ((long) Math.pow(256, i));
*/
} else {
// Server's ordering is big-endian (IOR flag is 0 = false).
for (int i = 0; i < count; i++) {
buff += _CDRArray[_bytePos++];
if (i != count - 1)
buff = (buff << 8);
}
/*
* for ( int i = 0; i < count; i++) ((long) Math.pow(256, count-i-1));
*/
}
return buff;
}
protected char hex2dual (char hc) {
char dual = 0;
if (Character.isDigit(hc))
dual = (char) (new Integer("" + hc).intValue());
else {
hc = Character.toLowerCase(hc);
if (hc == 'a')
dual = 10;
if (hc == 'b')
dual = 11;
if (hc == 'c')
dual = 12;
if (hc == 'd')
dual = 13;
if (hc == 'e')
dual = 14;
if (hc == 'f')
dual = 15;
}
return dual;
}
protected void init () {
if (_CDRArray[0] == 0)
_byteOrder = false;
else
_byteOrder = true;
}
protected void skip (int alignment) {
double remainder;
remainder = _bytePos % alignment;
if (remainder > 0)
_bytePos += (alignment - (int) remainder);
}
}
private static class IOR {
// Module IOP.
public static final long TAG_INTERNET_IOP = 0;
public static final long TAG_MULTIPLE_COMPONENTS = 1;
protected long _numProfiles;
protected String _iorString;
protected String _prefix; // IOP::IOR.
protected String _type_id; // IOP::IOR.
// IOP::IOR. This vector contains the tags (ProfileId) and the profile_data
// (octet sequences).
protected Vector _profiles = null;
public IOR(String iorString) {
_iorString = new String(iorString);
parse();
}
public long getNumProfiles () {
return _numProfiles;
}
public String getProfileData (long profileNo, String profileItem) {
String profile_item;
Hashtable profile_data;
profile_data = (Hashtable) _profiles.elementAt((int) profileNo * 2 + 1);
profile_item = profile_data.get(profileItem).toString();
return profile_item;
}
public int getProfileTag (long profileNo) {
int tag;
Long tagObj;
tagObj = (Long) _profiles.elementAt((int) profileNo * 2);
tag = tagObj.intValue();
return tag;
}
public String getTypeId () {
return _type_id;
}
public void print () {
if (_profiles != null) {
int tag;
Hashtable profile_data;
System.out.println("Type ID : " + _type_id);
System.out.println("Number of profiles: " + _numProfiles);
for (int i = 0; i < _numProfiles; i++) {
System.out.println("Profile No. " + (i + 1));
tag = ((Long) _profiles.elementAt(i * 2)).intValue();
profile_data = (Hashtable) _profiles.elementAt(i * 2 + 1);
switch (tag) {
case (int) TAG_INTERNET_IOP :
System.out.println(" Tag : TAG_INTERNET_IOP");
System.out.println(" Version.major : " + profile_data.get("Version.major"));
System.out.println(" Version.minor : " + profile_data.get("Version.minor"));
System.out.println(" Host : " + profile_data.get("ProfileBody.host"));
System.out.println(" Port : " + profile_data.get("ProfileBody.port"));
System.out.println(" Object key : " + profile_data.get("ProfileBody.object_key"));
break;
case (int) TAG_MULTIPLE_COMPONENTS :
System.out.println(" Tag : TAG_MULTIPLE_COMPONENTS");
System.out.println(" Profile data : " + profile_data.get("ProfileData"));
break;
default :
System.out.println(" New tag : " + tag);
System.out.println(" Profile data : " + profile_data.get("ProfileData"));
break;
}
}
}
}
protected void parse () {
long tag;
// IIOP::Version and IIOP::ProfileBody. This hashtable contains the
// version (char major, char minor), the host (string), the port
// (unsigned short) and the object_key (octet sequences).
Hashtable profile_data;
CDR iorCdr;
CDR profileCdr;
_prefix = _iorString.substring(0, 4);
iorCdr = new CDR();
iorCdr.parseHexString(_iorString.substring(4));
_type_id = iorCdr.getString();
_numProfiles = iorCdr.getULong();
// Store the tags and the profile_data sequences from IOP::TaggedProfile
// in the Vector _profiles.
_profiles = new Vector((int) _numProfiles * 2);
for (int i = 0; i < _numProfiles; i++) {
tag = iorCdr.getULong();
_profiles.addElement(new Long(tag));
profile_data = new Hashtable(5);
if (tag == TAG_INTERNET_IOP) {
profileCdr = new CDR();
// In future use ByteArrays instead of Strings.
profileCdr.parseByteArray(iorCdr.getSequence());
profile_data.put("Version.major", new Integer(profileCdr.getChar()));
profile_data.put("Version.minor", new Integer(profileCdr.getChar()));
profile_data.put("ProfileBody.host", profileCdr.getString());
profile_data.put("ProfileBody.port", new Integer(profileCdr.getUShort()));
profile_data.put("ProfileBody.object_key", new String(profileCdr.getSequence()));
} else
// If a MultipleComponentProfile or a profile with a new tag was
// discovered, skip the following sequence.
profile_data.put("ProfileData", new String(iorCdr.getSequence()));
_profiles.addElement(profile_data);
}
}
}
}
// //////////////////////////////////////////////////////
// / ------------------- API ------------------------ ///
// //////////////////////////////////////////////////////
// //////////////////////////////////////////////////////
// / ----------------- Internal --------------------- ///
// //////////////////////////////////////////////////////
//
//
//
//
//
//
//
//
//
//
//
//