package com.sun.slp;
import java.util.*;
import java.io.*;
class ServiceStoreInMemory extends Object implements ServiceStore {
private interface BVCollector {
abstract void setReturn(ServiceRecordInMemory rec);
}
private class ParserBVCollector extends Object implements BVCollector {
Parser.ParserRecord prReturns = null;
private Vector scopes = null;
ParserBVCollector(Vector scopes) {
this.scopes = scopes;
}
public void setReturn(ServiceRecordInMemory rec) {
Hashtable services = prReturns.services;
Hashtable signatures = prReturns.signatures;
ServiceURL surl = rec.getServiceURL();
if (services.get(surl) == null) {
Vector s = (Vector)rec.getScopes().clone();
DATable.filterScopes(s, scopes, false);
long lifetime =
(rec.getExpirationTime() -
System.currentTimeMillis()) / 1000;
if (lifetime > 0) {
ServiceURL url =
new ServiceURL(surl.toString(), (int)lifetime);
services.put(surl, s);
Hashtable sig = rec.getURLSignature();
if (sig != null) {
signatures.put(url, sig);
}
}
}
}
}
private class AttributeBVCollector extends Object implements BVCollector {
private Hashtable alreadySeen = new Hashtable();
private Vector attrTags = null;
private Hashtable ht = new Hashtable();
private Vector ret = null;
AttributeBVCollector(Vector attrTags, Vector ret) {
this.attrTags = attrTags;
this.ret = ret;
}
public void setReturn(ServiceRecordInMemory rec) {
if (alreadySeen.get(rec) == null) {
alreadySeen.put(rec, rec);
try {
findMatchingAttributes(rec, attrTags, ht, ret);
} catch (ServiceLocationException ex) {
Assert.slpassert(false,
"ssim_attrbvc_botch",
new Object[] {ex.getMessage()});
}
}
}
}
private class ScopeBVCollector extends Object implements BVCollector {
private Hashtable alreadySeen = new Hashtable();
private Vector records = null;
private Vector scopes = null;
ScopeBVCollector(Vector records, Vector scopes) {
this.records = records;
this.scopes = scopes;
}
public void setReturn(ServiceRecordInMemory rec) {
if (alreadySeen.get(rec) == null) {
alreadySeen.put(rec, rec);
if (scopes == null) {
records.addElement(rec);
} else {
int i;
Vector rscopes = rec.getScopes();
int len = scopes.size();
for (i = 0; i < len; i++) {
if (rscopes.contains(scopes.elementAt(i))) {
records.addElement(rec);
break;
}
}
}
}
}
}
private class AllBVCollector extends Object implements BVCollector {
private Vector records = null;
AllBVCollector(Vector records) {
this.records = records;
}
public void setReturn(ServiceRecordInMemory rec) {
if (!records.contains(rec)) {
records.addElement(rec);
}
}
}
private class List extends Object {
ServiceRecordInMemory record = null;
List next = null;
List prev = null;
List(ServiceRecordInMemory record) {
this.record = record;
}
synchronized List insertAfter(ServiceRecordInMemory record) {
List newRec = new List(record);
newRec.next = next;
newRec.prev = this;
if (next != null) {
next.prev = newRec;
}
this.next = newRec;
return newRec;
}
synchronized void delete() {
if (next != null) {
next.prev = prev;
}
if (prev != null) {
prev.next = next;
}
prev = null;
next = null;
}
}
private class RegRecord extends Object {
Object value = null;
List head = new List(null);
RegRecord(Object value) {
this.value = value;
}
List add(ServiceRecordInMemory rec) {
return head.insertAfter(rec);
}
boolean setReturn(BVCollector returns) {
boolean match = false;
List l = head;
for (l = l.next; l != null; l = l.next) {
ServiceRecordInMemory rec = l.record;
returns.setReturn(rec);
match = true;
}
return match;
}
public String toString() {
return "<RegRecord value="+value+"list="+head.next+">";
}
}
private class BtreeVector extends Object {
private Vector contents = new Vector();
public String toString() {
return "<BtreeVector "+contents.toString()+">";
}
Vector getContents() {
return contents;
}
boolean getAll(BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
match = match | rec.setReturn(returns);
}
return match;
}
List add(Object value, ServiceRecordInMemory record) {
RegRecord rec = walkVector(value, true);
return rec.add(record);
}
boolean matchDoesNotContain(Object pattern, BVCollector returns) {
int i, n = contents.size();
Vector noMatch = new Vector();
boolean match = false;
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (!compareEqual(rec.value, pattern)) {
noMatch.addElement(rec);
}
}
n = noMatch.size();
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)noMatch.elementAt(i);
match = match | rec.setReturn(returns);
}
return match;
}
boolean
matchEqual(Object pattern, BVCollector returns) {
boolean match = false;
if (pattern instanceof AttributePattern) {
int i, n = contents.size();
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
AttributeString val = (AttributeString)rec.value;
AttributePattern pat = (AttributePattern)pattern;
if (pat.match(val)) {
match = match | rec.setReturn(returns);
}
}
} else {
RegRecord rec = walkVector(pattern, false);
if (rec == null) {
match = false;
} else {
match = rec.setReturn(returns);
}
}
return match;
}
boolean
matchNotEqual(Object pattern, BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (!compareEqual(rec.value, pattern)) {
match = match | rec.setReturn(returns);
}
}
return match;
}
boolean
matchLessEqual(Object pattern,
BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (!compareLessEqual(rec.value, pattern)) {
break;
}
match = match | rec.setReturn(returns);
}
return match;
}
boolean
matchNotLessEqual(Object pattern,
BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = n - 1; i >= 0; i--) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (compareLessEqual(rec.value, pattern)) {
break;
}
match = match | rec.setReturn(returns);
}
return match;
}
boolean
matchGreaterEqual(Object pattern,
BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = n - 1; i >= 0; i--) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (!compareGreaterEqual(rec.value, pattern)) {
break;
}
match = match | rec.setReturn(returns);
}
return match;
}
boolean
matchNotGreaterEqual(Object pattern,
BVCollector returns) {
int i, n = contents.size();
boolean match = false;
for (i = 0; i < n; i++) {
RegRecord rec = (RegRecord)contents.elementAt(i);
if (compareGreaterEqual(rec.value, pattern)) {
break;
}
match = match | rec.setReturn(returns);
}
return match;
}
private RegRecord
walkVector(Object pattern, boolean update) {
int size = contents.size();
int middle = size / 2;
int top = size - 1;
int bottom = 0;
RegRecord rec = null;
top = (top < 0 ? 0:top);
while (size > 0) {
rec = (RegRecord)contents.elementAt(middle);
if (update) {
if (rec.head.next == null) {
contents.removeElementAt(middle);
size = size - 1;
middle = bottom + (size / 2);
top = top - 1;
top = (top < 0 ? 0:top);
continue;
}
}
if (compareEqual(rec.value, pattern)) {
return rec;
} else if (compareLessEqual(pattern, rec.value)) {
top = middle;
size = (top - bottom);
middle = top - (size / 2);
middle = (middle < 0 ? 0:middle);
if (middle == top) {
rec = null;
RegRecord trec = (RegRecord)contents.elementAt(bottom);
if (update) {
rec = new RegRecord(pattern);
if (compareEqual(trec.value, pattern)) {
return trec;
} else if (compareLessEqual(pattern, trec.value)) {
contents.insertElementAt(rec, bottom);
} else {
contents.insertElementAt(rec, middle);
}
} else {
if (compareEqual(trec.value, pattern)) {
rec = trec;
}
}
break;
}
} else if (compareGreaterEqual(pattern, rec.value)) {
bottom = middle;
size = (top - bottom);
middle = bottom + (size / 2);
if (middle == bottom) {
rec = null;
RegRecord trec = (RegRecord)contents.elementAt(top);
if (update) {
rec = new RegRecord(pattern);
if (compareEqual(trec.value, pattern)) {
return trec;
} else if (compareGreaterEqual(pattern,
trec.value)) {
int i = top + 1;
if (i >= contents.size()) {
contents.addElement(rec);
} else {
contents.insertElementAt(rec, i);
}
} else {
contents.insertElementAt(rec, top);
}
} else {
if (compareEqual(trec.value, pattern)) {
rec = trec;
}
}
break;
}
}
}
if (update && rec == null) {
rec = new RegRecord(pattern);
Assert.slpassert((contents.size() == 0),
"ssim_btree_botch",
new Object[0]);
contents.addElement(rec);
}
return rec;
}
boolean
compareEqual(Object target, Object pattern) {
if (target instanceof Integer ||
target instanceof Boolean ||
target instanceof Opaque ||
target instanceof Long) {
if (pattern.equals(target)) {
return true;
}
} else if (target instanceof AttributeString) {
if (((AttributeString)pattern).match(
(AttributeString)target)) {
return true;
}
} else {
Assert.slpassert(false,
"ssim_unk_qtype",
new Object[] {pattern.getClass().getName()});
}
return false;
}
boolean
compareLessEqual(Object target, Object pattern) {
if (target instanceof Integer) {
if (((Integer)target).intValue() <=
((Integer)pattern).intValue()) {
return true;
}
} else if (target instanceof AttributeString) {
if (((AttributeString)target).lessEqual(
(AttributeString)pattern)) {
return true;
}
} else if (target instanceof Long) {
if (((Long)target).longValue() <=
((Long)pattern).longValue()) {
return true;
}
} else if (target instanceof Boolean ||
target instanceof Opaque) {
if (target.toString().compareTo(pattern.toString()) <= 0) {
return true;
}
} else {
Assert.slpassert(false,
"ssim_unk_qtype",
new Object[] {target.getClass().getName()});
}
return false;
}
boolean
compareGreaterEqual(Object target, Object pattern) {
if (target instanceof Integer) {
if (((Integer)target).intValue() >=
((Integer)pattern).intValue()) {
return true;
}
} else if (target instanceof AttributeString) {
if (((AttributeString)target).greaterEqual(
(AttributeString)pattern)) {
return true;
}
} else if (target instanceof Long) {
if (((Long)target).longValue() >=
((Long)pattern).longValue()) {
return true;
}
} else if (target instanceof Boolean ||
target instanceof Opaque) {
if (target.toString().compareTo(pattern.toString()) >= 0) {
return true;
}
} else {
Assert.slpassert(false,
"ssim_unk_qtype",
new Object[] {target.getClass().getName()});
}
return false;
}
}
private class InMemoryEvaluator implements Parser.QueryEvaluator {
private Hashtable attrLevel;
private BtreeVector attrLevelNot;
private Vector inScopes;
private ParserBVCollector returns;
InMemoryEvaluator(Hashtable ht,
BtreeVector btv,
Vector nscopes) {
attrLevel = ht;
attrLevelNot = btv;
inScopes = nscopes;
returns = new ParserBVCollector(inScopes);
}
public boolean
evaluate(AttributeString tag,
char op,
Object pattern,
boolean invert,
Parser.ParserRecord prReturns)
throws ServiceLocationException {
boolean match = false;
returns.prReturns = prReturns;
if (invert) {
match = attrLevelNot.matchDoesNotContain(tag, returns);
}
Hashtable ttable = (Hashtable)attrLevel.get(tag);
if (ttable == null) {
return match;
}
if (op == Parser.PRESENT) {
if (!invert) {
match = attrLevelNot.matchEqual(tag, returns);
}
return match;
}
Class pclass = pattern.getClass();
String typeKey = pclass.getName();
if (pattern instanceof AttributePattern) {
typeKey = pclass.getSuperclass().getName();
}
if (invert) {
Enumeration en = ttable.keys();
while (en.hasMoreElements()) {
String key = (String)en.nextElement();
if (!key.equals(typeKey)) {
BtreeVector bvec = (BtreeVector)ttable.get(key);
match = match | bvec.getAll(returns);
}
}
}
BtreeVector bvec = (BtreeVector)ttable.get(typeKey);
switch (op) {
case Parser.EQUAL:
if (!invert) {
match = bvec.matchEqual(pattern, returns);
} else {
match = bvec.matchNotEqual(pattern, returns);
}
break;
case Parser.LESS:
if (!invert) {
match = bvec.matchLessEqual(pattern, returns);
} else {
match = bvec.matchNotLessEqual(pattern, returns);
}
break;
case Parser.GREATER:
if (!invert) {
match = bvec.matchGreaterEqual(pattern, returns);
} else {
match = bvec.matchNotGreaterEqual(pattern, returns);
}
break;
default:
Assert.slpassert(false,
"ssim_unk_qop",
new Object[] {Character.valueOf((char)op)});
}
return match;
}
}
private class ServiceRecordInMemory extends Object
implements ServiceStore.ServiceRecord {
private ServiceURL serviceURL = null;
private Vector attrList = null;
private Locale locale = null;
private long timeToDie = 0;
private Vector scopes = null;
private Hashtable urlSig = null;
private Hashtable attrSig = null;
ServiceRecordInMemory(ServiceURL surl, Vector alist,
Vector nscopes, Locale loc,
Hashtable nurlSig,
Hashtable nattrSig) {
Assert.nonNullParameter(surl, "surl");
Assert.nonNullParameter(alist, "alist");
Assert.nonNullParameter(nscopes, "nscopes");
Assert.nonNullParameter(loc, "loc");
serviceURL = surl;
attrList = attributeVectorToServerAttribute(alist, loc);
scopes = nscopes;
locale = loc;
urlSig = nurlSig;
attrSig = nattrSig;
int lifetime = serviceURL.getLifetime();
timeToDie = lifetime * 1000 + System.currentTimeMillis();
}
public final ServiceURL getServiceURL() {
return serviceURL;
}
public final Vector getAttrList() {
return attrList;
}
public final Locale getLocale() {
return locale;
}
public final Vector getScopes() {
return scopes;
}
public long getExpirationTime() {
return timeToDie;
}
public Hashtable getURLSignature() {
return urlSig;
}
public Hashtable getAttrSignature() {
return attrSig;
}
final void setAttrList(Vector newList) {
attrList = newList;
}
final void setScopes(Vector newScopes) {
scopes = newScopes;
}
final void setURLSignature(Hashtable nauth) {
urlSig = nauth;
}
final void setAttrSignature(Hashtable nauth) {
attrSig = nauth;
}
public String toString() {
String ret = "{";
ret +=
serviceURL + ", " + locale + ", " + attrList + ", " +
scopes + ", " + locale + ", " + urlSig + ", " + attrSig;
ret += "}";
return ret;
}
private Vector
attributeVectorToServerAttribute(Vector attrs, Locale locale) {
int i, n = attrs.size();
Vector v = new Vector();
for (i = 0; i < n; i++) {
ServiceLocationAttribute attr =
(ServiceLocationAttribute)attrs.elementAt(i);
v.addElement(new ServerAttribute(attr, locale));
}
return v;
}
}
private class STLRecord extends Object {
Hashtable attrValueSort = new Hashtable();
BtreeVector attrSort = new BtreeVector();
boolean isAbstract = false;
STLRecord(boolean isAbstract) {
this.isAbstract = isAbstract;
}
}
private final static String INTEGER_TYPE = "java.lang.Integer";
private final static String ATTRIBUTE_STRING_TYPE =
"com.sun.slp.AttributeString";
private final static String BOOLEAN_TYPE = "java.lang.Boolean";
private final static String OPAQUE_TYPE = "com.sun.slp.Opaque";
private Hashtable scopeTypeLangTable = new Hashtable();
private Hashtable urlScopeLangTable = new Hashtable();
private Hashtable sstLocales = new Hashtable();
BtreeVector ageOutQueue = new BtreeVector();
private final static int NO_REGS = 0;
private final static int NO_REGS_IN_LOCALE = 1;
private final static int REGS_IN_LOCALE = 2;
private long bootTime = SLPConfig.currentSLPTime();
public long getStateTimestamp() {
return bootTime;
}
synchronized public long ageOut(Vector deleted) {
SLPConfig conf = SLPConfig.getSLPConfig();
boolean traceDrop = conf.traceDrop();
Vector queue = ageOutQueue.getContents();
int i;
for (i = 0; i < queue.size(); i++) {
RegRecord qRec = (RegRecord)queue.elementAt(i);
long exTime = ((Long)(qRec.value)).longValue();
long time = System.currentTimeMillis();
if (exTime > time) {
break;
}
queue.removeElementAt(i);
i--;
List l = qRec.head.next;
while (l != null) {
ServiceRecordInMemory rec = l.record;
ServiceURL url = rec.getServiceURL();
Vector scopes = rec.getScopes();
Locale locale = rec.getLocale();
if (traceDrop) {
conf.writeLog("ssim_ageout",
new Object[] {
url,
rec.getAttrList(),
scopes,
locale,
rec.getURLSignature(),
rec.getAttrSignature(),
Long.toString(time),
Long.toString(exTime)});
}
deleted.addElement(rec);
l = l.next;
String lang = locale.getLanguage();
deregisterInternal(url, scopes, lang);
}
}
long newSleepy = Defaults.lMaxSleepTime;
if (queue.size() > 0) {
RegRecord rec = (RegRecord)queue.elementAt(0);
newSleepy =
((Long)(rec.value)).longValue() - System.currentTimeMillis();
newSleepy = (newSleepy > 0 ? newSleepy:0);
}
return newSleepy;
}
synchronized public boolean
register(ServiceURL url, Vector attrs,
Vector scopes, Locale locale,
Hashtable urlSig, Hashtable attrSig)
throws ServiceLocationException {
boolean existing = false;
String lang = locale.getLanguage();
ServiceRecordInMemory rec = findExistingRecord(url, null, lang);
if (rec != null) {
if (urlSig != null) {
Enumeration spis = urlSig.keys();
while (spis.hasMoreElements()) {
Object spi = spis.nextElement();
if (rec.urlSig.remove(spi) == null) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"not_all_spis_present",
new Object[] {spi});
}
}
if (rec.urlSig.size() != 0) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"not_all_spis_present",
new Object[] {rec.urlSig.keys()});
}
}
deregisterInternal(url, rec.getScopes(), lang);
existing = true;
}
rec = new ServiceRecordInMemory(url, attrs, scopes,
locale, urlSig, attrSig);
registerInternal(rec);
return existing;
}
synchronized public void
deregister(ServiceURL url, Vector scopes, Hashtable urlSig)
throws ServiceLocationException {
ServiceRecordInMemory oldRec =
findExistingRecord(url, scopes, null);
if (oldRec == null) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"ssim_no_rec",
new Object[] {url});
}
if (urlSig != null) {
Enumeration spis = urlSig.keys();
while (spis.hasMoreElements()) {
Object spi = spis.nextElement();
if (oldRec.urlSig.remove(spi) == null) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"not_all_spis_present",
new Object[] {spi});
}
}
if (oldRec.urlSig.size() != 0) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"not_all_spis_present",
new Object[] {oldRec.urlSig.keys()});
}
}
deregisterInternal(oldRec.getServiceURL(), scopes, null);
}
synchronized public void
updateRegistration(ServiceURL url, Vector attrs,
Vector scopes, Locale locale)
throws ServiceLocationException {
String lang = locale.getLanguage();
ServiceRecordInMemory oldRec =
findExistingRecord(url, scopes, lang);
if (oldRec == null) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_UPDATE,
"ssim_no_rec",
new Object[] {url});
}
ServiceType type = url.getServiceType();
if (!type.isServiceURL()) {
checkForExistingUnderOtherServiceType(url, scopes);
}
deregisterInternal(url, scopes, lang);
ServiceRecordInMemory rec =
new ServiceRecordInMemory(url, attrs, scopes,
locale, null, null);
mergeOldRecordIntoNew(oldRec, rec);
registerInternal(rec);
}
synchronized public void
deleteAttributes(ServiceURL url,
Vector scopes,
Vector attrTags,
Locale locale)
throws ServiceLocationException {
String lang = SLPConfig.localeToLangTag(locale);
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(url.toString());
if (scopeLevel == null) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"ssim_no_rec",
new Object[] {url});
}
checkScopeStatus(url,
scopes,
ServiceLocationException.INVALID_REGISTRATION);
Vector attrPatterns =
stringVectorToAttributePattern(attrTags, Defaults.locale);
Enumeration en = scopeLevel.keys();
Assert.slpassert(en.hasMoreElements(),
"ssim_empty_scope_table",
new Object[] {url});
Hashtable ht = new Hashtable();
boolean foundIt = false;
while (en.hasMoreElements()) {
String scope = (String)en.nextElement();
Hashtable langLevel = (Hashtable)scopeLevel.get(scope);
Enumeration een = langLevel.keys();
Assert.slpassert(een.hasMoreElements(),
"ssim_empty_lang_table",
new Object[] {url});
Vector listVec = (Vector)langLevel.get(lang);
if (listVec == null) {
continue;
}
foundIt = true;
List elem = (List)listVec.elementAt(0);
ServiceRecordInMemory rec = elem.record;
Locale loc = rec.getLocale();
if (ht.get(rec) != null) {
continue;
}
ht.put(rec, rec);
deregisterInternal(url, rec.getScopes(), lang);
if (loc.getLanguage().equals("tr")) {
Vector turkishTags =
stringVectorToAttributePattern(attrTags, loc);
deleteAttributes(rec, turkishTags);
} else {
deleteAttributes(rec, attrPatterns);
}
registerInternal(rec);
}
if (!foundIt) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"ssim_no_rec_locale",
new Object[] {url, locale});
}
}
synchronized public Vector
findServiceTypes(String namingAuthority, Vector scopes)
throws ServiceLocationException {
Vector ret = new Vector();
Enumeration keys = scopeTypeLangTable.keys();
boolean isWildCard = namingAuthority.equals("*");
boolean isIANA = (namingAuthority.length() <= 0);
while (keys.hasMoreElements()) {
String sstKey = (String)keys.nextElement();
if (isAbstractTypeRecord(sstKey)) {
continue;
}
String keyScope = keyScope(sstKey);
if (scopes.contains(keyScope)) {
String keyType = keyServiceType(sstKey);
if (!ret.contains(keyType)) {
ServiceType type = new ServiceType(keyType);
if (isWildCard) {
ret.addElement(type.toString());
} else {
String na = type.getNamingAuthority();
if (type.isNADefault() && isIANA) {
ret.addElement(type.toString());
} else if (namingAuthority.equals(na)) {
ret.addElement(type.toString());
}
}
}
}
}
return ret;
}
synchronized public Hashtable
findServices(String serviceType,
Vector scopes,
String query,
Locale locale)
throws ServiceLocationException {
String lang = locale.getLanguage();
Parser.ParserRecord ret = new Parser.ParserRecord();
Hashtable services = null;
Hashtable signatures = null;
int i, n = scopes.size();
int len = 0;
services = ret.services;
signatures = ret.signatures;
query = query.trim();
len = query.length();
int regStatus = languageSupported(serviceType, scopes, lang);
if (regStatus == NO_REGS_IN_LOCALE) {
throw
new ServiceLocationException(
ServiceLocationException.LANGUAGE_NOT_SUPPORTED,
"ssim_lang_unsup",
new Object[] {locale});
} else if (regStatus == REGS_IN_LOCALE) {
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
String sstKey =
makeScopeTypeLangKey(scope, serviceType, lang);
STLRecord regRecs =
(STLRecord)scopeTypeLangTable.get(sstKey);
if (regRecs == null) {
continue;
}
if (len <= 0) {
BtreeVector bvec = regRecs.attrSort;
ParserBVCollector collector =
new ParserBVCollector(scopes);
collector.prReturns = ret;
bvec.getAll(collector);
} else {
InMemoryEvaluator ev =
new InMemoryEvaluator(regRecs.attrValueSort,
regRecs.attrSort,
scopes);
Parser.parseAndEvaluateQuery(query, ev, locale, ret);
}
}
}
Hashtable ht = new Hashtable();
ht.put(ServiceStore.FS_SERVICES, services);
if (signatures.size() > 0) {
ht.put(ServiceStore.FS_SIGTABLE, signatures);
}
return ht;
}
synchronized public Hashtable
findAttributes(ServiceURL url,
Vector scopes,
Vector attrTags,
Locale locale)
throws ServiceLocationException {
Hashtable ht = new Hashtable();
Vector ret = new Vector();
String lang = locale.getLanguage();
Hashtable sig = null;
int regStatus =
languageSupported(url.getServiceType().toString(), scopes, lang);
if (regStatus == NO_REGS_IN_LOCALE) {
throw
new ServiceLocationException(
ServiceLocationException.LANGUAGE_NOT_SUPPORTED,
"ssim_lang_unsup",
new Object[] {locale});
} else if (regStatus == REGS_IN_LOCALE) {
attrTags = stringVectorToAttributePattern(attrTags, locale);
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(url.toString());
if (scopeLevel != null) {
int i, n = scopes.size();
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
Hashtable langLevel =
(Hashtable)scopeLevel.get(scope);
if (langLevel == null) {
continue;
}
Vector listVec = (Vector)langLevel.get(lang);
if (listVec == null) {
continue;
}
List elem = (List)listVec.elementAt(0);
ServiceRecordInMemory rec = elem.record;
findMatchingAttributes(rec, attrTags, ht, ret);
ht.clear();
ht.put(ServiceStore.FA_ATTRIBUTES, ret);
sig = rec.getAttrSignature();
if (sig != null) {
ht.put(ServiceStore.FA_SIG, sig);
}
break;
}
}
}
if (ht.size() <= 0) {
ht.put(ServiceStore.FA_ATTRIBUTES, ret);
}
return ht;
}
synchronized public Vector
findAttributes(String serviceType,
Vector scopes,
Vector attrTags,
Locale locale)
throws ServiceLocationException {
String lang = locale.getLanguage();
Vector ret = new Vector();
int regStatus = languageSupported(serviceType, scopes, lang);
if (regStatus == NO_REGS_IN_LOCALE) {
throw
new ServiceLocationException(
ServiceLocationException.LANGUAGE_NOT_SUPPORTED,
"ssim_lang_unsup",
new Object[] {locale});
} else if (regStatus == REGS_IN_LOCALE) {
attrTags = stringVectorToAttributePattern(attrTags, locale);
int len = attrTags.size();
BVCollector collector =
new AttributeBVCollector(attrTags, ret);
int i, n = scopes.size();
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
String sstKey =
makeScopeTypeLangKey(scope, serviceType, lang);
STLRecord regRecs = (STLRecord)scopeTypeLangTable.get(sstKey);
if (regRecs == null) {
continue;
}
BtreeVector bvec = regRecs.attrSort;
if (len <= 0) {
bvec.getAll(collector);
} else {
int j;
for (j = 0; j < len; j++) {
AttributePattern pat =
(AttributePattern)attrTags.elementAt(j);
bvec.matchEqual(pat, collector);
}
}
}
}
return ret;
}
synchronized public ServiceStore.ServiceRecord
getServiceRecord(ServiceURL URL, Locale locale) {
if (URL == null || locale == null) {
return null;
}
return findExistingRecord(URL,
null,
SLPConfig.localeToLangTag(locale));
}
synchronized public Enumeration getServiceRecordsByScope(Vector scopes) {
Vector records = new Vector();
BVCollector collector =
new ScopeBVCollector(records, scopes);
Enumeration keys = scopeTypeLangTable.keys();
while (keys.hasMoreElements()) {
String sstKey = (String)keys.nextElement();
STLRecord regRecs = (STLRecord)scopeTypeLangTable.get(sstKey);
BtreeVector bvec = regRecs.attrSort;
bvec.getAll(collector);
}
return records.elements();
}
synchronized public void dumpServiceStore() {
SLPConfig conf = SLPConfig.getSLPConfig();
conf.writeLogLine("ssim_dump_start",
new Object[] {this});
Enumeration keys = scopeTypeLangTable.keys();
while (keys.hasMoreElements()) {
String sstKey = (String)keys.nextElement();
STLRecord regRec = (STLRecord)scopeTypeLangTable.get(sstKey);
if (regRec.isAbstract) {
continue;
}
BtreeVector bvec = regRec.attrSort;
Vector vReturns = new Vector();
BVCollector collector = new AllBVCollector(vReturns);
bvec.getAll(collector);
int i, n = vReturns.size();
for (i = 0; i < n; i++) {
ServiceRecordInMemory rec =
(ServiceRecordInMemory)vReturns.elementAt(i);
writeRecordToLog(conf, rec);
}
}
conf.writeLog("ssim_dump_end",
new Object[] {this});
}
private void registerInternal(ServiceRecordInMemory rec) {
ServiceURL surl = rec.getServiceURL();
ServiceType type = surl.getServiceType();
String serviceType = type.toString();
String abstractTypeName = type.getAbstractTypeName();
Locale locale = rec.getLocale();
String lang = locale.getLanguage();
Vector scopes = rec.getScopes();
List ageOutElem = addToAgeOutQueue(rec);
int i, n = scopes.size();
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
Vector listVec =
initializeURLScopeLangTableVector(surl, scope, lang);
addRecordToScopeTypeLangTable(scope,
serviceType,
lang,
false,
rec,
listVec);
addTypeLocale(serviceType, scope, lang);
listVec.addElement(ageOutElem);
if (type.isAbstractType()) {
addRecordToScopeTypeLangTable(scope,
abstractTypeName,
lang,
true,
rec,
listVec);
addTypeLocale(abstractTypeName, scope, lang);
}
}
}
private Vector
initializeURLScopeLangTableVector(ServiceURL url,
String scope,
String lang) {
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(url.toString());
if (scopeLevel == null) {
scopeLevel = new Hashtable();
urlScopeLangTable.put(url.toString(), scopeLevel);
}
Hashtable langLevel =
(Hashtable)scopeLevel.get(scope);
if (langLevel == null) {
langLevel = new Hashtable();
scopeLevel.put(scope, langLevel);
}
Assert.slpassert(langLevel.get(lang) == null,
"ssim_url_lang_botch",
new Object[] {lang,
url,
scope});
Vector listVec = new Vector();
langLevel.put(lang, listVec);
return listVec;
}
private void
addRecordToScopeTypeLangTable(String scope,
String serviceType,
String lang,
boolean isAbstract,
ServiceRecordInMemory rec,
Vector listVec) {
String stlKey = makeScopeTypeLangKey(scope, serviceType, lang);
STLRecord trec = (STLRecord)scopeTypeLangTable.get(stlKey);
if (trec == null) {
trec = new STLRecord(isAbstract);
scopeTypeLangTable.put(stlKey, trec);
}
addRecordToAttrValueSort(trec.attrValueSort, rec, listVec);
addRecordToAttrSort(trec.attrSort, rec, listVec);
}
private void
addRecordToAttrValueSort(Hashtable table,
ServiceRecordInMemory rec,
Vector listVec) {
Vector attrList = rec.getAttrList();
int i, n = attrList.size();
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)attrList.elementAt(i);
AttributeString tag = attr.idPattern;
Vector values = attr.values;
Hashtable ttable = (Hashtable)table.get(tag);
if (ttable == null) {
ttable = makeAttrTypeTable();
table.put(tag, ttable);
}
String typeKey = null;
if (values == null) {
continue;
} else {
Object val = values.elementAt(0);
typeKey = val.getClass().getName();
}
BtreeVector bvec =
(BtreeVector)ttable.get(typeKey);
int j, m = values.size();
for (j = 0; j < m; j++) {
List elem = bvec.add(values.elementAt(j), rec);
listVec.addElement(elem);
}
}
}
private Hashtable makeAttrTypeTable() {
Hashtable ret = new Hashtable();
ret.put(INTEGER_TYPE, new BtreeVector());
ret.put(ATTRIBUTE_STRING_TYPE, new BtreeVector());
ret.put(BOOLEAN_TYPE, new BtreeVector());
ret.put(OPAQUE_TYPE, new BtreeVector());
return ret;
}
private void
addRecordToAttrSort(BtreeVector table,
ServiceRecordInMemory rec,
Vector listVec) {
Vector attrList = rec.getAttrList();
int i, n = attrList.size();
if (n <= 0) {
List elem =
table.add(new AttributeString("", rec.getLocale()), rec);
listVec.addElement(elem);
return;
}
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)attrList.elementAt(i);
List elem = table.add(attr.idPattern, rec);
listVec.addElement(elem);
}
}
private List addToAgeOutQueue(ServiceRecordInMemory rec) {
Long exTime = Long.valueOf(rec.getExpirationTime());
return ageOutQueue.add(exTime, rec);
}
private void
deregisterInternal(ServiceURL url, Vector scopes, String lang) {
ServiceType type = url.getServiceType();
Hashtable scopeLangTable =
(Hashtable)urlScopeLangTable.get(url.toString());
if (scopeLangTable == null) {
return;
}
int i, n = scopes.size();
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
Hashtable langTable = (Hashtable)scopeLangTable.get(scope);
if (langTable == null) {
continue;
}
if (lang != null) {
deregisterFromLocale(langTable, lang);
deleteTypeLocale(type.toString(), scope, lang);
if (type.isAbstractType()) {
deleteTypeLocale(type.getAbstractTypeName(), scope, lang);
}
} else {
Enumeration en = langTable.keys();
while (en.hasMoreElements()) {
lang = (String)en.nextElement();
deregisterFromLocale(langTable, lang);
deleteTypeLocale(type.toString(), scope, lang);
if (type.isAbstractType()) {
deleteTypeLocale(type.getAbstractTypeName(),
scope,
lang);
}
}
}
if (langTable.size() <= 0) {
scopeLangTable.remove(scope);
}
}
if (scopeLangTable.size() <= 0) {
urlScopeLangTable.remove(url.toString());
}
}
private void deregisterFromLocale(Hashtable langTable, String lang) {
Vector regList = (Vector)langTable.get(lang);
Assert.slpassert(regList != null,
"ssim_null_reg_vector",
new Object[] {lang});
int i, n = regList.size();
for (i = 0; i < n; i++) {
List elem = (List)regList.elementAt(i);
elem.delete();
}
langTable.remove(lang);
}
private ServiceRecordInMemory
findExistingRecord(ServiceURL surl, Vector scopes, String lang) {
ServiceRecordInMemory rec = null;
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(surl.toString());
if (scopeLevel != null) {
Enumeration en = null;
if (scopes == null) {
en = scopeLevel.keys();
} else {
en = scopes.elements();
}
while (en.hasMoreElements()) {
String scope = (String)en.nextElement();
Hashtable langLevel = (Hashtable)scopeLevel.get(scope);
if (langLevel == null) {
continue;
}
Vector listVec = null;
if (lang != null) {
listVec = (Vector)langLevel.get(lang);
} else {
Enumeration llen = langLevel.elements();
listVec = (Vector)llen.nextElement();
}
if (listVec == null) {
continue;
}
List elem = (List)listVec.elementAt(0);
rec = elem.record;
break;
}
}
return rec;
}
static void
findMatchingAttributes(ServiceRecordInMemory rec,
Vector attrTags,
Hashtable ht,
Vector ret)
throws ServiceLocationException {
int len = attrTags.size();
Vector attrList = rec.getAttrList();
int i, n = attrList.size();
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)attrList.elementAt(i);
if (len <= 0) {
saveValueIfMatch(attr, null, ht, ret);
} else {
int j;
for (j = 0; j < len; j++) {
AttributePattern attrTag =
(AttributePattern)attrTags.elementAt(j);
saveValueIfMatch(attr, attrTag, ht, ret);
}
}
}
}
static private void saveValueIfMatch(ServerAttribute attr,
AttributePattern attrTag,
Hashtable ht,
Vector ret)
throws ServiceLocationException {
AttributeString id = attr.idPattern;
if (attrTag == null || attrTag.match(id)) {
Vector values = attr.getValues();
if (values != null) {
values = (Vector)values.clone();
}
ServiceLocationAttribute nattr =
new ServiceLocationAttribute(attr.getId(), values);
ServiceLocationAttribute.mergeDuplicateAttributes(nattr,
ht,
ret,
true);
}
}
private void
checkScopeStatus(ServiceURL surl,
Vector scopes,
short errCode)
throws ServiceLocationException {
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(surl.toString());
if (scopeLevel == null) {
return;
}
int i, n = scopes.size();
boolean ok = true;
if (n != scopeLevel.size()) {
ok = false;
} else {
for (i = 0; i < n; i++) {
if (scopeLevel.get(scopes.elementAt(i)) == null) {
ok = false;
break;
}
}
}
if (!ok) {
throw
new ServiceLocationException(errCode,
"ssim_scope_mis",
new Object[0]);
}
}
private void checkForExistingUnderOtherServiceType(ServiceURL url,
Vector scopes)
throws ServiceLocationException {
Hashtable scopeLevel =
(Hashtable)urlScopeLangTable.get(url.toString());
if (scopeLevel == null) {
return;
}
Object scope = scopes.elementAt(0);
Hashtable localeLevel = (Hashtable)scopeLevel.get(scope);
Assert.slpassert(localeLevel != null,
"ssim_null_lang_table",
new Object[] {scope});
Enumeration en = localeLevel.elements();
Assert.slpassert(en.hasMoreElements(),
"ssim_empty_lang_table",
new Object[] {scope});
Vector vec = (Vector)en.nextElement();
Assert.slpassert(vec.size() > 0,
"ssim_empty_reg_vector",
new Object[] {scope});
List elem = (List)vec.elementAt(0);
ServiceURL recURL = elem.record.getServiceURL();
ServiceType recType = recURL.getServiceType();
if (!recType.equals(url.getServiceType())) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_UPDATE,
"ssim_st_already",
new Object[0]);
}
}
final private void mergeOldRecordIntoNew(ServiceRecordInMemory oldRec,
ServiceRecordInMemory newRec)
throws ServiceLocationException {
Vector newAttrs = newRec.getAttrList();
Vector oldAttrs = oldRec.getAttrList();
Hashtable ht = new Hashtable();
int i, n = newAttrs.size();
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)newAttrs.elementAt(i);
ht.put(attr.getId().toLowerCase(), attr);
}
n = oldAttrs.size();
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)oldAttrs.elementAt(i);
if (ht.get(attr.getId().toLowerCase()) == null) {
newAttrs.addElement(attr);
}
}
newRec.setAttrList(newAttrs);
Vector oldScopes = oldRec.getScopes();
Vector newScopes = newRec.getScopes();
int j, m = oldScopes.size();
for (j = 0; j < m; j++) {
String scope = (String)oldScopes.elementAt(j);
if (!newScopes.contains(scope)) {
newScopes.addElement(scope);
}
}
newRec.setScopes(newScopes);
}
private void deleteAttributes(ServiceRecordInMemory rec,
Vector attrTags)
throws ServiceLocationException {
Vector attrList = rec.getAttrList();
if (attrList.size() <= 0) {
return;
}
int i, n = attrList.size();
Vector newAttrList = new Vector();
int len = attrTags.size();
for (i = 0; i < n; i++) {
ServerAttribute attr =
(ServerAttribute)attrList.elementAt(i);
AttributeString id = attr.idPattern;
boolean deleteIt = false;
int j;
for (j = 0; j < len; j++) {
AttributePattern attrTag =
(AttributePattern)attrTags.elementAt(j);
if (attrTag.match(id)) {
deleteIt = true;
break;
}
}
if (!deleteIt) {
newAttrList.addElement(attr);
}
}
rec.setAttrList(newAttrList);
}
private Vector stringVectorToAttributePattern(Vector tags, Locale locale)
throws ServiceLocationException {
if (tags == null) {
return null;
}
Vector v = new Vector();
int i, n = tags.size();
for (i = 0; i < n; i++) {
String value = (String)tags.elementAt(i);
AttributePattern tag =
new AttributePattern(value, locale);
if (!v.contains(tag)) {
v.addElement(tag);
}
}
return v;
}
private void
writeRecordToLog(SLPConfig conf, ServiceStore.ServiceRecord rec) {
Locale locale = rec.getLocale();
ServiceURL surl = rec.getServiceURL();
Vector scopes = rec.getScopes();
Vector attributes = rec.getAttrList();
long exTime = rec.getExpirationTime();
Hashtable urlSig = rec.getURLSignature();
Hashtable attrSig = rec.getAttrSignature();
conf.writeLogLine("ssim_dump_entry_start", new Object[0]);
conf.writeLogLine("ssim_dump_entry",
new Object[] {
locale,
surl.toString(),
Integer.toString(surl.getLifetime()),
Long.toString(((exTime - System.currentTimeMillis())/1000)),
surl.getServiceType(),
scopes,
attributes});
if (urlSig != null) {
conf.writeLogLine("ssim_dump_urlsig",
new Object[] {urlSig});
}
if (attrSig != null) {
conf.writeLogLine("ssim_dump_attrsig",
new Object[] {
attrSig});
}
conf.writeLogLine("ssim_entry_end", new Object[0]);
}
private void
addTypeLocale(String type, String scope, String lang) {
String sstKey = makeScopeTypeKey(scope, type);
Hashtable langTable = (Hashtable)sstLocales.get(sstKey);
if (langTable == null) {
langTable = new Hashtable();
sstLocales.put(sstKey, langTable);
}
Integer numRegs = (Integer)langTable.get(lang);
if (numRegs == null) {
numRegs = Integer.valueOf(1);
} else {
numRegs = Integer.valueOf(numRegs.intValue() + 1);
}
langTable.put(lang, numRegs);
}
private void deleteTypeLocale(String type, String scope, String lang) {
String sstKey = makeScopeTypeKey(scope, type);
Hashtable langTable = (Hashtable)sstLocales.get(sstKey);
Assert.slpassert(langTable != null,
"ssim_ssttable_botch",
new Object[] {
type,
scope});
Integer numRegs = (Integer)langTable.get(lang);
Assert.slpassert(numRegs != null,
"ssim_ssttable_lang_botch",
new Object[] {
lang,
type,
scope});
numRegs = Integer.valueOf(numRegs.intValue() - 1);
if (numRegs.intValue() <= 0) {
langTable.remove(lang);
if (langTable.size() <= 0) {
sstLocales.remove(sstKey);
}
String stlKey =
makeScopeTypeLangKey(scope, type, lang);
scopeTypeLangTable.remove(stlKey);
} else {
langTable.put(lang, numRegs);
}
}
private int
languageSupported(String type, Vector scopes, String lang) {
boolean otherLangRegs = false;
boolean sameLangRegs = false;
int i, n = scopes.size();
for (i = 0; i < n; i++) {
String scope = (String)scopes.elementAt(i);
String sstKey = makeScopeTypeKey(scope, type);
Hashtable langTable = (Hashtable)sstLocales.get(sstKey);
if (langTable == null) {
continue;
}
Object numRegs = langTable.get(lang);
if (numRegs == null) {
otherLangRegs = true;
} else {
sameLangRegs = true;
}
}
if (otherLangRegs == false &&
sameLangRegs == false) {
return NO_REGS;
} else if (otherLangRegs == true &&
sameLangRegs == false) {
return NO_REGS_IN_LOCALE;
} else {
return REGS_IN_LOCALE;
}
}
private String makeScopeTypeKey(String scope, String type) {
return scope + "/" + type;
}
final private String
makeScopeTypeLangKey(String scope,
String serviceType,
String lang) {
return scope + "/" + serviceType + "/" + lang;
}
final private String keyScope(String key) {
int idx = key.indexOf('/');
String ret = "";
if (idx > 0) {
ret = key.substring(0, idx);
}
return ret;
}
final private String keyServiceType(String key) {
int idx = key.indexOf('/');
String ret = "";
int len = key.length();
if (idx >= 0 && idx < len - 1) {
ret = key.substring(idx+1, len);
}
idx = ret.indexOf('/');
ret = ret.substring(0, idx);
return ret;
}
final private boolean isAbstractTypeRecord(String sstKey) {
STLRecord rec = (STLRecord)scopeTypeLangTable.get(sstKey);
return rec.isAbstract;
}
}