Changeset 6779


Ignore:
Timestamp:
11/09/15 18:01:20 (9 years ago)
Author:
Oliver Schonefeld
Message:
  • prepare for SRU 2.0 (add basic version stuff)
Location:
SRUServer/trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • SRUServer/trunk/pom.xml

    r6110 r6779  
    1717        <maven.compiler.target>1.6</maven.compiler.target>
    1818        <!-- dependency versions -->
    19         <slf4j.version>1.6.4</slf4j.version>
     19        <slf4j.version>1.7.12</slf4j.version>
    2020    </properties>
    2121
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRURequestImpl.java

    r5924 r6779  
    2525import javax.servlet.http.HttpServletRequest;
    2626
     27import org.slf4j.Logger;
     28import org.slf4j.LoggerFactory;
    2729import org.z3950.zing.cql.CQLNode;
    2830import org.z3950.zing.cql.CQLParseException;
     
    3133
    3234final class SRURequestImpl implements SRURequest, SRUDiagnosticList {
     35    private static final Logger logger =
     36            LoggerFactory.getLogger(SRURequest.class);
    3337    private static final String PARAM_OPERATION         = "operation";
    3438    private static final String PARAM_VERSION           = "version";
     
    195199
    196200
     201    /**
     202     * Validate incoming request parameters.
     203     *
     204     * @return <code>true</code> if successful, <code>false</code> if something
     205     *         went wrong
     206     */
    197207    boolean checkParameters() {
    198         // parse mandatory operation parameter
    199         final String op = getParameter(PARAM_OPERATION, false, 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        /*
     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;
    208234                } else {
    209                     addDiagnostic(SRUConstants.SRU_UNSUPPORTED_OPERATION, null,
    210                             "Operation \"" + op + "\" is not supported.");
     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                    }
    211258                }
    212259            } 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         }
     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() {
    229311
    230312        if (diagnostics == null) {
     
    664746
    665747
    666     private void parseAndCheckVersionParameter() {
     748    private SRUVersion parseAndCheckVersionParameter(SRUOperation operation) {
    667749        final String v = getParameter(PARAM_VERSION, true, true);
    668750        if (v != null) {
     751            SRUVersion version = null;
    669752            if (v.equals(VERSION_1_1)) {
    670                 this.version = SRUVersion.VERSION_1_1;
     753                version = SRUVersion.VERSION_1_1;
    671754            } else if (v.equals(VERSION_1_2)) {
    672                 this.version = SRUVersion.VERSION_1_2;
     755                version = SRUVersion.VERSION_1_2;
    673756            } else {
    674757                addDiagnostic(SRUConstants.SRU_UNSUPPORTED_VERSION,
     
    676759                                "\" is not supported");
    677760            }
     761            return version;
    678762        } else {
    679763            /*
     
    681765             * parameter was not supplied.
    682766             */
    683             if (this.operation != SRUOperation.EXPLAIN) {
     767            if (operation != SRUOperation.EXPLAIN) {
    684768                addDiagnostic(
    685769                        SRUConstants.SRU_MANDATORY_PARAMETER_NOT_SUPPLIED,
     
    691775             * this is an explain operation, assume default version
    692776             */
    693             this.version = config.getDefaultVersion();
     777            return config.getDefaultVersion();
    694778        }
    695779    }
     
    730814                break;
    731815            case VERSION_1_2:
     816                /* FALL-THROUGH */
     817            case VERSION_2_0:
    732818                compat = CQLParser.V1POINT2;
    733819            }
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUServer.java

    r5924 r6779  
    5151 */
    5252public final class SRUServer {
    53     private static final String SRU_NS =
    54             "http://www.loc.gov/zing/srw/";
    55     private static final String SRU_PREFIX = "sru";
    56     private static final String SRU_DIAGNOSIC_NS =
    57             "http://www.loc.gov/zing/srw/diagnostic/";
    58     private static final String SRU_DIAGNOSTIC_PREFIX = "diag";
    5953    private static final String SRU_DIAGNOSTIC_RECORD_SCHEMA =
    6054            "info:srw/schema/1/diagnostics-v1.1";
    61     private static final String SRU_EXPLAIN_NS =
    62             "http://explain.z3950.org/dtd/2.0/";
    63     private static final String SRU_EXPLAIN_PREFIX = "zr";
    64     private static final String SRU_XCQL_NS =
    65             "http://www.loc.gov/zing/cql/xcql/";
    6655    static final String RESPONSE_ENCODING = "utf-8";
    6756    private static final String RESPONSE_CONTENT_TYPE = "application/xml";
     
    136125                                SRURecordPacking.XML, false,
    137126                                req.getIndentResponse());
    138                     writeFatalError(out, req, req.getDiagnostics());
     127                    final SRUNamespaces ns = getNamespaces(req.getVersion());
     128                    writeFatalError(out, ns, req, req.getDiagnostics());
    139129                }
    140130            } catch (XMLStreamException e) {
     
    176166                                    SRURecordPacking.XML, false,
    177167                                    req.getIndentResponse());
    178                     writeFatalError(out, req, diagnostics);
     168                    final SRUNamespaces ns = getNamespaces(req.getVersion());
     169                    writeFatalError(out, ns, req, diagnostics);
    179170                } catch (Exception ex) {
    180171                    logger.error("An exception occurred while in error state",
     
    205196
    206197        try {
     198            final SRUNamespaces ns = getNamespaces(request.getVersion());
     199
    207200            // send results
    208201            SRUXMLStreamWriter out =
     
    212205                                          request.getIndentResponse());
    213206
    214             beginResponse(out, request);
     207            beginResponse(out, ns, request);
    215208
    216209            // write the explain record
    217             writeExplainRecord(out, request);
     210            writeExplainRecord(out, ns, request);
    218211
    219212            if (config.getEchoRequests()) {
    220                 writeEchoedExplainRequest(out, request);
     213                writeEchoedExplainRequest(out, ns, request);
    221214            }
    222215
    223216            // diagnostics
    224             writeDiagnosticList(out, request.getDiagnostics());
     217            writeDiagnosticList(out, ns, request.getDiagnostics());
    225218
    226219            // extraResponseData
    227220            if (result != null) {
    228221                if (result.hasExtraResponseData()) {
    229                     out.writeStartElement(SRU_NS, "extraResponseData");
     222                    out.writeStartElement(ns.getResponseNS(), "extraResponseData");
    230223                    result.writeExtraResponseData(out);
    231224                    out.writeEndElement(); // "extraResponseData" element
     
    256249
    257250        try {
     251            final SRUNamespaces ns = getNamespaces(request.getVersion());
     252
     253            /*
     254             * FIXME: re-check, if while scan response needs to be put
     255             * in scan namespace for SRU 2.0!
     256             */
    258257            // send results
    259258            SRUXMLStreamWriter out =
     
    263262                                          request.getIndentResponse());
    264263
    265             beginResponse(out, request);
     264            beginResponse(out, ns, request);
    266265
    267266            try {
     
    274273                while (result.nextTerm()) {
    275274                    if (!wroteTerms) {
    276                         out.writeStartElement(SRU_NS, "terms");
     275                        final boolean needNsDecl =
     276                                !ns.getResponseNS().equals(ns.getScanNS());
     277                        if (needNsDecl) {
     278                            out.setPrefix(ns.getScanPrefix(), ns.getScanNS());
     279                        }
     280                        out.writeStartElement(ns.getScanNS(), "terms");
     281                        if (needNsDecl) {
     282                            out.writeNamespace(ns.getScanPrefix(),
     283                                    ns.getScanNS());
     284                        }
    277285                        wroteTerms = true;
    278286                    }
    279                     out.writeStartElement(SRU_NS, "term");
    280 
    281                     out.writeStartElement(SRU_NS, "value");
     287                    out.writeStartElement(ns.getScanNS(), "term");
     288
     289                    out.writeStartElement(ns.getScanNS(), "value");
    282290                    out.writeCharacters(result.getValue());
    283291                    out.writeEndElement(); // "value" element
    284292
    285293                    if (result.getNumberOfRecords() > -1) {
    286                         out.writeStartElement(SRU_NS, "numberOfRecords");
     294                        out.writeStartElement(ns.getScanNS(), "numberOfRecords");
    287295                        out.writeCharacters(
    288296                                Integer.toString(result.getNumberOfRecords()));
     
    291299
    292300                    if (result.getDisplayTerm() != null) {
    293                         out.writeStartElement(SRU_NS, "displayTerm");
     301                        out.writeStartElement(ns.getScanNS(), "displayTerm");
    294302                        out.writeCharacters(result.getDisplayTerm());
    295303                        out.writeEndElement(); // "displayTerm" element
     
    297305
    298306                    if (result.getWhereInList() != null) {
    299                         out.writeStartElement(SRU_NS, "whereInList");
     307                        out.writeStartElement(ns.getScanNS(), "whereInList");
    300308                        switch (result.getWhereInList()) {
    301309                        case FIRST:
     
    316324
    317325                    if (result.hasExtraTermData()) {
    318                         out.writeStartElement(SRU_NS, "extraTermData");
     326                        out.writeStartElement(ns.getScanNS(), "extraTermData");
    319327                        result.writeExtraTermData(out);
    320328                        out.writeEndElement(); // "extraTermData" element
     
    334342            // echoedScanRequest
    335343            if (config.getEchoRequests()) {
    336                 writeEchoedScanRequest(out, request, request.getScanClause());
     344                writeEchoedScanRequest(out, ns, request, request.getScanClause());
    337345            }
    338346
    339347            // diagnostics
    340             writeDiagnosticList(out, request.getDiagnostics());
     348            writeDiagnosticList(out, ns, request.getDiagnostics());
    341349
    342350            // extraResponseData
    343351            if (result.hasExtraResponseData()) {
    344                 out.writeStartElement(SRU_NS, "extraResponseData");
     352                out.writeStartElement(ns.getResponseNS(), "extraResponseData");
    345353                result.writeExtraResponseData(out);
    346354                out.writeEndElement(); // "extraResponseData" element
     
    381389
    382390        try {
     391            final SRUNamespaces ns = getNamespaces(request.getVersion());
     392
    383393            // send results
    384394            SRUXMLStreamWriter out =
     
    388398                                          request.getIndentResponse());
    389399
    390             beginResponse(out, request);
     400            beginResponse(out, ns, request);
    391401
    392402            // numberOfRecords
    393             out.writeStartElement(SRU_NS, "numberOfRecords");
     403            out.writeStartElement(ns.getResponseNS(), "numberOfRecords");
    394404            out.writeCharacters(
    395405                    Integer.toString(result.getTotalRecordCount()));
     
    398408            // resultSetId
    399409            if (result.getResultSetId() != null) {
    400                 out.writeStartElement(SRU_NS, "resultSetId");
     410                out.writeStartElement(ns.getResponseNS(), "resultSetId");
    401411                out.writeCharacters(result.getResultSetId());
    402412                out.writeEndElement(); // "resultSetId" element
     
    405415            // resultSetIdleTime
    406416            if (result.getResultSetIdleTime() > 0) {
    407                 out.writeStartElement(SRU_NS, "resultSetIdleTime");
     417                out.writeStartElement(ns.getResponseNS(), "resultSetIdleTime");
    408418                out.writeCharacters(Integer.toString(result
    409419                        .getResultSetIdleTime()));
     
    419429                        : -1;
    420430                try {
    421                     out.writeStartElement(SRU_NS, "records");
     431                    out.writeStartElement(ns.getResponseNS(), "records");
    422432                    while (result.nextRecord()) {
    423433                        /*
     
    435445                        }
    436446
    437                         out.writeStartElement(SRU_NS, "record");
     447                        out.writeStartElement(ns.getResponseNS(), "record");
    438448
    439449                        /*
     
    445455                                result.getSurrogateDiagnostic();
    446456
    447                         out.writeStartElement(SRU_NS, "recordSchema");
     457                        out.writeStartElement(ns.getResponseNS(), "recordSchema");
    448458                        if (diagnostic == null) {
    449459                            out.writeCharacters(
     
    455465
    456466                        // recordPacking
    457                         writeRecordPacking(out, request.getRecordPacking());
     467                        writeRecordPacking(out, ns, request.getRecordPacking());
    458468
    459469                        /*
    460470                         * Output either record data or surrogate diagnostic ...
    461471                         */
    462                         out.writeStartElement(SRU_NS, "recordData");
     472                        out.writeStartElement(ns.getResponseNS(), "recordData");
    463473                        out.startRecord();
    464474                        if (diagnostic == null) {
     
    466476                        } else {
    467477                            // write a surrogate diagnostic
    468                             writeDiagnostic(out, diagnostic, true);
     478                            writeDiagnostic(out, ns, diagnostic, true);
    469479                        }
    470480                        out.endRecord();
     
    478488                                    result.getRecordIdentifier();
    479489                            if (identifier != null) {
    480                                 out.writeStartElement(SRU_NS,
     490                                out.writeStartElement(ns.getResponseNS(),
    481491                                                      "recordIdentifier");
    482492                                out.writeCharacters(identifier);
     
    485495                        }
    486496
    487                         out.writeStartElement(SRU_NS, "recordPosition");
     497                        out.writeStartElement(ns.getResponseNS(),
     498                                "recordPosition");
    488499                        out.writeCharacters(Integer.toString(position));
    489500                        out.writeEndElement(); // "recordPosition" element
    490501
    491502                        if (result.hasExtraRecordData()) {
    492                             out.writeStartElement(SRU_NS, "extraRecordData");
     503                            out.writeStartElement(ns.getResponseNS(),
     504                                    "extraRecordData");
    493505                            result.writeExtraRecordData(out);
    494506                            out.writeEndElement(); // "extraRecordData"
     
    510522            // nextRecordPosition
    511523            if (position <= result.getTotalRecordCount()) {
    512                 out.writeStartElement(SRU_NS, "nextRecordPosition");
     524                out.writeStartElement(ns.getResponseNS(), "nextRecordPosition");
    513525                out.writeCharacters(Integer.toString(position));
    514526                out.writeEndElement();
     
    517529            // echoedSearchRetrieveRequest
    518530            if (config.getEchoRequests()) {
    519                 writeEchoedSearchRetrieveRequest(out, request,
     531                writeEchoedSearchRetrieveRequest(out, ns, request,
    520532                                                 request.getQuery());
    521533            }
    522534
    523535            // diagnostics
    524             writeDiagnosticList(out, request.getDiagnostics());
     536            writeDiagnosticList(out, ns, request.getDiagnostics());
    525537
    526538            // extraResponseData
    527539            if (result.hasExtraResponseData()) {
    528                 out.writeStartElement(SRU_NS, "extraResponseData");
     540                out.writeStartElement(ns.getResponseNS(), "extraResponseData");
    529541                result.writeExtraResponseData(out);
    530542                out.writeEndElement(); // "extraResponseData" element
     
    538550
    539551
    540     private void beginResponse(SRUXMLStreamWriter out, SRUOperation operation,
    541             SRUVersion version, String stylesheet) throws XMLStreamException {
     552    private void beginResponse(SRUXMLStreamWriter out, SRUNamespaces ns,
     553            SRUOperation operation, SRUVersion version, String stylesheet)
     554            throws XMLStreamException {
    542555        out.writeStartDocument("utf-8", "1.0");
    543556
     
    552565        }
    553566
    554         out.setPrefix(SRU_PREFIX, SRU_NS);
     567        out.setPrefix(ns.getResponsePrefix(), ns.getResponseNS());
    555568        switch (operation) {
    556569        case EXPLAIN:
    557             out.writeStartElement(SRU_NS, "explainResponse");
     570            out.writeStartElement(ns.getResponseNS(), "explainResponse");
    558571            break;
    559572        case SCAN:
    560             out.writeStartElement(SRU_NS, "scanResponse");
     573            out.writeStartElement(ns.getResponseNS(), "scanResponse");
    561574            break;
    562575        case SEARCH_RETRIEVE:
    563             out.writeStartElement(SRU_NS, "searchRetrieveResponse");
     576            out.writeStartElement(ns.getResponseNS(), "searchRetrieveResponse");
    564577            break;
    565578        }
    566         out.writeNamespace(SRU_PREFIX, SRU_NS);
     579        out.writeNamespace(ns.getResponsePrefix(), ns.getResponseNS());
    567580
    568581        // version
    569         writeVersion(out, version);
    570     }
    571 
    572 
    573     private void beginResponse(SRUXMLStreamWriter out, SRURequest request)
    574             throws XMLStreamException {
    575         beginResponse(out, request.getOperation(), request.getVersion(),
     582        writeVersion(out, ns, version);
     583    }
     584
     585
     586    private void beginResponse(SRUXMLStreamWriter out, SRUNamespaces ns,
     587            SRURequest request) throws XMLStreamException {
     588        beginResponse(out, ns, request.getOperation(), request.getVersion(),
    576589                request.getStylesheet());
    577590    }
     
    592605
    593606
    594     private void writeFatalError(SRUXMLStreamWriter out,
     607    private void writeFatalError(SRUXMLStreamWriter out, SRUNamespaces ns,
    595608            SRURequestImpl request, List<SRUDiagnostic> diagnotics)
    596609            throws XMLStreamException {
     
    609622         * write a response which conforms to the schema
    610623         */
    611         beginResponse(out, operation, version, null);
     624        beginResponse(out, ns, operation, version, null);
    612625        switch (operation) {
    613626        case EXPLAIN:
    614627            // 'explain' requires a complete explain record ...
    615             writeExplainRecord(out, request);
     628            writeExplainRecord(out, ns, request);
    616629            break;
    617630        case SCAN:
     
    620633        case SEARCH_RETRIEVE:
    621634            // 'searchRetrieve' needs numberOfRecords ..
    622             out.writeStartElement(SRU_NS, "numberOfRecords");
     635            out.writeStartElement(ns.getResponseNS(), "numberOfRecords");
    623636            out.writeCharacters("0");
    624637            out.writeEndElement(); // "numberOfRecords" element
    625638            break;
    626639        }
    627         writeDiagnosticList(out, diagnotics);
     640        writeDiagnosticList(out, ns, diagnotics);
    628641        endResponse(out);
    629642    }
    630643
    631644
    632     private void writeDiagnosticList(SRUXMLStreamWriter out,
     645    private void writeDiagnosticList(SRUXMLStreamWriter out, SRUNamespaces ns,
    633646            List<SRUDiagnostic> diagnostics) throws XMLStreamException {
    634647        if ((diagnostics != null) && !diagnostics.isEmpty()) {
    635             out.setPrefix(SRU_DIAGNOSTIC_PREFIX, SRU_DIAGNOSIC_NS);
    636             out.writeStartElement(SRU_NS, "diagnostics");
    637             out.writeNamespace(SRU_DIAGNOSTIC_PREFIX, SRU_DIAGNOSIC_NS);
     648            out.setPrefix(ns.getDiagnosticPrefix(), ns.getDiagnosticNS());
     649            out.writeStartElement(ns.getDiagnosticNS(), "diagnostics");
     650            out.writeNamespace(ns.getDiagnosticPrefix(), ns.getDiagnosticNS());
    638651            for (SRUDiagnostic diagnostic : diagnostics) {
    639                 writeDiagnostic(out, diagnostic, false);
     652                writeDiagnostic(out, ns, diagnostic, false);
    640653            }
    641654            out.writeEndElement(); // "diagnostics" element
     
    644657
    645658
    646     private void writeExplainRecord(SRUXMLStreamWriter out,
     659    private void writeExplainRecord(SRUXMLStreamWriter out, SRUNamespaces ns,
    647660            SRURequestImpl request) throws XMLStreamException {
    648         out.writeStartElement(SRU_NS, "record");
    649 
    650         out.writeStartElement(SRU_NS, "recordSchema");
    651         out.writeCharacters(SRU_EXPLAIN_NS);
     661        out.writeStartElement(ns.getResponseNS(), "record");
     662
     663        out.writeStartElement(ns.getResponseNS(), "recordSchema");
     664        out.writeCharacters(ns.getExplainNS());
    652665        out.writeEndElement(); // "recordSchema" element
    653666
    654667        // recordPacking
    655         writeRecordPacking(out, request.getRecordPacking());
    656 
    657         out.writeStartElement(SRU_NS, "recordData");
     668        writeRecordPacking(out, ns, request.getRecordPacking());
     669
     670        out.writeStartElement(ns.getResponseNS(), "recordData");
    658671
    659672        out.startRecord();
    660673
    661674        // explain ...
    662         out.setPrefix(SRU_EXPLAIN_PREFIX, SRU_EXPLAIN_NS);
    663         out.writeStartElement(SRU_EXPLAIN_NS, "explain");
    664         out.writeNamespace(SRU_EXPLAIN_PREFIX, SRU_EXPLAIN_NS);
     675        out.setPrefix(ns.getExplainPrefix(), ns.getExplainNS());
     676        out.writeStartElement(ns.getExplainNS(), "explain");
     677        out.writeNamespace(ns.getExplainPrefix(), ns.getExplainNS());
    665678
    666679        // explain/serverInfo
    667         out.writeStartElement(SRU_EXPLAIN_NS, "serverInfo");
     680        out.writeStartElement(ns.getExplainNS(), "serverInfo");
    668681        out.writeAttribute("protocol", "SRU");
    669682        switch (config.getDefaultVersion()) {
     
    673686        case VERSION_1_2:
    674687            out.writeAttribute("version", "1.2");
     688            break;
     689        case VERSION_2_0:
     690            out.writeAttribute("version", "2.0");
     691            break;
    675692        } // switch
    676693        out.writeAttribute("transport", config.getTransports());
    677         out.writeStartElement(SRU_EXPLAIN_NS, "host");
     694        out.writeStartElement(ns.getExplainNS(), "host");
    678695        out.writeCharacters(config.getHost());
    679696        out.writeEndElement(); // "host" element
    680         out.writeStartElement(SRU_EXPLAIN_NS, "port");
     697        out.writeStartElement(ns.getExplainNS(), "port");
    681698        out.writeCharacters(Integer.toString(config.getPort()));
    682699        out.writeEndElement(); // "port" element
    683         out.writeStartElement(SRU_EXPLAIN_NS, "database");
     700        out.writeStartElement(ns.getExplainNS(), "database");
    684701        out.writeCharacters(config.getDatabase());
    685702        out.writeEndElement(); // "database" element
     
    689706        final DatabaseInfo dbinfo = config.getDatabaseInfo();
    690707        if (dbinfo != null) {
    691             out.writeStartElement(SRU_EXPLAIN_NS, "databaseInfo");
    692             writeLocalizedStrings(out, "title", dbinfo.getTitle());
    693             writeLocalizedStrings(out, "description", dbinfo.getDescription());
    694             writeLocalizedStrings(out, "author", dbinfo.getAuthor());
    695             writeLocalizedStrings(out, "extent", dbinfo.getExtend());
    696             writeLocalizedStrings(out, "history", dbinfo.getHistory());
    697             writeLocalizedStrings(out, "langUsage", dbinfo.getLangUsage());
    698             writeLocalizedStrings(out, "restrictions", dbinfo.getRestrictions());
    699             writeLocalizedStrings(out, "subjects", dbinfo.getSubjects());
    700             writeLocalizedStrings(out, "links", dbinfo.getLinks());
    701             writeLocalizedStrings(out, "implementation",
     708            out.writeStartElement(ns.getExplainNS(), "databaseInfo");
     709            writeLocalizedStrings(out, ns, "title",
     710                    dbinfo.getTitle());
     711            writeLocalizedStrings(out, ns, "description",
     712                    dbinfo.getDescription());
     713            writeLocalizedStrings(out, ns, "author",
     714                    dbinfo.getAuthor());
     715            writeLocalizedStrings(out, ns, "extent",
     716                    dbinfo.getExtend());
     717            writeLocalizedStrings(out, ns, "history",
     718                    dbinfo.getHistory());
     719            writeLocalizedStrings(out, ns, "langUsage",
     720                    dbinfo.getLangUsage());
     721            writeLocalizedStrings(out, ns, "restrictions",
     722                    dbinfo.getRestrictions());
     723            writeLocalizedStrings(out, ns, "subjects",
     724                    dbinfo.getSubjects());
     725            writeLocalizedStrings(out, ns, "links",
     726                    dbinfo.getLinks());
     727            writeLocalizedStrings(out, ns, "implementation",
    702728                    dbinfo.getImplementation());
    703729            out.writeEndElement(); // "databaseInfo" element
     
    707733        final IndexInfo indexInfo = config.getIndexInfo();
    708734        if (indexInfo != null) {
    709             out.writeStartElement(SRU_EXPLAIN_NS, "indexInfo");
     735            out.writeStartElement(ns.getExplainNS(), "indexInfo");
    710736
    711737            List<IndexInfo.Set> sets = indexInfo.getSets();
    712738            if (sets != null) {
    713739                for (IndexInfo.Set set : sets) {
    714                     out.writeStartElement(SRU_EXPLAIN_NS, "set");
     740                    out.writeStartElement(ns.getExplainNS(), "set");
    715741                    out.writeAttribute("identifier", set.getIdentifier());
    716742                    out.writeAttribute("name", set.getName());
    717                     writeLocalizedStrings(out, "title", set.getTitle());
     743                    writeLocalizedStrings(out, ns, "title", set.getTitle());
    718744                    out.writeEndElement(); // "set" element
    719745                }
     
    723749            if (indexes != null) {
    724750                for (IndexInfo.Index index : indexes) {
    725                     out.writeStartElement(SRU_EXPLAIN_NS, "index");
     751                    out.writeStartElement(ns.getExplainNS(), "index");
    726752                    out.writeAttribute("search",
    727753                            index.canSearch() ? "true" : "false");
     
    730756                    out.writeAttribute("sort",
    731757                            index.canSort() ? "true" : "false");
    732                     writeLocalizedStrings(out, "title", index.getTitle());
     758                    writeLocalizedStrings(out, ns, "title", index.getTitle());
    733759                    List<IndexInfo.Index.Map> maps = index.getMaps();
    734760                    if (maps != null) {
    735761                        for (IndexInfo.Index.Map map : maps) {
    736                             out.writeStartElement(SRU_EXPLAIN_NS, "map");
     762                            out.writeStartElement(ns.getExplainNS(), "map");
    737763                            if (map.isPrimary()) {
    738764                                out.writeAttribute("primary", "true");
    739765                            }
    740                             out.writeStartElement(SRU_EXPLAIN_NS, "name");
     766                            out.writeStartElement(ns.getExplainNS(), "name");
    741767                            out.writeAttribute("set", map.getSet());
    742768                            out.writeCharacters(map.getName());
     
    755781                config.getSchemaInfo();
    756782        if (schemaInfo != null) {
    757             out.writeStartElement(SRU_EXPLAIN_NS, "schemaInfo");
     783            out.writeStartElement(ns.getExplainNS(), "schemaInfo");
    758784            for (SRUServerConfig.SchemaInfo schema : schemaInfo) {
    759                 out.writeStartElement(SRU_EXPLAIN_NS, "schema");
     785                out.writeStartElement(ns.getExplainNS(), "schema");
    760786                out.writeAttribute("identifier", schema.getIdentifier());
    761787                out.writeAttribute("name", schema.getName());
     
    772798                    out.writeAttribute("retrieve", "false");
    773799                }
    774                 writeLocalizedStrings(out, "title", schema.getTitle());
     800                writeLocalizedStrings(out, ns, "title", schema.getTitle());
    775801                out.writeEndElement(); // "schema" element
    776802            }
     
    779805
    780806        // explain/configInfo
    781         out.writeStartElement(SRU_EXPLAIN_NS, "configInfo");
     807        out.writeStartElement(ns.getExplainNS(), "configInfo");
    782808        // numberOfRecords (default)
    783         out.writeStartElement(SRU_EXPLAIN_NS, "default");
     809        out.writeStartElement(ns.getExplainNS(), "default");
    784810        out.writeAttribute("type", "numberOfRecords");
    785811        out.writeCharacters(Integer.toString(config.getNumberOfRecords()));
     
    787813
    788814        // maximumRecords (setting)
    789         out.writeStartElement(SRU_EXPLAIN_NS, "setting");
     815        out.writeStartElement(ns.getExplainNS(), "setting");
    790816        out.writeAttribute("type", "maximumRecords");
    791817        out.writeCharacters(Integer.toString(config.getMaximumRecords()));
     
    803829
    804830
    805     private void writeDiagnostic(SRUXMLStreamWriter out,
     831    private void writeDiagnostic(SRUXMLStreamWriter out, SRUNamespaces ns,
    806832            SRUDiagnostic diagnostic, boolean writeNsDecl)
    807833            throws XMLStreamException {
    808834        if (writeNsDecl) {
    809             out.setPrefix(SRU_DIAGNOSTIC_PREFIX, SRU_DIAGNOSIC_NS);
    810         }
    811         out.writeStartElement(SRU_DIAGNOSIC_NS, "diagnostic");
     835            out.setPrefix(ns.getDiagnosticPrefix(), ns.getDiagnosticNS());
     836        }
     837        out.writeStartElement(ns.getDiagnosticNS(), "diagnostic");
    812838        if (writeNsDecl) {
    813             out.writeNamespace(SRU_DIAGNOSTIC_PREFIX, SRU_DIAGNOSIC_NS);
    814         }
    815         out.writeStartElement(SRU_DIAGNOSIC_NS, "uri");
     839            out.writeNamespace(ns.getDiagnosticPrefix(), ns.getDiagnosticNS());
     840        }
     841        out.writeStartElement(ns.getDiagnosticNS(), "uri");
    816842        out.writeCharacters(diagnostic.getURI());
    817843        out.writeEndElement(); // "uri" element
    818844        if (diagnostic.getDetails() != null) {
    819             out.writeStartElement(SRU_DIAGNOSIC_NS, "details");
     845            out.writeStartElement(ns.getDiagnosticNS(), "details");
    820846            out.writeCharacters(diagnostic.getDetails());
    821847            out.writeEndElement(); // "details" element
    822848        }
    823849        if (diagnostic.getMessage() != null) {
    824             out.writeStartElement(SRU_DIAGNOSIC_NS, "message");
     850            out.writeStartElement(ns.getDiagnosticNS(), "message");
    825851            out.writeCharacters(diagnostic.getMessage());
    826852            out.writeEndElement(); // "message" element
     
    831857
    832858    private void writeEchoedExplainRequest(SRUXMLStreamWriter out,
    833             SRURequestImpl request) throws XMLStreamException,
    834             SRUException {
     859            SRUNamespaces ns, SRURequestImpl request)
     860            throws XMLStreamException, SRUException {
    835861        // echoedSearchRetrieveRequest
    836         out.writeStartElement(SRU_NS, "echoedExplainRequest");
     862        out.writeStartElement(ns.getResponseNS(), "echoedExplainRequest");
    837863
    838864        // echoedExplainRequest/version
    839865        if (request.getRawVersion() != null) {
    840             writeVersion(out, request.getRawVersion());
     866            writeVersion(out, ns, request.getRawVersion());
    841867        }
    842868
    843869        // echoedExplainRequest/recordPacking
    844870        if (request.getRawRecordPacking() != null) {
    845             writeRecordPacking(out, request.getRawRecordPacking());
     871            writeRecordPacking(out, ns, request.getRawRecordPacking());
    846872        }
    847873
    848874        // echoedExplainRequest/stylesheet
    849875        if (request.getStylesheet() != null) {
    850             out.writeStartElement(SRU_NS, "stylesheet");
     876            out.writeStartElement(ns.getResponseNS(), "stylesheet");
    851877            out.writeCharacters(request.getStylesheet());
    852878            out.writeEndElement(); // "stylesheet" element
     
    855881        // echoedExplainRequest/baseUrl (SRU 1.2 only)
    856882        if (request.isVersion(SRUVersion.VERSION_1_2)) {
    857             writeBaseUrl(out, request);
     883            writeBaseUrl(out, ns, request);
    858884        }
    859885
     
    863889
    864890    private void writeEchoedScanRequest(SRUXMLStreamWriter out,
    865             SRURequestImpl request, CQLNode cql) throws XMLStreamException,
    866             SRUException {
     891            SRUNamespaces ns, SRURequestImpl request, CQLNode cql)
     892            throws XMLStreamException, SRUException {
    867893        // echoedScanRequest
    868         out.writeStartElement(SRU_NS, "echoedScanRequest");
     894        out.writeStartElement(ns.getResponseNS(), "echoedScanRequest");
    869895
    870896        // echoedScanRequest/version
    871897        if (request.getRawVersion() != null) {
    872             writeVersion(out, request.getRawVersion());
     898            writeVersion(out, ns, request.getRawVersion());
    873899        }
    874900
    875901        // echoedScanRequest/scanClause
    876         out.writeStartElement(SRU_NS, "scanClause");
     902        out.writeStartElement(ns.getResponseNS(), "scanClause");
    877903        out.writeCharacters(request.getRawScanClause());
    878904        out.writeEndElement(); // "query"
    879905
    880906        // echoedScanRequest/xScanClause
    881         out.setDefaultNamespace(SRU_XCQL_NS);
    882         out.writeStartElement(SRU_NS, "xScanClause");
    883         out.writeDefaultNamespace(SRU_XCQL_NS);
     907        out.setDefaultNamespace(ns.getXcqlNS());
     908        out.writeStartElement(ns.getResponseNS(), "xScanClause");
     909        out.writeDefaultNamespace(ns.getXcqlNS());
    884910        out.writeXCQL(cql, false);
    885911        out.writeEndElement(); // "xScanClause" element
     
    887913        // echoedScanRequest/responsePosition
    888914        if (request.getResponsePosition() != -1) {
    889             out.writeStartElement(SRU_NS, "responsePosition");
     915            out.writeStartElement(ns.getResponseNS(), "responsePosition");
    890916            out.writeCharacters(
    891917                    Integer.toString(request.getResponsePosition()));
     
    895921        // echoedScanRequest/maximumTerms
    896922        if (request.getMaximumTerms() != -1) {
    897             out.writeStartElement(SRU_NS, "maximumTerms");
     923            out.writeStartElement(ns.getResponseNS(), "maximumTerms");
    898924            out.writeCharacters(Integer.toString(request.getMaximumTerms()));
    899925            out.writeEndElement(); // "maximumTerms" element
     
    902928        // echoedScanRequest/stylesheet
    903929        if (request.getStylesheet() != null) {
    904             out.writeStartElement(SRU_NS, "stylesheet");
     930            out.writeStartElement(ns.getResponseNS(), "stylesheet");
    905931            out.writeCharacters(request.getStylesheet());
    906932            out.writeEndElement(); // "stylesheet" element
     
    909935        // echoedScanRequest/baseUrl (SRU 1.2 only)
    910936        if (request.isVersion(SRUVersion.VERSION_1_2)) {
    911             writeBaseUrl(out, request);
     937            writeBaseUrl(out, ns, request);
    912938        }
    913939
     
    917943
    918944    private void writeEchoedSearchRetrieveRequest(SRUXMLStreamWriter out,
    919             SRURequestImpl request, CQLNode cql) throws XMLStreamException,
    920             SRUException {
     945            SRUNamespaces ns, SRURequestImpl request, CQLNode cql)
     946            throws XMLStreamException, SRUException {
    921947        // echoedSearchRetrieveRequest
    922         out.writeStartElement(SRU_NS, "echoedSearchRetrieveRequest");
     948        out.writeStartElement(ns.getResponseNS(),
     949                "echoedSearchRetrieveRequest");
    923950
    924951        // echoedSearchRetrieveRequest/version
    925952        if (request.getRawVersion() != null) {
    926             writeVersion(out, request.getRawVersion());
     953            writeVersion(out, ns, request.getRawVersion());
    927954        }
    928955
    929956        // echoedSearchRetrieveRequest/query
    930         out.writeStartElement(SRU_NS, "query");
     957        out.writeStartElement(ns.getResponseNS(), "query");
    931958        out.writeCharacters(request.getRawQuery());
    932959        out.writeEndElement(); // "query"
    933960
    934961        // echoedSearchRetrieveRequest/xQuery
    935         out.setDefaultNamespace(SRU_XCQL_NS);
    936         out.writeStartElement(SRU_NS, "xQuery");
    937         out.writeDefaultNamespace(SRU_XCQL_NS);
     962        out.setDefaultNamespace(ns.getXcqlNS());
     963        out.writeStartElement(ns.getResponseNS(), "xQuery");
     964        out.writeDefaultNamespace(ns.getXcqlNS());
    938965        out.writeXCQL(cql, true);
    939966        out.writeEndElement(); // "xQuery" element
     
    941968        // echoedSearchRetrieveRequest/startRecord
    942969        if (request.getStartRecord() > 0) {
    943             out.writeStartElement(SRU_NS, "startRecord");
     970            out.writeStartElement(ns.getResponseNS(), "startRecord");
    944971            out.writeCharacters(Integer.toString(request.getStartRecord()));
    945972            out.writeEndElement(); // "startRecord" element
     
    948975        // echoedSearchRetrieveRequest/maximumRecords
    949976        if (request.getRawMaximumRecords() > 0) {
    950             out.writeStartElement(SRU_NS, "maximumRecords");
     977            out.writeStartElement(ns.getResponseNS(), "maximumRecords");
    951978            out.writeCharacters(
    952979                    Integer.toString(request.getRawMaximumRecords()));
     
    956983        // echoedSearchRetrieveRequest/recordPacking
    957984        if (request.getRawRecordPacking() != null) {
    958             writeRecordPacking(out, request.getRawRecordPacking());
     985            writeRecordPacking(out, ns, request.getRawRecordPacking());
    959986        }
    960987
    961988        // echoedSearchRetrieveRequest/recordSchema
    962989        if (request.getRawRecordSchemaIdentifier() != null) {
    963             out.writeStartElement(SRU_NS, "recordSchema");
     990            out.writeStartElement(ns.getResponseNS(), "recordSchema");
    964991            out.writeCharacters(request.getRawRecordSchemaIdentifier());
    965992            out.writeEndElement(); // "recordSchema" element
     
    969996        if (request.isVersion(SRUVersion.VERSION_1_1) &&
    970997                (request.getRecordXPath() != null)) {
    971             out.writeStartElement(SRU_NS, "recordXPath");
     998            out.writeStartElement(ns.getResponseNS(), "recordXPath");
    972999            out.writeCharacters(request.getRecordXPath());
    9731000            out.writeEndElement(); // "recordXPath" element
     
    9761003        // echoedSearchRetrieveRequest/resultSetTTL
    9771004        if (request.getResultSetTTL() > 0) {
    978             out.writeStartElement(SRU_NS, "resultSetTTL");
     1005            out.writeStartElement(ns.getResponseNS(), "resultSetTTL");
    9791006            out.writeCharacters(Long.toString(request.getResultSetTTL()));
    9801007            out.writeEndElement(); // "resultSetTTL" element
     
    9841011        if (request.isVersion(SRUVersion.VERSION_1_1) &&
    9851012                (request.getSortKeys() != null)) {
    986             out.writeStartElement(SRU_NS, "sortKeys");
     1013            out.writeStartElement(ns.getResponseNS(), "sortKeys");
    9871014            out.writeCharacters(request.getSortKeys());
    9881015            out.writeEndElement(); // "sortKeys" element
     
    9931020        // echoedSearchRetrieveRequest/stylesheet
    9941021        if (request.getStylesheet() != null) {
    995             out.writeStartElement(SRU_NS, "stylesheet");
     1022            out.writeStartElement(ns.getResponseNS(), "stylesheet");
    9961023            out.writeCharacters(request.getStylesheet());
    9971024            out.writeEndElement(); // "stylesheet" element
     
    10001027        // echoedSearchRetrieveRequest/baseUrl (SRU 1.2 only)
    10011028        if (request.isVersion(SRUVersion.VERSION_1_2)) {
    1002             writeBaseUrl(out, request);
     1029            writeBaseUrl(out, ns, request);
    10031030        }
    10041031
     
    10071034
    10081035
    1009     private void writeVersion(SRUXMLStreamWriter out, SRUVersion version)
    1010             throws XMLStreamException {
    1011         out.writeStartElement(SRU_NS, "version");
     1036    private void writeVersion(SRUXMLStreamWriter out, SRUNamespaces ns,
     1037            SRUVersion version) throws XMLStreamException {
     1038        out.writeStartElement(ns.getResponseNS(), "version");
    10121039        switch (version) {
    10131040        case VERSION_1_1:
     
    10171044            out.writeCharacters("1.2");
    10181045            break;
     1046        case VERSION_2_0:
     1047            out.writeCharacters("2.0");
     1048            break;
    10191049        } // switch
    10201050        out.writeEndElement(); // "version" element
     
    10221052
    10231053
    1024     private void writeRecordPacking(SRUXMLStreamWriter out,
     1054    private void writeRecordPacking(SRUXMLStreamWriter out, SRUNamespaces ns,
    10251055            SRURecordPacking recordPacking) throws XMLStreamException {
    1026         out.writeStartElement(SRU_NS, "recordPacking");
     1056        out.writeStartElement(ns.getResponseNS(), "recordPacking");
    10271057        switch (recordPacking) {
    10281058        case XML:
     
    10371067
    10381068
    1039     private void writeBaseUrl(SRUXMLStreamWriter out,
     1069    private void writeBaseUrl(SRUXMLStreamWriter out, SRUNamespaces ns,
    10401070            SRURequest request) throws XMLStreamException {
    1041         out.writeStartElement(SRU_NS, "baseUrl");
     1071        out.writeStartElement(ns.getResponseNS(), "baseUrl");
    10421072        out.writeCharacters(request.getProtocolScheme());
    10431073        out.writeCharacters(config.getBaseUrl());
     
    10461076
    10471077
    1048     private void writeLocalizedStrings(XMLStreamWriter writer, String name,
    1049             List<LocalizedString> list) throws XMLStreamException {
     1078    private void writeLocalizedStrings(XMLStreamWriter writer,
     1079            SRUNamespaces ns, String name, List<LocalizedString> list)
     1080            throws XMLStreamException {
    10501081        if ((list != null) && !list.isEmpty()) {
    10511082            for (LocalizedString item : list) {
    1052                 writer.writeStartElement(SRU_EXPLAIN_NS, name);
     1083                writer.writeStartElement(ns.getExplainNS(), name);
    10531084                if (item.getLang() != null) {
    10541085                    writer.writeAttribute("lang", item.getLang());
     
    11011132    }
    11021133
    1103 } // class SRUService
     1134
     1135    private SRUNamespaces getNamespaces(SRUVersion version) {
     1136        if (version == null) {
     1137            throw new NullPointerException("version == null");
     1138        }
     1139        switch (version) {
     1140        case VERSION_1_1:
     1141            /* FALL-THROUGH */
     1142        case VERSION_1_2:
     1143            return NAMESPACES_LEGACY;
     1144        case VERSION_2_0:
     1145            return NAMESPACES_2_0;
     1146        default:
     1147            // FIXME: better exception?
     1148            throw new IllegalAccessError("invalid version: " + version);
     1149        }
     1150    }
     1151
     1152
     1153
     1154
     1155    private static final SRUNamespaces NAMESPACES_LEGACY = new SRUNamespaces() {
     1156        private static final String SRU_NS =
     1157                "http://www.loc.gov/zing/srw/";
     1158        private static final String SRU_PREFIX =
     1159                "sru";
     1160        private static final String SRU_DIAGNOSIC_NS =
     1161                "http://www.loc.gov/zing/srw/diagnostic/";
     1162        private static final String SRU_DIAGNOSTIC_PREFIX =
     1163                "diag";
     1164        private static final String SRU_EXPLAIN_NS =
     1165                "http://explain.z3950.org/dtd/2.0/";
     1166        private static final String SRU_EXPLAIN_PREFIX =
     1167                "zr";
     1168        private static final String SRU_XCQL_NS =
     1169                "http://www.loc.gov/zing/cql/xcql/";
     1170
     1171
     1172        @Override
     1173        public String getResponseNS() {
     1174            return SRU_NS;
     1175        }
     1176
     1177
     1178        @Override
     1179        public String getResponsePrefix() {
     1180            return SRU_PREFIX;
     1181        }
     1182
     1183
     1184        @Override
     1185        public String getScanNS() {
     1186            return SRU_NS;
     1187        }
     1188
     1189
     1190        @Override
     1191        public String getScanPrefix() {
     1192            return SRU_PREFIX;
     1193        }
     1194
     1195
     1196        @Override
     1197        public String getDiagnosticNS() {
     1198            return SRU_DIAGNOSIC_NS;
     1199        }
     1200
     1201
     1202        @Override
     1203        public String getDiagnosticPrefix() {
     1204            return SRU_DIAGNOSTIC_PREFIX;
     1205        }
     1206
     1207
     1208        @Override
     1209        public String getExplainNS() {
     1210            return SRU_EXPLAIN_NS;
     1211        }
     1212
     1213
     1214        @Override
     1215        public String getExplainPrefix() {
     1216            return SRU_EXPLAIN_PREFIX;
     1217        }
     1218
     1219
     1220        @Override
     1221        public String getXcqlNS() {
     1222            return SRU_XCQL_NS;
     1223        }
     1224    };
     1225
     1226
     1227    private static final SRUNamespaces NAMESPACES_2_0 = new SRUNamespaces() {
     1228        private static final String SRU_RESPONSE_NS =
     1229                "http://docs.oasis-open.org/ns/search-ws/sruResponse";
     1230        private static final String SRU_RESPONSE_PREFIX =
     1231                "sruResponse";
     1232        private static final String SRU_SCAN_NS =
     1233                "http://docs.oasis-open.org/ns/search-ws/scan";
     1234        private static final String SRU_SCAN_PREFIX =
     1235                "scan";
     1236        private static final String SRU_DIAGNOSIC_NS =
     1237                "http://docs.oasis-open.org/ns/search-ws/diagnostic";
     1238        private static final String SRU_DIAGNOSTIC_PREFIX =
     1239                "diag";
     1240        private static final String SRU_EXPLAIN_NS =
     1241                "http://explain.z3950.org/dtd/2.0/";
     1242        private static final String SRU_EXPLAIN_PREFIX =
     1243                "zr";
     1244        private static final String SRU_XCQL_NS =
     1245                "http://docs.oasis-open.org/ns/search-ws/xcql";
     1246
     1247
     1248        @Override
     1249        public String getResponseNS() {
     1250            return SRU_RESPONSE_NS;
     1251        }
     1252
     1253
     1254        @Override
     1255        public String getResponsePrefix() {
     1256            return SRU_RESPONSE_PREFIX;
     1257        }
     1258
     1259
     1260        @Override
     1261        public String getScanNS() {
     1262            return SRU_SCAN_NS;
     1263        }
     1264
     1265
     1266        @Override
     1267        public String getScanPrefix() {
     1268            return SRU_SCAN_PREFIX;
     1269        }
     1270
     1271
     1272        @Override
     1273        public String getDiagnosticNS() {
     1274            return SRU_DIAGNOSIC_NS;
     1275        }
     1276
     1277
     1278        @Override
     1279        public String getDiagnosticPrefix() {
     1280            return SRU_DIAGNOSTIC_PREFIX;
     1281        }
     1282
     1283
     1284        @Override
     1285        public String getExplainNS() {
     1286            return SRU_EXPLAIN_NS;
     1287        }
     1288
     1289
     1290        @Override
     1291        public String getExplainPrefix() {
     1292            return SRU_EXPLAIN_PREFIX;
     1293        }
     1294
     1295
     1296        @Override
     1297        public String getXcqlNS() {
     1298            return SRU_XCQL_NS;
     1299        }
     1300    };
     1301
     1302} // class SRUServer
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUServerConfig.java

    r6105 r6779  
    8686public final class SRUServerConfig {
    8787    /**
     88     * Parameter constant for setting the minimum supported SRU version for this
     89     * SRU server. Must be smaller or equal to {@link #SRU_SUPPORTED_VERSION_MAX}.
     90     * <p>
     91     * Valid values: "<code>1.1</code>", "<code>1.2</code>" or "
     92     * <code>2.0</code>" (without quotation marks)
     93     * <p>
     94     */
     95    public static final String SRU_SUPPORTED_VERSION_MIN =
     96            "eu.clarin.sru.server.sruSupportedVersionMin";
     97    /**
     98     * Parameter constant for setting the maximum supported SRU version for this
     99     * SRU server. Must be larger or equal to {@link #SRU_SUPPORTED_VERSION_MIN}.
     100     * <p>
     101     * Valid values: "<code>1.1</code>", "<code>1.2</code>" or "
     102     * <code>2.0</code>" (without quotation marks)
     103     * <p>
     104     */
     105    public static final String SRU_SUPPORTED_VERSION_MAX =
     106            "eu.clarin.sru.server.sruSupportedVersionMax";
     107    /**
     108     * Parameter constant for setting the default SRU version for this SRU
     109     * server, e.g. for an <em>Explain</em> request without explicit version.
     110     * Must not me less than {@link #SRU_SUPPORTED_VERSION_MIN} or larger than
     111     * {@link #SRU_SUPPORTED_VERSION_MAX}. Defaults to
     112     * {@link #SRU_SUPPORTED_VERSION_MAX}.
     113     * <p>
     114     * Valid values: "<code>1.1</code>", "<code>1.2</code>" or "
     115     * <code>2.0</code>" (without quotation marks)
     116     * <p>
     117     */
     118    public static final String SRU_SUPPORTED_VERSION_DEFAULT =
     119            "eu.clarin.sru.server.sruSupportedVersionDefault";
     120    /**
    88121     * Parameter constant for configuring the transports for this SRU server.
    89122     * <p>
     
    293326    private static final String LEGACY_SRU_ALLOW_OVERRIDE_INDENT_RESPONSE =
    294327            "sru.allowOverrideIndentResponse";
     328    private static final SRUVersion DEFAULT_SRU_VERSION_MIN =
     329            SRUVersion.VERSION_1_1;
     330    private static final SRUVersion DEFAULT_SRU_VERSION_MAX =
     331            SRUVersion.VERSION_1_2;
    295332    private static final int DEFAULT_NUMBER_OF_RECORDS    = 100;
    296333    private static final int DEFAULT_MAXIMUM_RECORDS      = 250;
     
    627664    private static final Logger logger =
    628665            LoggerFactory.getLogger(SRUServerConfig.class);
     666    private final SRUVersion minVersion;
     667    private final SRUVersion maxVersion;
     668    private final SRUVersion defaultVersion;
    629669    private final String transport;
    630670    private final String host;
     
    647687
    648688
    649     private SRUServerConfig(String transport, String host, int port,
     689    private SRUServerConfig(SRUVersion minVersion, SRUVersion maxVersion,
     690            SRUVersion defaultVersion, String transport, String host, int port,
    650691            String database, int numberOfRecords, int maximumRecords,
    651692            int numberOfTerms, int maximumTerms, boolean echoRequests,
     
    655696            boolean allowOverrideIndentResponse, DatabaseInfo databaseinfo,
    656697            IndexInfo indexInfo, List<SchemaInfo> schemaInfo) {
     698        this.minVersion                  = minVersion;
     699        this.maxVersion                  = maxVersion;
     700        this.defaultVersion              = defaultVersion;
    657701        this.transport                   = transport;
    658702        this.host                        = host;
     
    688732
    689733
     734    public SRUVersion getMinVersion() {
     735        return minVersion;
     736    }
     737
     738
     739    public SRUVersion getMaxVersion() {
     740        return maxVersion;
     741    }
     742
     743
    690744    public SRUVersion getDefaultVersion() {
    691         return SRUVersion.VERSION_1_2;
     745        return defaultVersion;
    692746    }
    693747
     
    937991
    938992            /*
    939              * fetch parameters more parameters
     993             * fetch parameters more parameters (usually passed from Servlet
     994             * context)
    940995             */
     996
     997            SRUVersion minVersion = parseVersionNumber(params,
     998                    SRU_SUPPORTED_VERSION_MIN, false, DEFAULT_SRU_VERSION_MIN);
     999
     1000            SRUVersion maxVersion = parseVersionNumber(params,
     1001                    SRU_SUPPORTED_VERSION_MAX, false, DEFAULT_SRU_VERSION_MAX);
     1002            if (maxVersion.compareTo(minVersion) < 0) {
     1003                throw new SRUConfigException(
     1004                        "parameter value \"" + SRU_SUPPORTED_VERSION_MAX +
     1005                                "\" (" + maxVersion.getVersionString() +
     1006                                ") must be equal or larger than value of parameter \"" +
     1007                                SRU_SUPPORTED_VERSION_MIN + "\" (" +
     1008                                minVersion.getVersionString() + ")");
     1009            }
     1010
     1011            SRUVersion defaultVersion = parseVersionNumber(params,
     1012                    SRU_SUPPORTED_VERSION_DEFAULT, false, maxVersion);
     1013            if ((defaultVersion.compareTo(minVersion) < 0) ||
     1014                    (defaultVersion.compareTo(maxVersion) > 0)) {
     1015                throw new SRUConfigException(
     1016                        "parameter value \"" + SRU_SUPPORTED_VERSION_DEFAULT +
     1017                                "\" (" + defaultVersion.getVersionString() +
     1018                                ") must be between value of parameter \"" +
     1019                                SRU_SUPPORTED_VERSION_MIN + "\" (" +
     1020                                minVersion.getVersionString() + ") and \"" +
     1021                                SRU_SUPPORTED_VERSION_MAX + "\" (" +
     1022                                maxVersion.getVersionString() + ")");
     1023            }
     1024
    9411025            String transport = params.get(SRU_TRANSPORT);
    9421026            if ((transport == null) || transport.isEmpty()) {
     
    10111095                    DEFAULT_RESPONSE_BUFFER_SIZE, 0, -1);
    10121096
    1013             return new SRUServerConfig(transport, host, port, database,
    1014                     numberOfRecords, maximumRecords, numberOfTerms,
    1015                     maximumTerms, echoRequests, indentResponse,
    1016                     responseBufferSize, allowOverrideMaximumRecords,
    1017                     allowOverrideMaximumTerms, allowOverrideIndentResponse,
    1018                     databaseInfo, indexInfo, schemaInfo);
     1097            return new SRUServerConfig(minVersion, maxVersion, defaultVersion,
     1098                    transport, host, port, database, numberOfRecords,
     1099                    maximumRecords, numberOfTerms, maximumTerms, echoRequests,
     1100                    indentResponse, responseBufferSize,
     1101                    allowOverrideMaximumRecords, allowOverrideMaximumTerms,
     1102                    allowOverrideIndentResponse, databaseInfo, indexInfo,
     1103                    schemaInfo);
    10191104        } catch (IOException e) {
    10201105            throw new SRUConfigException("error reading configuration file", e);
     
    10251110        } catch (SAXException e) {
    10261111            throw new SRUConfigException("error parsing configuration file", e);
     1112        }
     1113    }
     1114
     1115
     1116    private static SRUVersion parseVersionNumber(Map<String, String> params,
     1117            String name, boolean mandatory, SRUVersion defaultValue)
     1118                    throws SRUConfigException {
     1119        String value = params.get(name);
     1120        if ((value == null) || value.isEmpty()) {
     1121            if (mandatory) {
     1122                throw new SRUConfigException(
     1123                        "parameter \"" + name + "\" is mandatory");
     1124            } else {
     1125                return defaultValue;
     1126            }
     1127        } else {
     1128            if ("1.1".equals(value)) {
     1129                return SRUVersion.VERSION_1_1;
     1130            } else if ("1.2".equals(value)) {
     1131                return SRUVersion.VERSION_1_2;
     1132            } else if ("2.0".equals(value)) {
     1133                return SRUVersion.VERSION_2_0;
     1134            } else {
     1135                throw new SRUConfigException("invalid value for parameter \"" +
     1136                        name + "\": " + value);
     1137            }
    10271138        }
    10281139    }
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUVersion.java

    r2623 r6779  
    5151            return "1.2";
    5252        }
     53    },
     54
     55    /**
     56     * SRU/CQL version 2.0
     57     */
     58    VERSION_2_0 {
     59        @Override
     60        int getVersionNumber() {
     61            return ((2 << 16) | 0);
     62        }
     63
     64
     65        @Override
     66        String getVersionString() {
     67            return "2.0";
     68        }
    5369    };
    5470
Note: See TracChangeset for help on using the changeset viewer.