package com.sun.slp;
import java.util.*;
import java.io.*;
import java.security.*;
import java.net.*;
class ServiceTable extends Object {
static final String SDAADVERT = "com.sun.slp.SDAAdvert";
private static final String locationMsg = "Service table";
protected ServiceStore store = null;
static protected SLPConfig conf = null;
static protected ServiceTable table = null;
static protected AgerThread thrAger = null;
private static long sleepyTime = Defaults.lMaxSleepTime;
protected ServiceTable() {
if (thrAger != null) {
return;
}
thrAger = new AgerThread();
thrAger.setPriority(Thread.MIN_PRIORITY);
thrAger.start();
}
static ServiceTable getServiceTable()
throws ServiceLocationException {
if (conf == null) {
conf = SLPConfig.getSLPConfig();
}
if (table == null) {
table = createServiceTable();
}
return table;
}
private static ServiceTable createServiceTable()
throws ServiceLocationException {
ServiceTable table = new ServiceTable();
table.store = ServiceStoreFactory.createServiceStore();
return table;
}
public void deserializeTable() {
String serializedURL = conf.getSerializedRegURL();
if (serializedURL != null) {
ServiceStore serStore = getStoreFromURL(serializedURL);
if (serStore != null) {
registerStore(serStore);
}
}
}
void serializeServiceStore(String URL) {
try {
URL url = new URL(URL);
URLConnection urlConn = url.openConnection();
OutputStream os = urlConn.getOutputStream();
BufferedWriter di =
new BufferedWriter(new OutputStreamWriter(os));
ServiceStoreFactory.serialize(di, store);
} catch (MalformedURLException ex) {
conf.writeLog("st_serialized_malform",
new Object[] {URL});
} catch (UnsupportedEncodingException ex) {
conf.writeLog("st_unsupported_encoding",
new Object[] {URL});
} catch (IOException ex) {
conf.writeLog("st_serialized_ioexception",
new Object[] {URL, ex});
} catch (ServiceLocationException ex) {
conf.writeLog("st_serialized_sle",
new Object[] {URL, ex.getMessage()});
}
}
private ServiceStore getStoreFromURL(String serializedURL) {
ServiceStore serStore = null;
try {
URL url = new URL(serializedURL);
InputStream is = url.openStream();
BufferedReader di = new BufferedReader(new InputStreamReader(is));
serStore =
ServiceStoreFactory.deserializeServiceStore(di);
} catch (MalformedURLException ex) {
conf.writeLog("st_serialized_malform",
new Object[] {serializedURL});
} catch (UnsupportedEncodingException ex) {
conf.writeLog("st_unsupported_encoding",
new Object[] {serializedURL});
} catch (IOException ex) {
conf.writeLog("st_serialized_ioexception",
new Object[] {
serializedURL,
ex.getMessage()});
} catch (ServiceLocationException ex) {
conf.writeLog("st_serialized_sle",
new Object[] {
serializedURL,
ex.getMessage()});
}
return serStore;
}
private void registerStore(ServiceStore serStore) {
Enumeration en = serStore.getServiceRecordsByScope(null);
boolean hasURLSig = conf.getHasSecurity();
boolean hasAttrSig = conf.getHasSecurity();
PermSARegTable pregTable = SARequester.getPermSARegTable();
while (en.hasMoreElements()) {
ServiceStore.ServiceRecord rec =
(ServiceStore.ServiceRecord)en.nextElement();
ServiceURL surl = rec.getServiceURL();
Vector scopes = rec.getScopes();
Vector attrs = rec.getAttrList();
Locale locale = rec.getLocale();
Hashtable urlSig = null;
Hashtable attrSig = null;
try {
CSrvReg creg = new CSrvReg(false,
locale,
surl,
scopes,
attrs,
null,
null);
if (hasURLSig || hasAttrSig) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
creg.getHeader().externalize(baos, false, true);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
bais.read();
bais.read();
DataInputStream dis = new DataInputStream(bais);
SLPHeaderV2 hdr = new SLPHeaderV2();
hdr.parseHeader(SrvLocHeader.SrvReg, dis);
SSrvReg sreg = new SSrvReg(hdr, dis);
urlSig = sreg.URLSignature;
attrSig = sreg.attrSignature;
}
store.register(surl, attrs, scopes, locale, urlSig, attrSig);
if (surl.getIsPermanent()) {
pregTable.reg(surl, creg);
}
if (conf.regTest()) {
conf.writeLog("st_reg_add",
new Object[] {
locationMsg,
locale,
surl.getServiceType(),
surl,
attrs,
scopes});
}
} catch (ServiceLocationException ex) {
String msg = ex.getMessage();
conf.writeLog("st_serialized_seex",
new Object[] {
Integer.valueOf(ex.getErrorCode()),
surl,
(msg == null ? "<no message>":msg)});
} catch (Exception ex) {
String msg = ex.getMessage();
conf.writeLog("st_serialized_seex",
new Object[] {
surl,
(msg == null ? "<no message>":msg)});
}
}
}
private class AgerThread extends Thread {
public void run() {
setName("SLP Service Table Age-out");
long alarmTime = sleepyTime;
long wentToSleep = 0;
while (true) {
try {
wentToSleep = System.currentTimeMillis();
sleep(alarmTime);
} catch (InterruptedException ie) {
long remainingSleepTime =
(wentToSleep + alarmTime) - System.currentTimeMillis();
remainingSleepTime =
((remainingSleepTime <= 0) ? 0 : remainingSleepTime);
alarmTime = sleepyTime;
if (remainingSleepTime < alarmTime) {
alarmTime = remainingSleepTime;
}
continue;
}
if (table != null) {
table.ageStore();
alarmTime = sleepyTime;
}
}
}
}
void ageStore() {
try {
synchronized (store) {
Vector deleted = new Vector();
sleepyTime = store.ageOut(deleted);
int i, n = deleted.size();
for (i = 0; i < n; i++) {
ServiceStore.ServiceRecord rec =
(ServiceStore.ServiceRecord)deleted.elementAt(i);
ServiceURL surl = rec.getServiceURL();
trackRegisteredServiceTypes();
}
}
} catch (RuntimeException ex) {
reportNonfatalException(ex, new Vector(), store);
} catch (ServiceLocationException ex) {
reportNonfatalException(ex, new Vector(), store);
}
}
SrvLocMsg register(SSrvReg req) {
SrvLocHeader hdr = req.getHeader();
Locale locale = hdr.locale;
boolean fresh = hdr.fresh;
Vector scopes = hdr.scopes;
ServiceURL surl = req.URL;
String serviceType = req.serviceType;
Vector attrList = req.attrList;
Hashtable urlSig = req.URLSignature;
Hashtable attrSig = req.attrSignature;
short errorCode =
(fresh ? ServiceLocationException.INVALID_REGISTRATION :
ServiceLocationException.INVALID_UPDATE);
try {
if (urlSig != null) {
AuthBlock.verifyAll(urlSig);
}
if (attrSig != null) {
AuthBlock.verifyAll(attrSig);
}
if (surl.getLifetime() <= 0) {
throw
new ServiceLocationException(errorCode,
"st_zero",
new Object[0]);
}
checkForRestrictedType(surl.getServiceType());
if (attrSig != null && urlSig == null) {
throw
new ServiceLocationException(errorCode,
"st_attr_sig",
new Object[0]);
}
if (urlSig != null && !fresh) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_UPDATE,
"st_prot_update",
new Object[0]);
}
if (!areSupportedScopes(scopes)) {
throw
new ServiceLocationException(
ServiceLocationException.SCOPE_NOT_SUPPORTED,
"st_scope_unsup",
new Object[0]);
}
if (conf.getHasSecurity() && (urlSig == null || attrSig == null)) {
throw
new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"st_unprot_non_reg",
new Object[0]);
} else if (!conf.getHasSecurity() &&
(urlSig != null || attrSig != null)) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"st_prot_non_reg",
new Object[0]);
}
Vector attrs = new Vector();
Hashtable attrHash = new Hashtable();
int i, n = attrList.size();
for (i = 0; i < n; i++) {
ServiceLocationAttribute attr =
(ServiceLocationAttribute)attrList.elementAt(i);
ServiceLocationAttribute.mergeDuplicateAttributes(
attr,
attrHash,
attrs,
false);
}
boolean existing = false;
if (fresh) {
existing = store.register(surl,
attrs,
scopes,
locale,
urlSig,
attrSig);
trackRegisteredServiceTypes();
} else {
store.updateRegistration(surl, attrs, scopes, locale);
}
SrvLocMsg ack = req.makeReply(existing);
if (conf.regTest()) {
conf.writeLog((fresh ? "st_reg_add":"st_reg_update"),
new Object[] {
locationMsg,
locale,
serviceType,
surl,
attrs,
scopes});
}
if (conf.traceAll()) {
conf.writeLog("st_dump", new Object[] {locationMsg});
store.dumpServiceStore();
}
long sTime = getSleepIncrement(surl);
synchronized (store) {
if (sTime < sleepyTime) {
sleepyTime = sTime;
thrAger.interrupt();
}
}
return ack;
} catch (ServiceLocationException ex) {
if (conf.traceDrop()) {
conf.writeLog("st_reg_drop",
new Object[] {
locationMsg,
ex.getMessage()+"("+ex.getErrorCode()+")",
locale,
serviceType,
surl,
attrList,
scopes});
}
return hdr.makeErrorReply(ex);
} catch (RuntimeException ex) {
Vector args = new Vector();
args.addElement(req);
reportNonfatalException(ex, args, store);
return hdr.makeErrorReply(ex);
}
}
SrvLocMsg deregister(SSrvDereg req) {
SrvLocHeader hdr = req.getHeader();
Locale locale = hdr.locale;
Vector scopes = hdr.scopes;
ServiceURL surl = req.URL;
Hashtable urlSig = req.URLSignature;
Vector tags = req.tags;
short errorCode = ServiceLocationException.OK;
try {
if (urlSig != null) {
AuthBlock.verifyAll(urlSig);
}
checkForRestrictedType(surl.getServiceType());
if ((urlSig != null) && (tags != null)) {
throw
new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"st_prot_attr_dereg",
new Object[0]);
}
if (conf.getHasSecurity() && urlSig == null) {
throw
new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"st_unprot_non_dereg",
new Object[0]);
} else if (!conf.getHasSecurity() && urlSig != null) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"st_prot_non_dereg",
new Object[0]);
}
if (tags == null) {
store.deregister(surl, scopes, urlSig);
trackRegisteredServiceTypes();
} else {
store.deleteAttributes(surl, scopes, tags, locale);
}
SrvLocMsg ack = req.makeReply();
if (conf.regTest()) {
conf.writeLog((tags == null ? "st_dereg":"st_delattr"),
new Object[] {
locationMsg,
locale,
surl.getServiceType(),
surl,
tags});
}
if (conf.traceAll()) {
conf.writeLog("st_dump",
new Object[] {locationMsg});
store.dumpServiceStore();
}
return ack;
} catch (ServiceLocationException ex) {
if (conf.traceDrop()) {
conf.writeLog((tags == null ?
"st_dereg_drop" : "st_dereg_attr_drop"),
new Object[] {
locationMsg,
ex.getMessage()+"("+ex.getErrorCode()+")",
locale,
surl.getServiceType(),
surl,
tags});
}
return hdr.makeErrorReply(ex);
} catch (RuntimeException ex) {
Vector args = new Vector();
args.addElement(req);
reportNonfatalException(ex, args, store);
return hdr.makeErrorReply(ex);
}
}
SrvLocMsg findServiceTypes(SSrvTypeMsg req) {
SrvLocHeader hdr = req.getHeader();
Vector scopes = hdr.scopes;
String namingAuthority = req.namingAuthority;
short errorCode = ServiceLocationException.OK;
try {
if (!areSupportedScopes(scopes)) {
throw
new ServiceLocationException(
ServiceLocationException.SCOPE_NOT_SUPPORTED,
"st_scope_unsup",
new Object[0]);
}
Vector types = store.findServiceTypes(namingAuthority, scopes);
SrvLocMsg ack = req.makeReply(types);
if (conf.traceAll()) {
conf.writeLog("st_stypes",
new Object[] {
locationMsg,
namingAuthority,
scopes,
types});
}
return ack;
} catch (ServiceLocationException ex) {
if (conf.traceDrop()) {
conf.writeLog("st_stypes_drop",
new Object[] {
locationMsg,
ex.getMessage()+"("+ex.getErrorCode()+")",
namingAuthority,
scopes,
hdr.locale});
}
return hdr.makeErrorReply(ex);
} catch (RuntimeException ex) {
Vector args = new Vector();
args.addElement(req);
reportNonfatalException(ex, args, store);
return hdr.makeErrorReply(ex);
}
}
SrvLocMsg findServices(SSrvMsg req) {
SrvLocHeader hdr = req.getHeader();
Locale locale = hdr.locale;
Vector scopes = hdr.scopes;
String serviceType = req.serviceType;
String query = req.query;
short errorCode = ServiceLocationException.OK;
try {
if (!areSupportedScopes(scopes)) {
throw
new ServiceLocationException(
ServiceLocationException.SCOPE_NOT_SUPPORTED,
"st_scope_unsup",
new Object[0]);
}
Hashtable returns =
store.findServices(serviceType,
scopes,
query,
locale);
Hashtable services =
(Hashtable)returns.get(ServiceStore.FS_SERVICES);
Hashtable signatures =
(Hashtable)returns.get(ServiceStore.FS_SIGTABLE);
boolean hasSignatures = (signatures != null);
if (hasSignatures && !req.spi.equals("")) {
Enumeration allSurls = services.keys();
while (allSurls.hasMoreElements()) {
Object aSurl = allSurls.nextElement();
Hashtable auths = (Hashtable) signatures.get(aSurl);
AuthBlock auth =
AuthBlock.getEquivalentAuth(req.spi, auths);
if (auth == null) {
services.remove(aSurl);
}
}
}
SrvLocMsg ack = req.makeReply(services, signatures);
if (conf.traceAll()) {
conf.writeLog("st_sreq",
new Object[] {
locationMsg,
serviceType,
scopes,
query,
locale,
services,
signatures});
}
return ack;
} catch (ServiceLocationException ex) {
if (conf.traceDrop()) {
conf.writeLog("st_sreq_drop",
new Object[] {
locationMsg,
ex.getMessage()+"("+ex.getErrorCode()+")",
serviceType,
scopes,
query,
locale});
}
return hdr.makeErrorReply(ex);
} catch (RuntimeException ex) {
Vector args = new Vector();
args.addElement(req);
reportNonfatalException(ex, args, store);
return hdr.makeErrorReply(ex);
}
}
SrvLocMsg findAttributes(SAttrMsg req) {
SrvLocHeader hdr = req.getHeader();
Vector scopes = hdr.scopes;
Locale locale = hdr.locale;
ServiceURL surl = req.URL;
String serviceType = req.serviceType;
Vector tags = req.tags;
short errorCode = ServiceLocationException.OK;
try {
if (!areSupportedScopes(scopes)) {
throw
new ServiceLocationException(
ServiceLocationException.SCOPE_NOT_SUPPORTED,
"st_scope_unsup",
new Object[0]);
}
Vector attributes = null;
Hashtable sig = null;
if (serviceType == null) {
if (!req.spi.equals("") && tags.size() > 0) {
throw
new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"st_par_attr",
new Object[0]);
}
Hashtable ht =
store.findAttributes(surl, scopes, tags, locale);
attributes = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES);
sig = (Hashtable)ht.get(ServiceStore.FA_SIG);
if (sig != null && !req.spi.equals("")) {
AuthBlock auth = AuthBlock.getEquivalentAuth(req.spi, sig);
if (auth == null) {
attributes = new Vector();
}
}
} else {
if (!req.spi.equals("")) {
throw
new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_FAILED,
"st_par_attr",
new Object[0]);
}
attributes =
store.findAttributes(serviceType, scopes, tags, locale);
}
ServiceType type =
(serviceType == null ? surl.getServiceType():
new ServiceType(serviceType));
SrvLocMsg ack = req.makeReply(attributes, sig);
if (conf.traceAll()) {
conf.writeLog((serviceType != null ?
"st_st_attr" : "st_url_attr"),
new Object[] {
locationMsg,
(serviceType != null ? serviceType.toString() :
surl.toString()),
scopes,
tags,
locale,
attributes});
}
return ack;
} catch (ServiceLocationException ex) {
if (conf.traceDrop()) {
conf.writeLog((serviceType != null ? "st_st_attr_drop":
"st_url_attr_drop"),
new Object[] {
locationMsg,
ex.getMessage()+"("+ex.getErrorCode()+")",
(serviceType != null ? serviceType.toString() :
surl.toString()),
scopes,
tags,
locale});
}
return hdr.makeErrorReply(ex);
} catch (RuntimeException ex) {
Vector args = new Vector();
args.addElement(req);
reportNonfatalException(ex, args, store);
return hdr.makeErrorReply(ex);
}
}
ServiceStore.ServiceRecord getServiceRecord(ServiceURL URL,
Locale locale) {
return store.getServiceRecord(URL, locale);
}
private void checkForRestrictedType(ServiceType type)
throws ServiceLocationException {
if (Defaults.restrictedTypes.contains(type)) {
throw
new ServiceLocationException(
ServiceLocationException.INVALID_REGISTRATION,
"st_restricted_type",
new Object[] {type});
}
}
private void trackRegisteredServiceTypes()
throws ServiceLocationException {
Vector types = store.findServiceTypes(Defaults.ALL_AUTHORITIES,
conf.getSAConfiguredScopes());
Vector attrs = conf.getSAAttributes();
ServiceLocationAttribute attr =
new ServiceLocationAttribute(Defaults.SERVICE_TYPE_ATTR_ID,
types);
attrs.addElement(attr);
Vector interfaces = conf.getInterfaces();
int i, n = interfaces.size();
for (i = 0; i < n; i++) {
InetAddress addr = (InetAddress)interfaces.elementAt(i);
ServiceURL url =
new ServiceURL(Defaults.SUN_SA_SERVICE_TYPE + "://" +
addr.getHostAddress(),
ServiceURL.LIFETIME_MAXIMUM);
Vector scopes = conf.getSAOnlyScopes();
Locale locale = Defaults.locale;
store.register(url,
attrs,
scopes,
locale,
null,
null);
}
}
final private boolean areSupportedScopes(Vector scopes) {
Vector configuredScopes = conf.getSAConfiguredScopes();
Vector saOnlyScopes = conf.getSAOnlyScopes();
int i = 0;
while (i < scopes.size()) {
Object o = scopes.elementAt(i);
if (!configuredScopes.contains(o) && !saOnlyScopes.contains(o)) {
scopes.removeElementAt(i);
} else {
i++;
}
}
if (scopes.size() <= 0) {
return false;
}
return true;
}
private long getSleepIncrement(ServiceURL url) {
long urlLifetime = (long)(url.getLifetime() * 1000);
long increment =
(long)((float)urlLifetime * Defaults.fRefreshGranularity);
long sTime = urlLifetime - increment;
if (sTime <= 0) {
sTime = 500;
}
return sTime;
}
SrvLocMsg
makeDAAdvert(SSrvMsg rqst,
InetAddress daAddr,
SLPConfig conf) {
SrvLocHeader hdr = rqst.getHeader();
Vector scopes = hdr.scopes;
short xid = hdr.xid;
String query = rqst.query;
try {
if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_UNKNOWN,
"st_cant_sign_as",
new Object[] {rqst.spi});
}
Hashtable services =
ServerDATable.getServerDATable().returnMatchingDAs(query);
Enumeration urls = services.keys();
boolean foundIt = false;
String strDAAddr = daAddr.getHostAddress();
while (urls.hasMoreElements()) {
ServiceURL url = (ServiceURL)urls.nextElement();
if (url.getHost().equals(strDAAddr)) {
foundIt = true;
break;
}
}
if (!foundIt) {
return rqst.makeReply(new Hashtable(), new Hashtable());
}
return makeDAAdvert(hdr, daAddr, xid, scopes, conf);
} catch (ServiceLocationException ex) {
return hdr.makeErrorReply(ex);
}
}
SrvLocMsg
makeDAAdvert(SrvLocHeader hdr,
InetAddress daAddr,
short xid,
Vector scopes,
SLPConfig config)
throws ServiceLocationException {
if (hdr.version == 1) {
scopes = new Vector();
}
if (scopes.size() > 0 && !areSupportedScopes(scopes)) {
throw
new ServiceLocationException(
ServiceLocationException.SCOPE_NOT_SUPPORTED,
"st_scope_unsup",
new Object[0]);
}
long timestamp = store.getStateTimestamp();
ServiceURL url =
new ServiceURL(Defaults.DA_SERVICE_TYPE + "://" +
daAddr.getHostAddress(),
ServiceURL.LIFETIME_DEFAULT);
SDAAdvert advert =
hdr.getDAAdvert(xid,
timestamp,
url,
scopes,
conf.getDAAttributes());
return advert;
}
SSAAdvert
makeSAAdvert(SSrvMsg rqst,
InetAddress interfac,
SLPConfig conf)
throws ServiceLocationException {
SrvLocHeader hdr = rqst.getHeader();
int version = hdr.version;
short xid = hdr.xid;
Locale locale = hdr.locale;
Vector scopes = hdr.scopes;
String query = rqst.query;
String serviceType = rqst.serviceType;
Vector saOnlyScopes = conf.getSAOnlyScopes();
if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) {
throw new ServiceLocationException(
ServiceLocationException.AUTHENTICATION_UNKNOWN,
"st_cant_sign_as",
new Object[] {rqst.spi});
}
if (!areSupportedScopes(scopes) && !(scopes.size() <= 0)) {
return null;
}
if (scopes.size() <= 0) {
scopes = (Vector)conf.getSAConfiguredScopes().clone();
}
Hashtable returns =
store.findServices(Defaults.SUN_SA_SERVICE_TYPE.toString(),
saOnlyScopes,
query,
Defaults.locale);
Hashtable services =
(Hashtable)returns.get(ServiceStore.FS_SERVICES);
Enumeration en = services.keys();
if (!en.hasMoreElements()) {
return null;
}
ServiceURL url = null;
ServiceURL surl = null;
String addr = interfac.getHostAddress();
while (en.hasMoreElements()) {
surl = (ServiceURL)en.nextElement();
if (addr.equals(surl.getHost())) {
url = new ServiceURL(Defaults.SA_SERVICE_TYPE + "://" +
addr,
ServiceURL.LIFETIME_DEFAULT);
break;
}
}
if (url == null) {
return null;
}
Hashtable ht =
store.findAttributes(surl,
saOnlyScopes,
new Vector(),
Defaults.locale);
Vector attrs = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES);
return
new SSAAdvert(version,
xid,
locale,
url,
conf.getSAConfiguredScopes(),
attrs);
}
protected static void reportFatalException(Exception ex) {
reportException(true, ex, new Vector());
if (table != null) {
table.store.dumpServiceStore();
}
conf.writeLog("exiting_msg", new Object[0]);
System.exit(1);
}
protected static void reportNonfatalException(Exception ex,
Vector args,
ServiceStore store) {
reportException(false, ex, args);
if (conf.traceAll()) {
store.dumpServiceStore();
}
}
private static void
reportException(boolean isFatal, Exception ex, Vector args) {
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
ex.printStackTrace(writer);
String severity = (isFatal ? "fatal_error":"nonfatal_error");
String msg = ex.getMessage();
if (msg == null) {
msg = conf.formatMessage("no_message", new Object[0]);
} else if (ex instanceof ServiceLocationException) {
msg = msg +
"(" + ((ServiceLocationException)ex).getErrorCode() + ")";
}
StringBuffer argMsg = new StringBuffer();
int i, n = args.size();
for (i = 0; i < n; i++) {
argMsg.append("\n (" + Integer.toString(i) + "):" +
args.elementAt(i).toString());
}
conf.writeLog(severity,
new Object[] {
ex.getClass().getName(),
msg,
argMsg,
sw.toString()});
}
}