001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.search.rdmserver;
007:
008: import com.sun.portal.search.rdm.*;
009: import com.sun.portal.search.util.*;
010: import com.sun.portal.search.soif.*;
011: import com.sun.portal.log.common.PortalLogger;
012:
013: import java.io.*;
014: import java.util.*;
015: import java.util.logging.Logger;
016: import java.util.logging.Level;
017:
018: /**
019: * Support for RDM-Query-Language=Schema-Basic
020: *
021: * NOTE: The resulting schema uses multivalued SOIF to the hilt.
022: * All numbering used to implemented the multivalued SOIF
023: * is valid only for that 1 result, and may be renumbered
024: * for another query.
025: *
026: * Scope = defined Attribute
027: *
028: * Example RDM messages
029: * --------------------
030: *
031: * To send the entire schema:
032: *
033: * @RDMHEADER { -
034: * RDM-Version{x}: 1.0
035: * RDM-Type{x}: schema-description-request
036: * RDM-Query-Language{x}: schema-basic
037: * }
038: *
039: * @RDMQUERY { -
040: * Scope{x}: defined SOIF-Attribute
041: * }
042: *
043: * To send the entire only those pieces in the default view:
044: *
045: * @RDMHEADER { -
046: * RDM-Version{x}: 1.0
047: * RDM-Type{x}: schema-description-request
048: * RDM-Query-Language{x}: schema-basic
049: * }
050: *
051: * @RDMQUERY { -
052: * Scope{x}: defined Default-View-Attribute
053: * }
054: *
055: * To send the entire only those pieces in the default view, and impose
056: * a view:
057: *
058: * @RDMHEADER { -
059: * RDM-Version{x}: 1.0
060: * RDM-Type{x}: schema-description-request
061: * RDM-Query-Language{x}: schema-basic
062: * }
063: *
064: * @RDMQUERY { -
065: * Scope{x}: defined Default-View-Attribute
066: * View-Attributes{x}: soif-attribute,default-view-attribute
067: * }
068: *
069: */
070: public class SchemaService extends RDMService {
071:
072: RDMSchema schema;
073:
074: public SchemaService() {
075: supportedServices.add(new RDMServiceDescriptor(RDM.RDM_SCH_REQ,
076: null));
077: supportedServices.add(new RDMServiceDescriptor(RDM.RDM_SCH_REQ,
078: "schema-basic"));
079: }
080:
081: class QLSchemaQuery {
082: String attr;
083: }
084:
085: /**
086: * RDM-QL=Schema-Basic Service Function
087: *
088: * Takes the incoming RDM Request message, and returns the RDMResponse.
089: */
090: public void service(RDMRequest req, RDMResponse res)
091: throws Exception {
092:
093: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0074");
094:
095: normalizeRequest(req);
096:
097: // Set outgoing response type
098: res.getHeader().setType(RDM.RDM_SCH_RES);
099:
100: String scope = req.getQuery().getScope();
101: QLSchemaQuery qry = new QLSchemaQuery();
102:
103: // Validate Scope specification
104: if (scope == null || scope.length() == 0
105: || !scopeParse(scope, qry)) {
106: SearchLogger.getLogger().log(Level.WARNING,
107: "PSSH_CSPSRDMS0075", scope);
108: res.getHeader().setErrorMessage("Invalid Scope");
109: return;
110: }
111:
112: // Send the results
113: getResults(req, res, qry);
114:
115: }
116:
117: public void normalizeRequest(RDMRequest req) {
118:
119: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0076");
120: RDMHeader hdr = req.getHeader();
121: String rdmtype = hdr.getType();
122: String ql, scope;
123:
124: // Set Default Query Language if needed
125: ql = hdr.getQueryLanguage();
126: if (ql == null || ql.length() == 0) // handle empty form vars
127: hdr.setQueryLanguage("schema-basic");
128: // Set Default Scope if needed
129: if (req.getQuery() == null)
130: req.setQuery(new RDMQuery((String) null));
131: scope = req.getQuery().getScope();
132: if (scope == null || scope.length() == 0)
133: req.getQuery().setScope("defined soif-attribute");
134:
135: }
136:
137: /**
138: * parsing "defined attr"
139: */
140: protected boolean scopeParse(String scope, QLSchemaQuery qry) {
141: qry.attr = null;
142: if (scope.regionMatches(true, 0, "defined", 0, 7)) {
143: int p = 7;
144: while (p < scope.length() && scope.charAt(p) == ' ')
145: p++; // skip space
146: if (p < scope.length()) {
147: qry.attr = scope.substring(7).trim().toLowerCase();
148: return true;
149: }
150: }
151: return false;
152: }
153:
154: protected synchronized void loadSchema(String csid)
155: throws Exception {
156: if (schema == null) {
157: String schfn;
158: if ((schfn = SearchConfig.getValue(SearchConfig.SCHEMA)) == null) {
159: //XXX strcpy(schfn, hook.serverroot);
160: //strcat(schfn, "/config/schema.rdm");
161: SearchLogger.getLogger().log(Level.WARNING,
162: "PSSH_CSPSRDMS0077", SearchConfig.SCHEMA);
163: throw new Exception("Missing schema configuration");
164: }
165:
166: // Load the schema from disk into object
167:
168: SOIFInputStream ss = null;
169: try {
170: ss = new SOIFInputStream(schfn);
171: } catch (Exception e) {
172: SearchLogger.getLogger().log(Level.WARNING,
173: "PSSH_CSPSRDMS0078", schfn);
174: throw new Exception("Schema Unavailable: " + schfn);
175: }
176:
177: try {
178: schema = new RDMSchema(ss.readSOIF());
179: } catch (Exception e) {
180: SearchLogger.getLogger().log(Level.WARNING,
181: "PSSH_CSPSRDMS0079", schfn);
182: throw new Exception("Schema Unavailable: " + schfn);
183: }
184: }
185: }
186:
187: protected void getResults(RDMRequest req, RDMResponse res,
188: QLSchemaQuery qry) throws Exception {
189:
190: if (schema == null)
191: loadSchema(req.getHeader().getCSID());
192:
193: SOIFOutputStream sos = res.getOutputStream();
194:
195: // Transmit the RDM Response Header
196: res.sendHeader();
197:
198: // Set View-Attributes if available
199: RDMView vp = new RDMView(req);
200: if (vp.attr != null) {
201: SearchLogger.getLogger().log(Level.FINE,
202: "PSSH_CSPSRDMS0080", vp.attr);
203: sos.setAllowed(vp.attr);
204: }
205:
206: // Restrict the Schema and send the results
207: printDefined(schema, qry, sos);
208:
209: req.logRDM("scope=\""
210: + Encoder.quotedEscape(req.getQuery().getScope())
211: + "\"");
212:
213: }
214:
215: protected boolean printDefined(RDMSchema schema, QLSchemaQuery qry,
216: SOIFOutputStream ss) throws Exception {
217: String defined = qry.attr, s;
218: int i = 0, max = 0, n = 0;
219: AVPair avp;
220:
221: if ((s = schema.getNumEntries()) != null)
222: max = Integer.parseInt(s);
223:
224: // NumEntries could be wrong...
225: if ((avp = schema.getSOIF().getAVPair(RDM.A_RDM_SOIF_ATTR)) != null)
226: if (max < avp.valueCount())
227: max = avp.valueCount();
228:
229: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0081",
230: new Integer(max));
231:
232: // Validate the number of entries
233: for (i = 0; (max == 0) || (i < max); i++)
234: if (schema.getSOIFAttribute(i) == null) {
235: max = i + 1;
236: break;
237: }
238: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0082",
239: new Integer(max));
240: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0083",
241: defined);
242:
243: // defined SOIF-Attribute is equivalent to the entire schema
244: if (defined.equalsIgnoreCase(RDM.A_RDM_SOIF_ATTR)) {
245: ss.write(schema.getSOIF());
246: return false;
247: }
248:
249: // See if anything is defined for the given attribute?
250: if ((avp = schema.getSOIF().getAVPair(defined)) == null) {
251: return true;
252: }
253:
254: for (n = i = 0; i < max; i++) {
255: if (!avp.nthValid(i))
256: schema.deleteColumn(i);
257: else
258: n++;
259: }
260: // XXX BROKEN! This is side-effecting the schema and returning wrong results!!
261: // DO NOT USE!!!
262:
263: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0084",
264: new Integer(n));
265: schema.setNumEntries("" + n);
266:
267: ss.write(schema.getSOIF());
268: return false;
269: }
270:
271: }
|