blob: 0f434d2e8254d96004d37410170b858c0739a9e1 [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.
*/
//
// OB 3.x object keys:
// Transient: 0 + data
// Persistent: non-zero + data
//
// OB 4.x object key:
//
// The object key is: 0xabacab
// ['1'=transient|'0'=persistent]|[time\0]`poa \0 poa \0 poa \0\0 id'.
// NOTE: we then know that we've reached the id by the presence of the
// two \0\0. The time field we add for the POA create time (if
// transient) is current seconds. This is a tradeoff - it's most
// likely to be good enough.
//
package org.apache.yoko.orb.OB;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.yoko.orb.OB.IORUtil;
final public class ObjectKey {
static final Logger logger = Logger.getLogger(ObjectKey.class.getName());
public static byte[] CreateObjectKey(ObjectKeyData id) {
byte[] key;
//
// Count the number of bytes for the poas.
//
int len = id.serverId.length() + 1;
for (int i = 0; i < id.poaId.length; i++) {
len += id.poaId[i].length() + 1;
}
//
// Add one for the '\0'
//
len += 1;
//
// Add 4 for the magic number
//
len += 3;
//
// Add one for persistent bit
//
len += 1;
String time = null;
//
// If the POA is transient then add the time the poa was created
//
if (!id.persistent) {
time = "" + id.createTime;
len += time.length() + 1;
}
key = new byte[id.oid.length + len];
int data = 0;
//
// Add the magic number
//
key[data++] = (byte) 0xab;
key[data++] = (byte) 0xac;
key[data++] = (byte) 0xab;
//
// Add the persistent/transient information
//
if (id.persistent) {
key[data++] = (byte) '0';
} else {
key[data++] = (byte) '1';
int n = time.length();
for (int i = 0; i < n; i++) {
key[data++] = (byte) time.charAt(i);
}
data++;
}
//
// Copy in the data for the poas
//
int n = id.serverId.length();
for (int j = 0; j < n; j++) {
key[data++] = (byte) id.serverId.charAt(j);
}
data++;
for (int i = 0; i < id.poaId.length; i++) {
n = id.poaId[i].length();
for (int j = 0; j < n; j++) {
key[data++] = (byte) id.poaId[i].charAt(j);
}
data++;
}
//
// Add additional '\0'
//
data++;
System.arraycopy(id.oid, 0, key, data, id.oid.length);
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Created object key\n" + IORUtil.dump_octets(key));
}
return key;
}
//
// Parse an object key, filling in the fields of the ObjectKeyData.
// Return false if the object-key cannot be parsed, true otherwise.
//
public static boolean ParseObjectKey(byte[] key, ObjectKeyData keyData) {
//
// Parse out the POA's. This should be a sequence of strings
// terminated by two null values.
//
int data = 0;
int end = key.length;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Parsing object key\n" + IORUtil.dump_octets(key));
}
//
// First try to figure out whether the object-key is OB 4.x
// format. Must be at least 4 bytes - magic + 1|0.
//
// OB 4.x magic number: abacab
//
if (key.length > 4 && key[0] == (byte) 0xab && key[1] == (byte) 0xac
&& key[2] == (byte) 0xab) {
data += 3;
if (key[data] == '0') // persistent
{
logger.fine("Parsing persistent object key");
keyData.persistent = true;
keyData.createTime = 0;
++data;
} else {
if (key[data] != '1') {
logger.fine("Characters '1' expected at position " + data);
return false;
}
keyData.persistent = false;
++data;
//
// Remember the start of the time stamp
//
int start = data;
while (data < end && key[data] != '\0') {
data++;
}
if (data >= end) {
logger.fine("Missing '\0' in key data");
return false;
}
String t = new String(key, start, data - start);
try {
keyData.createTime = Integer.valueOf(t).intValue();
} catch (NumberFormatException ex) {
logger.log(Level.FINE, "Invalid timestamp in key data", ex);
return false;
}
//
// skip the null byte
//
++data;
}
boolean first = true;
java.util.Vector poaId = new java.util.Vector();
while (data < end) {
//
// Remember the start of the POA name
//
int start = data;
while (data < end && key[data] != '\0') {
data++;
}
//
// Ensure that we haven't gone too far...
//
if (data >= end) {
logger.fine("Missing '\0' in key data");
return false;
}
//
// Append this to the sequence of POA's.
//
if (first) {
keyData.serverId = new String(key, start, data - start);
logger.fine("Parsed serverId=" + keyData.serverId);
first = false;
} else {
String element = new String(key, start, data - start);
logger.fine("Parsed POA name=" + element);
poaId.addElement(element);
}
//
// Skip this byte, check to see if we have another '\0'
//
if (key[++data] == '\0') {
//
// Skip this byte
//
++data;
break;
}
}
keyData.poaId = new String[poaId.size()];
poaId.copyInto(keyData.poaId);
//
// Verify that we haven't gone too far.
//
if (data >= end) {
logger.fine("Missing object id in key data");
return false;
}
//
// Remaining portion is the ObjectId.
//
int len = end - data;
keyData.oid = new byte[len];
System.arraycopy(key, data, keyData.oid, 0, len);
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Parsed object id is\n" + IORUtil.dump_octets(keyData.oid));
}
return true;
} else {
logger.fine("Invalid magic number in object key");
return false;
}
}
}