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

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