source: SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRURequestImpl.java @ 2867

Last change on this file since 2867 was 2867, checked in by oschonef, 11 years ago
  • save a few bytes of memory
  • Property svn:eol-style set to native
File size: 25.6 KB
Line 
1/**
2 * This software is copyright (c) 2011-2013 by
3 *  - Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
4 * This is free software. You can redistribute it
5 * and/or modify it under the terms described in
6 * the GNU General Public License v3 of which you
7 * should have received a copy. Otherwise you can download
8 * it from
9 *
10 *   http://www.gnu.org/licenses/gpl-3.0.txt
11 *
12 * @copyright Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
13 *
14 * @license http://www.gnu.org/licenses/gpl-3.0.txt
15 *  GNU General Public License v3
16 */
17package eu.clarin.sru.server;
18
19import java.io.IOException;
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.Enumeration;
23import java.util.List;
24
25import javax.servlet.http.HttpServletRequest;
26
27import org.z3950.zing.cql.CQLNode;
28import org.z3950.zing.cql.CQLParseException;
29import org.z3950.zing.cql.CQLParser;
30
31
32final class SRURequestImpl implements SRURequest, SRUDiagnosticList {
33    private static final String PARAM_OPERATION         = "operation";
34    private static final String PARAM_VERSION           = "version";
35    private static final String PARAM_RECORD_PACKING    = "recordPacking";
36    private static final String PARAM_STYLESHEET        = "stylesheet";
37    private static final String PARAM_QUERY             = "query";
38    private static final String PARAM_START_RECORD      = "startRecord";
39    private static final String PARAM_MAXIMUM_RECORDS   = "maximumRecords";
40    private static final String PARAM_RECORD_SCHEMA     = "recordSchema";
41    private static final String PARAM_RECORD_X_PATH     = "recordXPath";
42    private static final String PARAM_RESULT_SET_TTL    = "resultSetTTL";
43    private static final String PARAM_SORT_KEYS         = "sortKeys";
44    private static final String PARAM_SCAN_CLAUSE       = "scanClause";
45    private static final String PARAM_RESPONSE_POSITION = "responsePosition";
46    private static final String PARAM_MAXIMUM_TERMS     = "maximumTerms";
47    private static final String OP_EXPLAIN              = "explain";
48    private static final String OP_SCAN                 = "scan";
49    private static final String OP_SEARCH_RETRIEVE      = "searchRetrieve";
50    private static final String VERSION_1_1             = "1.1";
51    private static final String VERSION_1_2             = "1.2";
52    private static final String RECORD_PACKING_XML      = "xml";
53    private static final String RECORD_PACKING_STRING   = "string";
54    private static final String PARAM_EXTENSION_PREFIX  = "x-";
55    private static final String X_UNLIMITED_RESULTSET   = "x-unlimited-resultset";
56    private static final String X_UNLIMITED_TERMLIST    = "x-unlimited-termlist";
57    private static final String X_INDENT_RESPONSE       = "x-indent-response";
58    private static final int DEFAULT_START_RECORD       = 1;
59    private static final int DEFAULT_RESPONSE_POSITION  = 1;
60    private final SRUServerConfig config;
61    private final HttpServletRequest request;
62    private List<SRUDiagnostic> diagnostics;
63    private SRUOperation operation;
64    private SRUVersion version;
65    private SRURecordPacking recordPacking;
66    private CQLNode query;
67    private int startRecord = DEFAULT_START_RECORD;
68    private int maximumRecords = -1;
69    private String recordSchemaIdentifier;
70    private String stylesheet;
71    private String recordXPath;
72    private int resultSetTTL = -1;
73    private String sortKeys;
74    private CQLNode scanClause;
75    private int responsePosition = DEFAULT_RESPONSE_POSITION;
76    private int maximumTerms = -1;
77
78    private static enum Parameter {
79        RECORD_PACKING,
80        QUERY,
81        START_RECORD,
82        MAXIMUM_RECORDS,
83        RECORD_SCHEMA,
84        RECORD_XPATH,
85        RESULT_SET_TTL,
86        SORT_KEYS,
87        SCAN_CLAUSE,
88        RESPONSE_POSITION,
89        MAXIMUM_TERMS,
90        STYLESHEET
91    }
92
93    private static final class ParameterInfo {
94        private final Parameter parameter;
95        private final SRUVersion min;
96        private final SRUVersion max;
97        private final boolean mandatory;
98
99        private ParameterInfo(Parameter name, boolean mandatory,
100                SRUVersion min, SRUVersion max) {
101            this.parameter = name;
102            this.mandatory = mandatory;
103            this.min       = min;
104            this.max       = max;
105        }
106
107        public Parameter getParameter() {
108            return parameter;
109        }
110
111        public String getName() {
112            switch (parameter) {
113            case RECORD_PACKING:
114                return PARAM_RECORD_PACKING;
115            case QUERY:
116                return PARAM_QUERY;
117            case START_RECORD:
118                return PARAM_START_RECORD;
119            case MAXIMUM_RECORDS:
120                return PARAM_MAXIMUM_RECORDS;
121            case RECORD_SCHEMA:
122                return PARAM_RECORD_SCHEMA;
123            case RECORD_XPATH:
124                return PARAM_RECORD_X_PATH;
125            case RESULT_SET_TTL:
126                return PARAM_RESULT_SET_TTL;
127            case SORT_KEYS:
128                return PARAM_SORT_KEYS;
129            case SCAN_CLAUSE:
130                return PARAM_SCAN_CLAUSE;
131            case RESPONSE_POSITION:
132                return PARAM_RESPONSE_POSITION;
133            case MAXIMUM_TERMS:
134                return PARAM_MAXIMUM_TERMS;
135            case STYLESHEET:
136                return PARAM_STYLESHEET;
137            default:
138                throw new InternalError();
139            } // switch
140        }
141
142        public boolean getMandatory() {
143            return mandatory;
144        }
145
146        public boolean isForVersion(SRUVersion version) {
147            return (min.getVersionNumber() <= version.getVersionNumber()) &&
148                    (version.getVersionNumber() <= max.getVersionNumber());
149        }
150    } // class ParameterInfo
151
152    private static final ParameterInfo[] PARAMS_EXPLAIN = {
153        new ParameterInfo(Parameter.RECORD_PACKING, false,
154                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
155        new ParameterInfo(Parameter.STYLESHEET, false,
156                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2)
157    };
158    private static final ParameterInfo[] PARAMS_SCAN = {
159        new ParameterInfo(Parameter.SCAN_CLAUSE, true,
160                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
161        new ParameterInfo(Parameter.RESPONSE_POSITION, false,
162                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
163        new ParameterInfo(Parameter.MAXIMUM_TERMS, false,
164                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
165        new ParameterInfo(Parameter.STYLESHEET, false,
166                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2)
167
168    };
169    private static final ParameterInfo[] PARAMS_SEARCH_RETRIEVE = {
170        new ParameterInfo(Parameter.QUERY, true,
171                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
172        new ParameterInfo(Parameter.START_RECORD, false,
173                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
174        new ParameterInfo(Parameter.MAXIMUM_RECORDS, false,
175                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
176        new ParameterInfo(Parameter.RECORD_PACKING, false,
177                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
178        new ParameterInfo(Parameter.RECORD_SCHEMA, false,
179                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
180        new ParameterInfo(Parameter.RECORD_XPATH, false,
181                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_1),
182        new ParameterInfo(Parameter.RESULT_SET_TTL, false,
183                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2),
184        new ParameterInfo(Parameter.SORT_KEYS, false,
185                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_1),
186        new ParameterInfo(Parameter.STYLESHEET, false,
187                SRUVersion.VERSION_1_1, SRUVersion.VERSION_1_2)
188    };
189
190
191    SRURequestImpl(SRUServerConfig config, HttpServletRequest request) {
192        this.config        = config;
193        this.request       = request;
194    }
195
196
197    boolean checkParameters() {
198        // parse mandatory operation parameter
199        final String op = getParameter(PARAM_OPERATION, false);
200        if (op != null) {
201            if (!op.isEmpty()) {
202                if (op.equals(OP_EXPLAIN)) {
203                    this.operation = SRUOperation.EXPLAIN;
204                } else if (op.equals(OP_SCAN)) {
205                    this.operation = SRUOperation.SCAN;
206                } else if (op.equals(OP_SEARCH_RETRIEVE)) {
207                    this.operation = SRUOperation.SEARCH_RETRIEVE;
208                } else {
209                    addDiagnostic(SRUConstants.SRU_UNSUPPORTED_OPERATION, null,
210                            "Operation \"" + op + "\" is not supported.");
211                }
212            } else {
213                addDiagnostic(SRUConstants.SRU_UNSUPPORTED_OPERATION, null,
214                        "An empty parameter \"" + PARAM_OPERATION +
215                                "\" is not supported.");
216            }
217
218            // parse and check version
219            parseAndCheckVersionParameter();
220        } else {
221            /*
222             * absent parameter should be interpreted as "explain"
223             */
224            this.operation = SRUOperation.EXPLAIN;
225
226            // parse and check version
227            parseAndCheckVersionParameter();
228        }
229
230        if (diagnostics == null) {
231            // check mandatory/optional parameters for operation
232            ParameterInfo[] parameters;
233            switch (operation) {
234            case EXPLAIN:
235                parameters = PARAMS_EXPLAIN;
236                break;
237            case SCAN:
238                parameters = PARAMS_SCAN;
239                break;
240            case SEARCH_RETRIEVE:
241                parameters = PARAMS_SEARCH_RETRIEVE;
242                break;
243            default:
244                /* actually cannot happen */
245                addDiagnostic(SRUConstants.SRU_GENERAL_SYSTEM_ERROR, null,
246                        "internal error (invalid operation)");
247                return false;
248            }
249
250            /*
251             * keep list of all submitted parameters (except "operation" and
252             * "version"), so we can later warn if an unsupported parameter
253             * was sent (= not all parameters were consumed).
254             */
255            List<String> parameterNames = getParameterNames();
256
257            // check parameters ...
258            for (ParameterInfo parameter : parameters) {
259                String value = getParameter(parameter.getName(), true);
260                if (value != null) {
261                    // remove supported parameter from list
262                    parameterNames.remove(parameter.getName());
263
264                    /*
265                     * if parameter is not supported in this version, skip
266                     * it and create add an diagnostic.
267                     */
268                    if (!parameter.isForVersion(version)) {
269                        addDiagnostic(SRUConstants.SRU_UNSUPPORTED_PARAMETER,
270                                parameter.getName(),
271                                "Version " + version.getVersionString() +
272                                        " does not support parameter \"" +
273                                        parameter.getName() + "\".");
274                        continue;
275                    }
276
277                    // validate and parse parameters ...
278                    switch (parameter.getParameter()) {
279                    case RECORD_PACKING:
280                        if (value.endsWith(RECORD_PACKING_XML)) {
281                            recordPacking = SRURecordPacking.XML;
282                        } else if (value.equals(RECORD_PACKING_STRING)) {
283                            recordPacking = SRURecordPacking.STRING;
284                        } else {
285                            addDiagnostic(
286                                    SRUConstants.SRU_UNSUPPORTED_RECORD_PACKING,
287                                    null, "Record packing \"" + value +
288                                            "\" is not supported.");
289                        }
290                        break;
291                    case QUERY:
292                        query = parseCQLParameter(parameter.getName(), value);
293                        break;
294                    case START_RECORD:
295                        startRecord = parseNumberedParameter(
296                                parameter.getName(), value, 1);
297                        break;
298                    case MAXIMUM_RECORDS:
299                        maximumRecords = parseNumberedParameter(
300                                parameter.getName(), value, 0);
301                        break;
302                    case RECORD_SCHEMA:
303                        if (value != null) {
304                            /*
305                             * The parameter recordSchema may contain either
306                             * schema identifier or the short name. If
307                             * available, set to appropriate schema identifier
308                             * in the request object.
309                             */
310                            SRUServerConfig.SchemaInfo schemaInfo =
311                                    config.findSchemaInfo(value);
312                            if (schemaInfo != null) {
313                                recordSchemaIdentifier =
314                                        schemaInfo.getIdentifier();
315                            } else {
316                                /*
317                                 * SRU servers are supposed to raise a
318                                 * non-surrogate (fatal) diagnostic in case the
319                                 * record schema is not known to the server.
320                                 */
321                                addDiagnostic(
322                                        SRUConstants.SRU_UNKNOWN_SCHEMA_FOR_RETRIEVAL,
323                                        value, "Record schema \"" + value +
324                                        "\" is not supported  for retrieval.");
325                            }
326                        }
327                        break;
328                    case RECORD_XPATH:
329                        recordXPath = value;
330                        break;
331                    case RESULT_SET_TTL:
332                        resultSetTTL = parseNumberedParameter(
333                                parameter.getName(), value, 0);
334                        break;
335                    case SORT_KEYS:
336                        sortKeys = value;
337                        break;
338                    case SCAN_CLAUSE:
339                        scanClause = parseCQLParameter(
340                                parameter.getName(), value);
341                        break;
342                    case RESPONSE_POSITION:
343                        responsePosition = parseNumberedParameter(
344                                parameter.getName(), value, 0);
345                        break;
346                    case MAXIMUM_TERMS:
347                        maximumTerms = parseNumberedParameter(
348                                parameter.getName(), value, 0);
349                        break;
350                    case STYLESHEET:
351                        stylesheet = value;
352                        break;
353                    } // switch
354                } else {
355                    if (parameter.getMandatory()) {
356                        addDiagnostic(
357                                SRUConstants.SRU_MANDATORY_PARAMETER_NOT_SUPPLIED,
358                                parameter.getName(), "Mandatory parameter \"" +
359                                        parameter.getName() +
360                                        "\" was not supplied.");
361                    }
362                }
363            } // for
364
365            /*
366             *  check if any parameters where not consumed and
367             *  add appropriate warnings
368             */
369            if (!parameterNames.isEmpty()) {
370                for (String name : parameterNames) {
371                    // skip extraRequestData (aka extensions)
372                    if (!name.startsWith(PARAM_EXTENSION_PREFIX)) {
373                        addDiagnostic(SRUConstants.SRU_UNSUPPORTED_PARAMETER,
374                                name, "Parameter \"" + name + "\" is not " +
375                                        "supported for this operation.");
376                    }
377                }
378            }
379        }
380
381        // diagnostics != null -> consider as success
382        return (diagnostics == null);
383    }
384
385
386    List<SRUDiagnostic> getDiagnostics() {
387        return diagnostics;
388    }
389
390
391    SRUVersion getRawVersion() {
392        return version;
393    }
394
395
396    SRURecordPacking getRawRecordPacking() {
397        return recordPacking;
398    }
399
400
401    String getRawRecordSchemaIdentifier() {
402        return getRawParameter(PARAM_RECORD_SCHEMA);
403    }
404
405
406    String getRawQuery() {
407        return getRawParameter(PARAM_QUERY);
408    }
409
410
411    int getRawMaximumRecords() {
412        return maximumRecords;
413    }
414
415
416    String getRawScanClause() {
417        return getRawParameter(PARAM_SCAN_CLAUSE);
418    }
419
420
421    int getIndentResponse() {
422        if (config.allowOverrideIndentResponse()) {
423            String s = getExtraRequestData(X_INDENT_RESPONSE);
424            if (s != null) {
425                try {
426                    int x = Integer.parseInt(s);
427                    if ((x > -2) && (x < 9)) {
428                        return x;
429                    }
430                } catch (NumberFormatException e) {
431                    /* IGNORE */
432                }
433            }
434        }
435        return config.getIndentResponse();
436    }
437
438
439    @Override
440    public SRUOperation getOperation() {
441        return operation;
442    }
443
444
445    @Override
446    public SRUVersion getVersion() {
447        return (version != null) ? version : config.getDefaultVersion();
448    }
449
450
451    @Override
452    public boolean isVersion(SRUVersion version) {
453        if (version == null) {
454            throw new NullPointerException("version == null");
455        }
456        return getVersion().equals(version);
457    }
458
459
460    @Override
461    public boolean isVersion(SRUVersion min, SRUVersion max) {
462        if (min == null) {
463            throw new NullPointerException("min == null");
464        }
465        if (max == null) {
466            throw new NullPointerException("max == null");
467        }
468        if (min.getVersionNumber() > max.getVersionNumber()) {
469            throw new IllegalArgumentException("min > max");
470        }
471        final SRUVersion v = getVersion();
472        return (min.getVersionNumber() >= v.getVersionNumber()) &&
473                (v.getVersionNumber() <= max.getVersionNumber());
474    }
475
476
477    @Override
478    public SRURecordPacking getRecordPacking() {
479        return (recordPacking != null)
480                ? recordPacking
481                : config.getDeaultRecordPacking();
482    }
483
484
485    @Override
486    public CQLNode getQuery() {
487        return query;
488    }
489
490
491    @Override
492    public int getStartRecord() {
493        return startRecord;
494    }
495
496
497    @Override
498    public int getMaximumRecords() {
499        if (config.allowOverrideMaximumRecords() &&
500                (getExtraRequestData(X_UNLIMITED_RESULTSET) != null)) {
501            return -1;
502        }
503        if (maximumRecords == -1) {
504            return config.getNumberOfRecords();
505        } else {
506            if (maximumRecords > config.getMaximumRecords()) {
507                return config.getMaximumRecords();
508            } else {
509                return maximumRecords;
510            }
511        }
512    }
513
514
515    @Override
516    @Deprecated
517    public String getRecordSchemaName() {
518        return getRawRecordSchemaIdentifier();
519    }
520
521
522    @Override
523    public String getRecordSchemaIdentifier() {
524        return recordSchemaIdentifier;
525    }
526
527
528    @Override
529    public String getRecordXPath() {
530        return recordXPath;
531    }
532
533
534    @Override
535    public int getResultSetTTL() {
536        return resultSetTTL;
537    }
538
539
540    @Override
541    public String getSortKeys() {
542        return sortKeys;
543    }
544
545
546    @Override
547    public CQLNode getScanClause() {
548        return scanClause;
549    }
550
551
552    @Override
553    public int getResponsePosition() {
554        return responsePosition;
555    }
556
557
558    @Override
559    public int getMaximumTerms() {
560        if (config.allowOverrideMaximumTerms() &&
561                (getExtraRequestData(X_UNLIMITED_TERMLIST) != null)) {
562            return -1;
563        }
564        if (maximumTerms == -1) {
565            return config.getNumberOfTerms();
566        } else {
567            if (maximumTerms > config.getMaximumTerms()) {
568                return config.getMaximumTerms();
569            } else {
570                return maximumTerms;
571            }
572        }
573    }
574
575
576    @Override
577    public String getStylesheet() {
578        return stylesheet;
579    }
580
581
582    @Override
583    public String getProtocolScheme() {
584        return request.isSecure() ? "https://" : "http://";
585    }
586
587
588    @Override
589    public List<String> getExtraRequestDataNames() {
590        List<String> result = null;
591        for (Enumeration<?> i = request.getParameterNames(); i.hasMoreElements(); ) {
592            String name = (String) i.nextElement();
593            if (name.startsWith(PARAM_EXTENSION_PREFIX)) {
594                if (result == null) {
595                    result = new ArrayList<String>();
596                }
597                result.add(name);
598            }
599        }
600
601        if (result != null) {
602            return result;
603        } else {
604            return Collections.emptyList();
605        }
606    }
607
608
609    @Override
610    public String getExtraRequestData(String name) {
611        if (name == null) {
612            throw new NullPointerException("name == null");
613        }
614        if (!name.startsWith(PARAM_EXTENSION_PREFIX)) {
615            throw new IllegalArgumentException(
616                    "name must start with \"" + PARAM_EXTENSION_PREFIX + "\"");
617        }
618        return request.getParameter(name);
619    }
620
621
622    @Override
623    public HttpServletRequest getServletRequest() {
624        return request;
625    }
626
627
628    @Override
629    public void addDiagnostic(int code, String details, String message) {
630        if (diagnostics == null) {
631            diagnostics = new ArrayList<SRUDiagnostic>();
632        }
633        diagnostics.add(new SRUDiagnostic(code, details, message));
634    }
635
636
637    private List<String> getParameterNames() {
638        List<String> list = new ArrayList<String>();
639        for (Enumeration<?> i = request.getParameterNames();
640                i.hasMoreElements();) {
641            String name = (String) i.nextElement();
642            if (!(name.equals(PARAM_OPERATION) || name.equals(PARAM_VERSION))) {
643                list.add(name);
644            }
645        }
646        return list;
647    }
648
649
650    private String getParameter(String name, boolean nullify) {
651        String s = request.getParameter(name);
652        if (s != null) {
653            s = s.trim();
654            if (nullify && s.isEmpty()) {
655                addDiagnostic(SRUConstants.SRU_UNSUPPORTED_PARAMETER_VALUE,
656                        name, "An empty parameter \"" + PARAM_OPERATION +
657                                "\" is not supported.");
658                s = null;
659            }
660        }
661        return s;
662    }
663
664
665    private String getRawParameter(String name) {
666        String s = request.getParameter(name);
667        if (s != null) {
668            s = s.trim();
669            if (s.isEmpty()) {
670                s = null;
671            }
672        }
673        return s;
674    }
675
676
677    private void parseAndCheckVersionParameter() {
678        final String v = getParameter(PARAM_VERSION, true);
679        if (v != null) {
680            if (v.equals(VERSION_1_1)) {
681                this.version = SRUVersion.VERSION_1_1;
682            } else if (v.equals(VERSION_1_2)) {
683                this.version = SRUVersion.VERSION_1_2;
684            } else {
685                addDiagnostic(SRUConstants.SRU_UNSUPPORTED_VERSION,
686                        VERSION_1_2, "Version \"" + v +
687                                "\" is not supported");
688            }
689        } else {
690            /*
691             * except for "explain" operation, complain if "version"
692             * parameter was not supplied.
693             */
694            if (this.operation != SRUOperation.EXPLAIN) {
695                addDiagnostic(
696                        SRUConstants.SRU_MANDATORY_PARAMETER_NOT_SUPPLIED,
697                        PARAM_VERSION, "Mandatory parameter \"" +
698                                PARAM_VERSION + "\" was not supplied.");
699            }
700
701            /*
702             * this is an explain operation, assume default version
703             */
704            this.version = config.getDefaultVersion();
705        }
706    }
707
708
709    private int parseNumberedParameter(String param, String value,
710            int minValue) {
711        int result = -1;
712
713        if (value != null) {
714            try {
715                result = Integer.parseInt(value);
716                if (result < minValue) {
717                    addDiagnostic(SRUConstants.SRU_UNSUPPORTED_PARAMETER_VALUE,
718                            param, "Value is less than " + minValue + ".");
719                }
720            } catch (NumberFormatException e) {
721                addDiagnostic(SRUConstants.SRU_UNSUPPORTED_PARAMETER_VALUE,
722                        param, "Invalid number format.");
723            }
724        }
725        return result;
726    }
727
728
729    private CQLNode parseCQLParameter(String param, String value) {
730        CQLNode result = null;
731
732        /*
733         * XXX: maybe query length against limit and return
734         * "Too many characters in query" error?
735         */
736        try {
737            int compat = -1;
738            switch (version) {
739            case VERSION_1_1:
740                compat = CQLParser.V1POINT1;
741                break;
742            case VERSION_1_2:
743                compat = CQLParser.V1POINT2;
744            }
745            result = new CQLParser(compat).parse(value);
746        } catch (CQLParseException e) {
747            addDiagnostic(SRUConstants.SRU_QUERY_SYNTAX_ERROR,
748                    null, "error parsing query");
749        } catch (IOException e) {
750            addDiagnostic(SRUConstants.SRU_QUERY_SYNTAX_ERROR,
751                    null, "error parsing query");
752        }
753        return result;
754    }
755
756} // class SRURequestImpl
Note: See TracBrowser for help on using the repository browser.