/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
// UARequester.java: Requester operations for UA.
// Author: James Kempf
// Created On: Thu Jan 8 15:17:35 1998
// Last Modified By: James Kempf
// Last Modified On: Mon Feb 22 13:47:06 1999
// Update Count: 78
//
package com.sun.slp;
import java.util.*;
/**
* The URequester class implements the Locator interface.
* It handles the request for the API. If any of the parameters
* are missing, they will be supplied with a default value if
* possible. If a cached value may be supplied, it will be.
* If no DA is present, and convergence is used to gather
* results, these will be merged into one result.
*
* @author Erik Guttman, James Kempf
*/
class UARequester extends Object implements Locator {
private static SLPConfig config = null;
private static DATable dat = null;
private Locale locale;
UARequester(Locale nlocale) {
Assert.nonNullParameter(nlocale, "locale");
if (config == null) {
config = SLPConfig.getSLPConfig();
}
if (dat == null) {
dat = DATable.getDATable();
}
locale = nlocale;
}
/**
* Return the Locator's locale object. All requests are made in
* this locale.
*
* @return The Locale object.
*/
public Locale getLocale() {
return locale;
}
/**
* Return an enumeration of known service types for this scope and naming
* authority. Unless a proprietary or experimental service is being
* discovered, the namingAuthority parameter should be the empty
* string, "".
*
* @param NA The naming authority, "" for default,
* '*' for any naming authority.
* @param scopes The SLP scopes of the types.
* @return ServiceLocationEnumeration of ServiceType objects for
* the service type names.
* @exception IllegalArgumentException If any of the parameters are
* null or syntactically incorrect.
* @exception ServiceLocationException An exception is thrown if the
* operation fails.
*/
public synchronized ServiceLocationEnumeration
findServiceTypes(String NA, Vector scopes)
throws ServiceLocationException {
Assert.nonNullParameter(NA, " NA");
Assert.nonNullParameter(scopes, "scopes");
// Formulate and send off messages.
Vector msgs = createMessages(SrvLocHeader.SrvTypeRqst,
NA,
null,
null,
scopes);
// Collate results.
Vector ret = new Vector();
int i, n = msgs.size();
int max = config.getMaximumResults();
for (i = 0; i < n; i++) {
CSrvTypeMsg msg = (CSrvTypeMsg)msgs.elementAt(i);
// Check for errors.
checkForError(msg, msgs);
Vector serviceTypes = msg.serviceTypes;
addUnique(serviceTypes, ret, max);
}
// Return.
return new ServiceLocationEnumerator(ret);
}
/**
* Return an enumeration of ServiceURL objects for services matching
* the query. The services are returned from the locale of the
* locator.
*
* @param type The type of the service (e.g. printer, etc.).
* @param scopes The SLP scopes of the service types.
* @param query A string with the SLP query.
* @return ServiceLocationEnumeration of ServiceURL objects for
* services matching the
* attributes.
* @exception ServiceLocationException An exception is returned if the
* operation fails.
* @see ServiceURL
*/
public synchronized ServiceLocationEnumeration
findServices(ServiceType type, Vector scopes, String query)
throws ServiceLocationException {
Assert.nonNullParameter(type, "type");
Assert.nonNullParameter(scopes, "scopes");
Assert.nonNullParameter(query, "query");
// Formulate and send off messages.
Vector msgs = createMessages(SrvLocHeader.SrvReq,
type,
query,
type,
scopes);
// Collate results.
Vector ret = new Vector();
int i, n = msgs.size();
int max = config.getMaximumResults();
for (i = 0; i < n; i++) {
SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
// Check for errors.
checkForError(msg, msgs);
// Be sure to account for DAAdverts and SAAdverts.
Vector serviceURLs = null;
if (msg instanceof CSrvMsg) {
serviceURLs = ((CSrvMsg)msg).serviceURLs;
} else if (msg instanceof CSAAdvert) {
serviceURLs = new Vector();
serviceURLs.addElement(((CSAAdvert)msg).URL);
} else if (msg instanceof CDAAdvert) {
serviceURLs = new Vector();
serviceURLs.addElement(((CDAAdvert)msg).URL);
}
addUnique(serviceURLs, ret, max);
}
// Return.
return new ServiceLocationEnumerator(ret);
}
/**
* Return the attributes for the service URL, using the locale
* of the locator.
*
* @param URL The service URL.
* @param scopes The SLP scopes of the service.
* @param attributeIds A vector of strings identifying the desired
* attributes. A null value means return all
* the attributes. <b>Partial id strings</b> may
* begin with '*' to match all ids which end with
* the given suffix, or end with '*' to match all
* ids which begin with a given prefix, or begin
* and end with '*' to do substring matching for
* ids containing the given partial id.
* @return ServiceLocationEnumeration of ServiceLocationAttribute
* objects matching the ids.
* @exception ServiceLocationException An exception is returned if the
* operation fails.
* @exception IllegalArgumentException If any of the parameters are
* null or syntactically incorrect.
* @see ServiceLocationAttribute
*
*/
public synchronized ServiceLocationEnumeration
findAttributes(ServiceURL URL, Vector scopes, Vector attributeIds)
throws ServiceLocationException {
Assert.nonNullParameter(URL, "URL");
Assert.nonNullParameter(scopes, "scopes");
Assert.nonNullParameter(attributeIds, "attributeIds");
Vector msgs = createMessages(SrvLocHeader.AttrRqst,
URL,
attributeIds,
URL.getServiceType(),
scopes);
// Check results.
Vector ret = new Vector();
int i, n = msgs.size();
int max = config.getMaximumResults();
// We only take the first message that came back and is OK.
for (i = 0; i < n; i++) {
SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
// Check for errors.
checkForError(msg, msgs);
// Select out attribute list.
if (msg instanceof CAttrMsg) {
ret = ((CAttrMsg)msg).attrList;
} else if (msg instanceof CSAAdvert) {
// Need to check that URL matches.
CSAAdvert smsg = (CSAAdvert)msg;
if (!URL.equals(smsg.URL)) {
continue;
}
ret = smsg.attrs;
} else if (msg instanceof CDAAdvert) {
// Need to check that URL matches.
CDAAdvert smsg = (CDAAdvert)msg;
if (!URL.equals(smsg.URL)) {
continue;
}
ret = smsg.attrs;
}
// Truncate, if return is larger than maximum.
if (ret.size() > max) {
ret.setSize(max);
}
// Break out, we only need one.
break;
}
// Return.
return new ServiceLocationEnumerator(ret);
}
/**
* Return all attributes for all service URL's having this
* service type in the locale of the Locator.
*
* @param type The service type.
* @param scopes The SLP scopes of the service type.
* @param attributeIds A vector of strings identifying the desired
* attributes. A null value means return all
* the attributes. <b>Partial id strings</b> may
* begin with '*' to match all ids which end with
* the given suffix, or end with '*' to match all
* ids which begin with a given prefix, or begin
* and end with '*' to do substring matching for
* ids containing the given partial id.
* @return ServiceLocationEnumeration of ServiceLocationAttribute
* objects matching the ids.
* @exception ServiceLocationException An exception is returned if the
* operation fails.
* @exception IllegalArgumentException If any of the parameters are
* null or syntactically incorrect.
* @see ServiceLocationAttribute
*
*/
public synchronized ServiceLocationEnumeration
findAttributes(ServiceType type, Vector scopes, Vector attributeIds)
throws ServiceLocationException {
Assert.nonNullParameter(type, "URL");
Assert.nonNullParameter(scopes, "scopes");
Assert.nonNullParameter(attributeIds, "attributeIds");
// Formulate and send off messages.
Vector msgs = createMessages(SrvLocHeader.AttrRqst,
type,
attributeIds,
type,
scopes);
// Collate results.
Vector ret = new Vector();
int i, n = msgs.size();
int max = config.getMaximumResults();
Hashtable ht = new Hashtable();
for (i = 0; i < n && ret.size() < max; i++) {
SrvLocMsg msg = (SrvLocMsg)msgs.elementAt(i);
// Check for errors.
checkForError(msg, msgs);
Vector attrList = null;
// Get the instance variable.
if (msg instanceof CAttrMsg) {
attrList = ((CAttrMsg)msg).attrList;
} else if (msg instanceof CSAAdvert) {
attrList = ((CSAAdvert)msg).attrs;
} else if (msg instanceof CDAAdvert) {
attrList = ((CDAAdvert)msg).attrs;
}
// Merge any duplicates.
int j, m = attrList.size();
for (j = 0; j < m; j++) {
ServiceLocationAttribute attr =
(ServiceLocationAttribute)attrList.elementAt(j);
ServiceLocationAttribute.mergeDuplicateAttributes(attr,
ht,
ret,
true);
if (ret.size() >= max) {
break;
}
}
}
// Return.
return new ServiceLocationEnumerator(ret);
}
// Execute the message request, returning messages.
private Vector
createMessages(int msgType,
Object t1,
Object t2,
ServiceType type,
Vector scopes)
throws ServiceLocationException {
// Validate, lower case scopes.
DATable.validateScopes(scopes, locale);
SrvLocMsg multiMsg = null;
SrvLocMsg uniMsg = null;
Vector daAddresses = null;
Vector multiCastScopes = null;
// Get the hashtable of unicast DA addresses and multicast scopes.
Hashtable daRecords = dat.findDAScopes(scopes);
// Get multicast scopes and DA addresses.
multiCastScopes =
(Vector)daRecords.get(DATable.MULTICAST_KEY);
daAddresses =
(Vector)daRecords.get(DATable.UNICAST_KEY);
// Special case for service request and attribute request
// if the user is looking for a special SLP type.
if (((msgType == SrvLocHeader.SrvReq) ||
(msgType == SrvLocHeader.AttrRqst)) &&
(type.equals(Defaults.DA_SERVICE_TYPE) ||
type.equals(Defaults.SA_SERVICE_TYPE))) {
multiCastScopes = scopes;
daAddresses = null;
// Get query. If an attribute request, then the user
// needs to sort out the attributes.
String query = "";
if (msgType == SrvLocHeader.SrvReq) {
query = (String)t2;
}
multiMsg = new CSrvMsg(locale, type, multiCastScopes, query);
} else {
// Handle a regular message.
// Multicast scopes are all scopes not supported by any DA.
if (multiCastScopes != null) {
switch (msgType) {
case SrvLocHeader.SrvTypeRqst:
multiMsg =
new CSrvTypeMsg(locale, (String)t1, multiCastScopes);
break;
case SrvLocHeader.SrvReq:
multiMsg =
new CSrvMsg(locale, type, multiCastScopes, (String)t2);
break;
case SrvLocHeader.AttrRqst:
if (t1 instanceof ServiceURL) {
multiMsg =
new CAttrMsg(locale,
(ServiceURL)t1,
multiCastScopes,
(Vector)t2);
} else {
multiMsg =
new CAttrMsg(locale,
type,
multiCastScopes,
(Vector)t2);
}
}
}
// Unicast only requires a single message because the DAs will
// ignore any scopes they do not support, just as long as
// they support one of them.
if (daAddresses != null) {
switch (msgType) {
case SrvLocHeader.SrvTypeRqst:
uniMsg =
new CSrvTypeMsg(locale, (String)t1, scopes);
break;
case SrvLocHeader.SrvReq:
uniMsg =
new CSrvMsg(locale, type, scopes, (String)t2);
break;
case SrvLocHeader.AttrRqst:
if (t1 instanceof ServiceURL) {
uniMsg =
new CAttrMsg(locale,
(ServiceURL)t1,
scopes,
(Vector)t2);
} else {
uniMsg =
new CAttrMsg(locale,
type,
scopes,
(Vector)t2);
}
}
}
}
// Send off messages, return results.
return Transact.transactUA(daAddresses,
uniMsg,
multiMsg,
config.getMulticastAddress());
}
// Check message for error code.
private static void
checkForError(SrvLocMsg msg, Vector v)
throws ServiceLocationException {
int err = msg.getErrorCode();
if (err != ServiceLocationException.OK) {
if (v.size() == 1) {
config.writeLog("single_exception",
new Object[] {
new Integer(err)});
throw
new ServiceLocationException((short)err,
"remote_error",
new Object[] {});
} else {
config.writeLog("multiple_exception",
new Object[] {
new Integer(err)});
}
}
}
// Process the incoming vector, adding any unique returns.
private static void addUnique(Vector incoming, Vector returns, int max) {
int i, n = incoming.size();
for (i = 0; i < n; i++) {
Object o = incoming.elementAt(i);
if (!returns.contains(o) && returns.size() < max) {
returns.addElement(o);
}
}
}
}