blob: 405714878dddd05865aefa38a6e366d4c071166a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.yoko.orb.OCI.IIOP;
import org.apache.yoko.orb.CORBA.InputStream;
import org.apache.yoko.orb.CORBA.OutputStream;
import org.omg.CORBA.Any;
import org.omg.CSIIOP.CompoundSecMechList;
import org.omg.CSIIOP.CompoundSecMechListHelper;
import org.omg.CSIIOP.TAG_TLS_SEC_TRANS;
import org.omg.CSIIOP.TLS_SEC_TRANS;
import org.omg.CSIIOP.TLS_SEC_TRANSHelper;
import org.omg.CSIIOP.TransportAddress;
import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.FormatMismatch;
import org.omg.IOP.CodecPackage.TypeMismatch;
final public class Util {
static public org.omg.IOP.IOR createIOR(String host, int port, String id,
org.apache.yoko.orb.OCI.ProfileInfo profileInfo) {
org.omg.IOP.IOR ior = new org.omg.IOP.IOR();
ior.type_id = id;
ior.profiles = new org.omg.IOP.TaggedProfile[1];
ior.profiles[0] = new org.omg.IOP.TaggedProfile();
ior.profiles[0].tag = org.omg.IOP.TAG_INTERNET_IOP.value;
if (profileInfo.major == 1 && profileInfo.minor == 0) {
org.omg.IIOP.ProfileBody_1_0 body = new org.omg.IIOP.ProfileBody_1_0();
body.iiop_version = new org.omg.IIOP.Version((byte) 1, (byte) 0);
body.host = host;
if (port >= 0x8000)
body.port = (short) (port - 0xffff - 1);
else
body.port = (short) port;
body.object_key = profileInfo.key;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
org.omg.IIOP.ProfileBody_1_0Helper.write(out, body);
ior.profiles[0].profile_data = new byte[buf.length()];
System.arraycopy(buf.data(), 0, ior.profiles[0].profile_data, 0,
buf.length());
} else {
org.omg.IIOP.ProfileBody_1_1 body = new org.omg.IIOP.ProfileBody_1_1();
body.iiop_version = new org.omg.IIOP.Version(profileInfo.major,
profileInfo.minor);
body.host = host;
if (port >= 0x8000)
body.port = (short) (port - 0xffff - 1);
else
body.port = (short) port;
body.object_key = profileInfo.key;
body.components = profileInfo.components;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
OutputStream out = new OutputStream(buf);
out._OB_writeEndian();
org.omg.IIOP.ProfileBody_1_1Helper.write(out, body);
ior.profiles[0].profile_data = new byte[buf.length()];
System.arraycopy(buf.data(), 0, ior.profiles[0].profile_data, 0,
buf.length());
}
return ior;
}
static public org.omg.IOP.IOR createIOR(org.omg.IOP.IOR ior, String id,
byte[] key) {
//
// Extract the IIOP profile information from the provided IOR
//
int profile;
for (profile = 0; profile < ior.profiles.length; profile++)
if (ior.profiles[profile].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
break;
// TODO: Internal error?
org.apache.yoko.orb.OB.Assert._OB_assert(profile < ior.profiles.length);
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
ior.profiles[profile].profile_data,
ior.profiles[profile].profile_data.length);
InputStream in = new InputStream(buf, 0, false, null, null);
in._OB_readEndian();
org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
.read(in);
org.apache.yoko.orb.OCI.ProfileInfo profileInfo = new org.apache.yoko.orb.OCI.ProfileInfo();
profileInfo.key = key;
profileInfo.major = body.iiop_version.major;
profileInfo.minor = body.iiop_version.minor;
profileInfo.components = new org.omg.IOP.TaggedComponent[0];
return createIOR(body.host, body.port, id, profileInfo);
}
static public boolean extractProfileInfo(org.omg.IOP.IOR ior,
org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo) {
org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq = new org.apache.yoko.orb.OCI.ProfileInfoSeqHolder();
profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[0];
extractAllProfileInfos(ior, profileInfoSeq, false, null, 0, false, null);
if (profileInfoSeq.value.length > 0) {
profileInfo.value = profileInfoSeq.value[0];
return true;
}
return false;
}
static public boolean hostMatch(String host1, String host2,
boolean loopbackMatches) {
//
// Direct host name comparison
//
if (!host1.equals(host2)) {
//
//
// Direct host name comparision failed - must look up
// addresses to be really sure if the hosts differ
//
try {
java.net.InetAddress addr1 = java.net.InetAddress
.getByName(host1);
java.net.InetAddress addr2 = java.net.InetAddress
.getByName(host2);
if (!addr1.equals(addr2)) {
//
// Address comparison failed - shall I extract
// the key if the profile body contains the
// loopback address?
//
if (loopbackMatches) {
java.net.InetAddress loopback = java.net.InetAddress
.getByName("127.0.0.1");
if (!addr2.equals(loopback))
return false;
} else
return false;
}
} catch (java.net.UnknownHostException ex) {
//
// Continue on hostname lookup failure
//
return false;
}
}
return true;
}
static public void extractAllProfileInfos(org.omg.IOP.IOR ior,
org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq,
boolean performMatch, String host, int port, boolean loopbackMatches, Codec codec) {
short portNo;
if (port >= 0x8000) {
portNo = (short) (port - 0xffff - 1);
}
else {
portNo = (short) port;
}
java.util.Vector vec = new java.util.Vector();
for (int i = 0; i < ior.profiles.length; i++) {
if (ior.profiles[i].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
//
// Get the IIOP profile body
//
byte[] data = ior.profiles[i].profile_data;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
data, data.length);
InputStream in = new InputStream(buf, 0, false, null, null);
in._OB_readEndian();
org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
.read(in);
//
// Read components if the IIOP version is > 1.0
//
org.omg.IOP.TaggedComponent[] components;
if (body.iiop_version.major > 1 || body.iiop_version.minor > 0) {
int len = in.read_ulong();
components = new org.omg.IOP.TaggedComponent[len];
for (int j = 0; j < len; j++) {
components[j] = org.omg.IOP.TaggedComponentHelper.read(in);
}
} else {
components = new org.omg.IOP.TaggedComponent[0];
}
if (performMatch) {
//
// Check primary host/port
//
boolean match = false;
if (portNo == body.port
&& hostMatch(host, body.host, loopbackMatches)) {
match = true;
}
//
// Check alternate host/port
//
if (!match) {
for (int j = 0; j < components.length && !match; j++) {
if (components[j].tag == org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value) {
byte[] d = components[j].component_data;
org.apache.yoko.orb.OCI.Buffer b = new org.apache.yoko.orb.OCI.Buffer(
d, d.length);
InputStream s = new InputStream(b, 0, false,
null, null);
s._OB_readEndian();
String altHost = s.read_string();
short altPort = s.read_ushort();
if (portNo == altPort
&& hostMatch(host, altHost,
loopbackMatches)) {
match = true;
}
} else if (components[j].tag == org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST.value) {
Any any;
try {
any = codec.decode_value(components[j].component_data, CompoundSecMechListHelper.type());
CompoundSecMechList csml = CompoundSecMechListHelper.extract(any);
for (int k = 0; i < csml.mechanism_list.length && !match; i++) {
org.omg.IOP.TaggedComponent tc = csml.mechanism_list[k].transport_mech;
if (tc.tag == TAG_TLS_SEC_TRANS.value) {
Any tstAny = codec.decode_value(tc.component_data, TLS_SEC_TRANSHelper.type());
TLS_SEC_TRANS tst = TLS_SEC_TRANSHelper.extract(tstAny);
TransportAddress[] transportAddresses = tst.addresses;
for (TransportAddress addr: transportAddresses) {
if (portNo == addr.port && hostMatch(host, addr.host_name, loopbackMatches)) {
match = true;
break;
}
}
}
}
} catch (FormatMismatch e) {
} catch (TypeMismatch e) {
}
}
}
}
if (!match)
continue;
}
//
// OK, found a match
//
org.apache.yoko.orb.OCI.ProfileInfo profileInfo = new org.apache.yoko.orb.OCI.ProfileInfo();
profileInfo.key = body.object_key;
profileInfo.minor = body.iiop_version.minor;
profileInfo.major = body.iiop_version.major;
profileInfo.id = ior.profiles[i].tag;
profileInfo.index = i;
profileInfo.components = components;
vec.addElement(profileInfo);
}
}
if (vec.size() > 0) {
int len = profileInfoSeq.value.length;
if (len == 0) {
profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[vec
.size()];
vec.copyInto(profileInfoSeq.value);
} else {
org.apache.yoko.orb.OCI.ProfileInfo[] arr = new org.apache.yoko.orb.OCI.ProfileInfo[len
+ vec.size()];
System.arraycopy(profileInfoSeq.value, 0, arr, 0, len);
for (int i = 0; i < vec.size(); i++) {
arr[len + i] = (org.apache.yoko.orb.OCI.ProfileInfo) vec.elementAt(i);
}
profileInfoSeq.value = arr;
}
}
}
static public boolean equivalent(org.omg.IOP.IOR ior1, org.omg.IOP.IOR ior2) {
int p1, p2, b1, b2;
int cnt1 = 0, cnt2 = 0;
org.omg.IIOP.ProfileBody_1_0[] bodies1;
org.omg.IIOP.ProfileBody_1_0[] bodies2;
//
// Calculate number of IIOP profiles in ior1
//
for (p1 = 0; p1 < ior1.profiles.length; p1++)
if (ior1.profiles[p1].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
cnt1++;
//
// Calculate number of IIOP profiles in ior2
//
for (p2 = 0; p2 < ior2.profiles.length; p2++)
if (ior2.profiles[p2].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
cnt2++;
//
// Return false now if the number of IIOP profile bodies do not
// match
//
if (cnt1 != cnt2)
return false;
//
// Create an array with all IIOP profile bodies of ior1
//
bodies1 = new org.omg.IIOP.ProfileBody_1_0[cnt1];
for (p1 = 0, b1 = 0; p1 < ior1.profiles.length; p1++)
if (ior1.profiles[p1].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
byte[] data = ior1.profiles[p1].profile_data;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
data, data.length);
InputStream in = new InputStream(buf, 0, false, null, null);
in._OB_readEndian();
bodies1[b1++] = org.omg.IIOP.ProfileBody_1_0Helper.read(in);
}
if (b1 != cnt1)
throw new InternalError();
//
// Create an array with all IIOP profile bodies of ior2
//
bodies2 = new org.omg.IIOP.ProfileBody_1_0[cnt2];
for (p2 = 0, b2 = 0; p2 < ior2.profiles.length; p2++)
if (ior2.profiles[p2].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
byte[] data = ior2.profiles[p2].profile_data;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
data, data.length);
InputStream in = new InputStream(buf, 0, false, null, null);
in._OB_readEndian();
bodies2[b2++] = org.omg.IIOP.ProfileBody_1_0Helper.read(in);
}
if (b2 != cnt2)
throw new InternalError();
//
// Check for profile body matches
//
for (b1 = 0; b1 < cnt1; b1++) {
for (b2 = 0; b2 < cnt2; b2++) {
if (bodies2[b2] == null)
continue;
//
// Compare profile bodies
//
if (compareBodies(bodies1[b1], bodies2[b2])) {
//
// OK, found a match
//
bodies1[b1] = null;
bodies2[b2] = null;
break;
}
}
}
//
// Check whether there are any unmatched IIOP profile bodies
//
for (b1 = 0; b1 < cnt1; b1++)
if (bodies1[b1] != null)
return false;
for (b2 = 0; b2 < cnt2; b2++)
if (bodies2[b2] != null)
return false;
return true;
}
static boolean compareBodies(org.omg.IIOP.ProfileBody_1_0 body1,
org.omg.IIOP.ProfileBody_1_0 body2) {
//
// Compare versions
//
if (body1.iiop_version.major != body2.iiop_version.major
|| body1.iiop_version.minor != body2.iiop_version.minor)
return false;
//
// Compare ports
//
if (body1.port != body2.port)
return false;
//
// Compare object keys
//
if (body1.object_key.length != body2.object_key.length)
return false;
int k;
for (k = 0; k < body1.object_key.length; k++)
if (body1.object_key[k] != body2.object_key[k])
return false;
//
// Direct host name comparison
//
if (!body1.host.equals(body2.host)) {
//
// Direct host name comparision failed - must look up
// addresses to be really sure if the hosts differ
//
try {
java.net.InetAddress addr1 = java.net.InetAddress
.getByName(body1.host);
java.net.InetAddress addr2 = java.net.InetAddress
.getByName(body2.host);
if (!addr1.equals(addr2))
return false;
} catch (java.net.UnknownHostException ex) {
//
// Return false on hostname lookup failure
//
return false;
}
}
//
// OK, found a match
//
return true;
}
//
// Calculate a hash for an IOR containing IIOP profiles
//
static public int hash(org.omg.IOP.IOR ior, int maximum) {
int hash = 0;
for (int i = 0; i < ior.profiles.length; i++) {
if (ior.profiles[i].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
//
// Get the first IIOP profile body
//
byte[] data = ior.profiles[i].profile_data;
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
data, data.length);
InputStream in = new InputStream(buf, 0, false, null, null);
in._OB_readEndian();
org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
.read(in);
//
// Add port to hash
//
hash ^= body.port;
//
// Add object key to hash
//
for (int j = 0; j + 1 < body.object_key.length; j += 2)
hash ^= body.object_key[j + 1] * 256 + body.object_key[j];
}
}
return hash % (maximum + 1);
}
}