Ignore:
Timestamp:
06/16/12 17:12:37 (12 years ago)
Author:
oschonef
Message:
  • add SRUServerServlet and SRUSearchEngineBase
  • add close() method to response objects
  • remove hasMore*() methods and modify next*() to return boolean from SRUScanResponse and SRUSearchResponse

HEADS UP:
This commit breaks existing API and requires changes to your SRUScanResponse and SRUSearchResponse implementations

File:
1 edited

Legend:

Unmodified
Added
Removed
  • SRUServer/trunk/src/main/java/eu/clarin/sru/server/SRUServer.java

    r1989 r1990  
    3737import eu.clarin.sru.server.SRUServerConfig.LocalizedString;
    3838import eu.clarin.sru.server.SRUServerConfig.SchemaInfo;
     39import eu.clarin.sru.server.utils.SRUServerServlet;
    3940
    4041
     
    4243 * SRU/CQL protocol implementation for the server-side (SRU/S). This class
    4344 * implements SRU/CQL version 1.1 and and 1.2.
    44  * <p>
    45  * An example servlet using this class:
    46  * </p>
    47  * <pre>
    48  * public class MySRUServlet extends HttpServlet {
    49  *     private transient SRUServer sruServer;
    50  *
    51  *
    52  *     public void init() throws ServletException {
    53  *         final ServletContext ctx = getServletContext();
    54  *         try {
    55  *             URL url = MySRUServlet.class.getClassLoader().getResource(
    56  *                     &quot;META-INF/endpoint-config.xml&quot;);
    57  *             if (url == null) {
    58  *                 throw new ServletException(&quot;not found, url == null&quot;);
    59  *             }
    60  *
    61  *             // get additional runtime configuration from Servlet context
    62  *             HashMap&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
    63  *             for (Enumeration&lt;?&gt; i = ctx.getInitParameterNames(); i
    64  *                     .hasMoreElements();) {
    65  *                 String key = (String) i.nextElement();
    66  *                 String value = ctx.getInitParameter(key);
    67  *                 if ((value != null) &amp;&amp; !value.isEmpty()) {
    68  *                     params.put(key, value);
    69  *                 }
    70  *             }
    71  *
    72  *             SRUServerConfig config = SRUServerConfig.parse(params,
    73  *                     url.openStream());
    74  *             SRUSearchEngine searchEngine = new MySRUSearchEngine(config, params);
    75  *             sruServer = new SRUServer(config, searchEngine);
    76  *         } catch (Exception e) {
    77  *             throw new ServletException(&quot;error initializing endpoint&quot;, e);
    78  *         }
    79  *     }
    80  *
    81  *
    82  *     protected void doGet(HttpServletRequest request,
    83  *             HttpServletResponse response) throws ServletException, IOException {
    84  *         sruServer.handleRequest(request, response);
    85  *     }
    86  *
    87  *
    88  *     protected void doPost(HttpServletRequest request,
    89  *             HttpServletResponse response) throws ServletException, IOException {
    90  *         sruServer.handleRequest(request, response);
    91  *     }
    92  * }
    93  * </pre>
    9445 *
    9546 * @see SRUServerConfig
    9647 * @see SRUSearchEngine
     48 * @see SRUServerServlet
    9749 * @see <a href="http://www.loc.gov/standards/sru/">SRU/CQL protocol 1.2</a>
    9850 */
    99 public class SRUServer {
     51public final class SRUServer {
    10052    private static final String SRU_NS =
    10153            "http://www.loc.gov/zing/srw/";
     
    228180
    229181        // commence explain ...
    230         SRUExplainResult result = searchEngine.explain(config,
    231                 request, request);
    232 
    233         // send results
    234         SRUXMLStreamWriter out =
    235                 createXMLStreamWriter(response.getOutputStream(),
    236                                       request.getRecordPacking(),
    237                                       request.getIndentResponse());
    238 
    239         beginResponse(out, request);
    240 
    241         // write the explain record
    242         writeExplainRecord(out, request);
    243 
    244         if (config.getEchoRequests()) {
    245             writeEchoedExplainRequest(out, request);
    246         }
    247 
    248         // diagnostics
    249         writeDiagnosticList(out, request.getDiagnostics());
    250 
    251         // extraResponseData
    252         if (result != null) {
     182        final SRUExplainResult result =
     183                searchEngine.explain(config, request, request);
     184
     185        try {
     186            // send results
     187            SRUXMLStreamWriter out =
     188                    createXMLStreamWriter(response.getOutputStream(),
     189                                          request.getRecordPacking(),
     190                                          request.getIndentResponse());
     191
     192            beginResponse(out, request);
     193
     194            // write the explain record
     195            writeExplainRecord(out, request);
     196
     197            if (config.getEchoRequests()) {
     198                writeEchoedExplainRequest(out, request);
     199            }
     200
     201            // diagnostics
     202            writeDiagnosticList(out, request.getDiagnostics());
     203
     204            // extraResponseData
     205            if (result != null) {
     206                if (result.hasExtraResponseData()) {
     207                    out.writeStartElement(SRU_NS, "extraResponseData");
     208                    result.writeExtraResponseData(out);
     209                    out.writeEndElement(); // "extraResponseData" element
     210                }
     211            }
     212
     213            endResponse(out);
     214        } finally {
     215            if (result != null) {
     216                result.close();
     217            }
     218        }
     219    }
     220
     221
     222    private void scan(SRURequestImpl request, HttpServletResponse response)
     223            throws IOException, XMLStreamException, SRUException {
     224        logger.info("scan: scanClause = \"{}\"",
     225                new Object[] { request.getRawScanClause() });
     226
     227        // commence scan
     228        final SRUScanResultSet result =
     229                searchEngine.scan(config, request, request);
     230        if (result == null) {
     231            throw new SRUException(SRUConstants.SRU_UNSUPPORTED_OPERATION,
     232                    "The 'scan' operation is not supported by this endpoint.");
     233        }
     234
     235        try {
     236            // send results
     237            SRUXMLStreamWriter out =
     238                    createXMLStreamWriter(response.getOutputStream(),
     239                                          request.getRecordPacking(),
     240                                          request.getIndentResponse());
     241
     242            beginResponse(out, request);
     243
     244            try {
     245                out.writeStartElement(SRU_NS, "terms");
     246                while (result.nextTerm()) {
     247                    out.writeStartElement(SRU_NS, "term");
     248
     249                    out.writeStartElement(SRU_NS, "value");
     250                    out.writeCharacters(result.getValue());
     251                    out.writeEndElement(); // "value" element
     252
     253                    if (result.getNumberOfRecords() > -1) {
     254                        out.writeStartElement(SRU_NS, "numberOfRecords");
     255                        out.writeCharacters(
     256                                Integer.toString(result.getNumberOfRecords()));
     257                        out.writeEndElement(); // "numberOfRecords" element
     258                    }
     259
     260                    if (result.getDisplayTerm() != null) {
     261                        out.writeStartElement(SRU_NS, "displayTerm");
     262                        out.writeCharacters(result.getDisplayTerm());
     263                        out.writeEndElement(); // "displayTerm" element
     264                    }
     265
     266                    if (result.getWhereInList() != null) {
     267                        out.writeStartElement(SRU_NS, "whereInList");
     268                        switch (result.getWhereInList()) {
     269                        case FIRST:
     270                            out.writeCharacters("first");
     271                            break;
     272                        case LAST:
     273                            out.writeCharacters("last");
     274                            break;
     275                        case ONLY:
     276                            out.writeCharacters("only");
     277                            break;
     278                        case INNER:
     279                            out.writeCharacters("inner");
     280                            break;
     281                        } // switch
     282                        out.writeEndElement(); // "whereInList" element
     283                    }
     284
     285                    if (result.hasExtraTermData()) {
     286                        out.writeStartElement(SRU_NS, "extraTermData");
     287                        result.writeExtraTermData(out);
     288                        out.writeEndElement(); // "extraTermData" element
     289                    }
     290
     291                    out.writeEndElement(); // "term" element
     292                } // while
     293                out.writeEndElement(); // "terms" element
     294            } catch (NoSuchElementException e) {
     295                throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
     296                        "An internal error occurred while "
     297                                + "serializing scan results.");
     298            }
     299
     300            // echoedScanRequest
     301            if (config.getEchoRequests()) {
     302                writeEchoedScanRequest(out, request, request.getScanClause());
     303            }
     304
     305            // diagnostics
     306            writeDiagnosticList(out, request.getDiagnostics());
     307
     308            // extraResponseData
    253309            if (result.hasExtraResponseData()) {
    254310                out.writeStartElement(SRU_NS, "extraResponseData");
     
    256312                out.writeEndElement(); // "extraResponseData" element
    257313            }
    258         }
    259 
    260         endResponse(out);
    261     }
    262 
    263 
    264     private void scan(SRURequestImpl request, HttpServletResponse response)
    265             throws IOException, XMLStreamException, SRUException {
    266         logger.info("scan: scanClause = \"{}\"",
    267                 new Object[] { request.getRawScanClause() });
    268 
    269         // commence scan
    270         final SRUScanResultSet result = searchEngine.scan(config,
    271                 request, request);
    272         if (result == null) {
    273             throw new SRUException(SRUConstants.SRU_UNSUPPORTED_OPERATION,
    274                     "The 'scan' operation is not supported by this endpoint.");
    275         }
    276 
    277         // send results
    278         SRUXMLStreamWriter out =
    279                 createXMLStreamWriter(response.getOutputStream(),
    280                                       request.getRecordPacking(),
    281                                       request.getIndentResponse());
    282 
    283         beginResponse(out, request);
    284 
    285         try {
    286             out.writeStartElement(SRU_NS, "terms");
    287             while (result.hasMoreTerms()) {
    288                 out.writeStartElement(SRU_NS, "term");
    289 
    290                 out.writeStartElement(SRU_NS, "value");
    291                 out.writeCharacters(result.getValue());
    292                 out.writeEndElement(); // "value" element
    293 
    294                 if (result.getNumberOfRecords() > -1) {
    295                     out.writeStartElement(SRU_NS, "numberOfRecords");
    296                     out.writeCharacters(
    297                             Integer.toString(result.getNumberOfRecords()));
    298                     out.writeEndElement(); // "numberOfRecords" element
    299                 }
    300 
    301                 if (result.getDisplayTerm() != null) {
    302                     out.writeStartElement(SRU_NS, "displayTerm");
    303                     out.writeCharacters(result.getDisplayTerm());
    304                     out.writeEndElement(); // "displayTerm" element
    305                 }
    306 
    307                 if (result.getWhereInList() != null) {
    308                     out.writeStartElement(SRU_NS, "whereInList");
    309                     switch (result.getWhereInList()) {
    310                     case FIRST:
    311                         out.writeCharacters("first");
    312                         break;
    313                     case LAST:
    314                         out.writeCharacters("last");
    315                         break;
    316                     case ONLY:
    317                         out.writeCharacters("only");
    318                         break;
    319                     case INNER:
    320                         out.writeCharacters("inner");
    321                         break;
    322                     } // switch
    323                     out.writeEndElement(); // "whereInList" element
    324                 }
    325 
    326                 if (result.hasExtraTermData()) {
    327                     out.writeStartElement(SRU_NS, "extraTermData");
    328                     result.writeExtraTermData(out);
    329                     out.writeEndElement(); // "extraTermData" element
    330                 }
    331 
    332                 out.writeEndElement(); // "term" element
    333 
    334                 result.nextTerm();
    335             }
    336             out.writeEndElement(); // "terms" element
    337         } catch (NoSuchElementException e) {
    338             throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
    339                     "An internal error occurred while " +
    340                     "serializing scan results.");
    341         }
    342 
    343         // echoedScanRequest
    344         if (config.getEchoRequests()) {
    345             writeEchoedScanRequest(out, request, request.getScanClause());
    346         }
    347 
    348         // diagnostics
    349         writeDiagnosticList(out, request.getDiagnostics());
    350 
    351         // extraResponseData
    352         if (result.hasExtraResponseData()) {
    353             out.writeStartElement(SRU_NS, "extraResponseData");
    354             result.writeExtraResponseData(out);
    355             out.writeEndElement(); // "extraResponseData" element
    356         }
    357 
    358         endResponse(out);
     314
     315            endResponse(out);
     316        } finally {
     317            if (result != null) {
     318                result.close();
     319            }
     320        }
    359321    }
    360322
     
    370332
    371333        // commence search ...
    372         final SRUSearchResultSet result = searchEngine.search(config,
    373                 request, request);
     334        final SRUSearchResultSet result =
     335                searchEngine.search(config, request, request);
    374336        if (result == null) {
    375337            throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
    376                     "Database implementation returned invalid result (null).");
    377         }
    378 
    379         // send results
    380         SRUXMLStreamWriter out =
    381                 createXMLStreamWriter(response.getOutputStream(),
    382                                       request.getRecordPacking(),
    383                                       request.getIndentResponse());
    384 
    385         beginResponse(out, request);
    386 
    387         // numberOfRecords
    388         out.writeStartElement(SRU_NS, "numberOfRecords");
    389         out.writeCharacters(Integer.toString(result.getTotalRecordCount()));
    390         out.writeEndElement(); // "numberOfRecords" element
    391 
    392         // resultSetId
    393         if (result.getResultSetId() != null) {
    394             out.writeStartElement(SRU_NS, "resultSetId");
    395             out.writeCharacters(result.getResultSetId());
    396             out.writeEndElement(); // "resultSetId" element
    397         }
    398 
    399         // resultSetIdleTime
    400         if (result.getResultSetIdleTime() > 0) {
    401             out.writeStartElement(SRU_NS, "resultSetIdleTime");
     338                    "SRUSearchEngine implementation returned invalid result (null).");
     339        }
     340
     341        try {
     342            // send results
     343            SRUXMLStreamWriter out =
     344                    createXMLStreamWriter(response.getOutputStream(),
     345                                          request.getRecordPacking(),
     346                                          request.getIndentResponse());
     347
     348            beginResponse(out, request);
     349
     350            // numberOfRecords
     351            out.writeStartElement(SRU_NS, "numberOfRecords");
    402352            out.writeCharacters(
    403                     Integer.toString(result.getResultSetIdleTime()));
    404             out.writeEndElement();  // "resultSetIdleTime" element
    405         }
    406 
    407         int position = (request.getStartRecord() > 0)
    408                      ? request.getStartRecord() : 1;
    409         if (result.getRecordCount() > 0) {
    410             final int maxPositionOffset =
    411                     (request.getMaximumRecords() != -1)
    412                     ? (position + request.getMaximumRecords() - 1) : - 1;
    413             try {
    414                 out.writeStartElement(SRU_NS, "records");
    415                 while (result.hasMoreRecords()) {
    416                     /*
    417                      * Sanity check: do not return more then the maximum
    418                      * requested records. If database implementation does
    419                      * not honor limit truncate the result set.
    420                      */
    421                     if ((maxPositionOffset != -1) &&
    422                             (position > maxPositionOffset)) {
    423                         logger.error("SRUSearchEngine implementation did not " +
    424                                 "honor limit for the amount of requsted " +
    425                                 "records. Result set truncated!");
    426                         break;
    427                     }
    428 
    429                     out.writeStartElement(SRU_NS, "record");
    430 
    431                     /*
    432                      *  We need to output either the record or a
    433                      *  surrogate diagnostic. In case of the latter, we need
    434                      *  to output the appropriate record schema ...
    435                      */
    436                     SRUDiagnostic diagnostic = result.getSurrogateDiagnostic();
    437 
    438                     out.writeStartElement(SRU_NS, "recordSchema");
    439                     if (diagnostic == null) {
    440                         out.writeCharacters(result.getRecordSchemaIdentifier());
    441                     } else {
    442                         out.writeCharacters(SRU_DIAGNOSTIC_RECORD_SCHEMA);
    443                     }
    444                     out.writeEndElement(); // "recordSchema" element
    445 
    446                     // recordPacking
    447                     writeRecordPacking(out, request.getRecordPacking());
    448 
    449                     /*
    450                      * Output either record data or surrogate diagnostic ...
    451                      */
    452                     out.writeStartElement(SRU_NS, "recordData");
    453                     out.startRecord();
    454                     if (diagnostic == null) {
    455                         result.writeRecord(out);
    456                     } else {
    457                         // write a surrogate diagnostic
    458                         writeDiagnostic(out, diagnostic, true);
    459                     }
    460                     out.endRecord();
    461                     out.writeEndElement(); // "recordData" element
    462 
    463                     /*
    464                      * recordIdentifier is version 1.2 only
    465                      */
    466                     if (request.isVersion(SRUVersion.VERSION_1_2)) {
    467                         final String identifier = result.getRecordIdentifier();
    468                         if (identifier != null) {
    469                             out.writeStartElement(SRU_NS, "recordIdentifier");
    470                             out.writeCharacters(identifier);
    471                             out.writeEndElement(); // "recordIdentifier" element
     353                    Integer.toString(result.getTotalRecordCount()));
     354            out.writeEndElement(); // "numberOfRecords" element
     355
     356            // resultSetId
     357            if (result.getResultSetId() != null) {
     358                out.writeStartElement(SRU_NS, "resultSetId");
     359                out.writeCharacters(result.getResultSetId());
     360                out.writeEndElement(); // "resultSetId" element
     361            }
     362
     363            // resultSetIdleTime
     364            if (result.getResultSetIdleTime() > 0) {
     365                out.writeStartElement(SRU_NS, "resultSetIdleTime");
     366                out.writeCharacters(Integer.toString(result
     367                        .getResultSetIdleTime()));
     368                out.writeEndElement(); // "resultSetIdleTime" element
     369            }
     370
     371            int position = (request.getStartRecord() > 0)
     372                    ? request.getStartRecord() : 1;
     373            if (result.getRecordCount() > 0) {
     374                final int maxPositionOffset =
     375                        (request.getMaximumRecords() != -1)
     376                        ? (position + request.getMaximumRecords() - 1)
     377                        : -1;
     378                try {
     379                    out.writeStartElement(SRU_NS, "records");
     380                    while (result.nextRecord()) {
     381                        /*
     382                         * Sanity check: do not return more then the maximum
     383                         * requested records. If the search engine
     384                         * implementation does not honor limit truncate the
     385                         * result set.
     386                         */
     387                        if ((maxPositionOffset != -1) &&
     388                                (position > maxPositionOffset)) {
     389                            logger.error("SRUSearchEngine implementation did " +
     390                                    "not honor limit for the amount of " +
     391                                    "requsted records. Result set truncated!");
     392                            break;
    472393                        }
    473                     }
    474 
    475                     out.writeStartElement(SRU_NS, "recordPosition");
    476                     out.writeCharacters(Integer.toString(position));
    477                     out.writeEndElement(); // "recordPosition" element
    478 
    479                     if (result.hasExtraRecordData()) {
    480                         out.writeStartElement(SRU_NS, "extraRecordData");
    481                         result.writeExtraRecordData(out);
    482                         out.writeEndElement(); // "extraRecordData"
    483                     }
    484 
    485                     out.writeEndElement(); // "record" element
    486 
    487                     result.nextRecord();
    488                     position++;
     394
     395                        out.writeStartElement(SRU_NS, "record");
     396
     397                        /*
     398                         * We need to output either the record or a surrogate
     399                         * diagnostic. In case of the latter, we need to output
     400                         * the appropriate record schema ...
     401                         */
     402                        final SRUDiagnostic diagnostic =
     403                                result.getSurrogateDiagnostic();
     404
     405                        out.writeStartElement(SRU_NS, "recordSchema");
     406                        if (diagnostic == null) {
     407                            out.writeCharacters(
     408                                    result.getRecordSchemaIdentifier());
     409                        } else {
     410                            out.writeCharacters(SRU_DIAGNOSTIC_RECORD_SCHEMA);
     411                        }
     412                        out.writeEndElement(); // "recordSchema" element
     413
     414                        // recordPacking
     415                        writeRecordPacking(out, request.getRecordPacking());
     416
     417                        /*
     418                         * Output either record data or surrogate diagnostic ...
     419                         */
     420                        out.writeStartElement(SRU_NS, "recordData");
     421                        out.startRecord();
     422                        if (diagnostic == null) {
     423                            result.writeRecord(out);
     424                        } else {
     425                            // write a surrogate diagnostic
     426                            writeDiagnostic(out, diagnostic, true);
     427                        }
     428                        out.endRecord();
     429                        out.writeEndElement(); // "recordData" element
     430
     431                        /*
     432                         * recordIdentifier is version 1.2 only
     433                         */
     434                        if (request.isVersion(SRUVersion.VERSION_1_2)) {
     435                            final String identifier =
     436                                    result.getRecordIdentifier();
     437                            if (identifier != null) {
     438                                out.writeStartElement(SRU_NS,
     439                                                      "recordIdentifier");
     440                                out.writeCharacters(identifier);
     441                                out.writeEndElement(); // "recordIdentifier" element
     442                            }
     443                        }
     444
     445                        out.writeStartElement(SRU_NS, "recordPosition");
     446                        out.writeCharacters(Integer.toString(position));
     447                        out.writeEndElement(); // "recordPosition" element
     448
     449                        if (result.hasExtraRecordData()) {
     450                            out.writeStartElement(SRU_NS, "extraRecordData");
     451                            result.writeExtraRecordData(out);
     452                            out.writeEndElement(); // "extraRecordData"
     453                        }
     454
     455                        out.writeEndElement(); // "record" element
     456
     457                        position++;
     458                    } // while
     459                    out.writeEndElement(); // "records" element
     460                } catch (NoSuchElementException e) {
     461                    throw new SRUException(
     462                            SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
     463                            "An internal error occurred while " +
     464                            "serializing search result set.");
    489465                }
    490                 out.writeEndElement(); // "records" element
    491             } catch (NoSuchElementException e) {
    492                 throw new SRUException(SRUConstants.SRU_GENERAL_SYSTEM_ERROR,
    493                         "An internal error occurred while " +
    494                         "serializing search result set.");
    495             }
    496         }
    497 
    498         // nextRecordPosition
    499         if (position <= result.getTotalRecordCount()) {
    500             out.writeStartElement(SRU_NS, "nextRecordPosition");
    501             out.writeCharacters(Integer.toString(position));
    502             out.writeEndElement();
    503         }
    504 
    505         // echoedSearchRetrieveRequest
    506         if (config.getEchoRequests()) {
    507             writeEchoedSearchRetrieveRequest(out, request, request.getQuery());
    508         }
    509 
    510         // diagnostics
    511         writeDiagnosticList(out, request.getDiagnostics());
    512 
    513         // extraResponseData
    514         if (result.hasExtraResponseData()) {
    515             out.writeStartElement(SRU_NS, "extraResponseData");
    516             result.writeExtraResponseData(out);
    517             out.writeEndElement(); // "extraResponseData" element
    518         }
    519 
    520         endResponse(out);
     466            }
     467
     468            // nextRecordPosition
     469            if (position <= result.getTotalRecordCount()) {
     470                out.writeStartElement(SRU_NS, "nextRecordPosition");
     471                out.writeCharacters(Integer.toString(position));
     472                out.writeEndElement();
     473            }
     474
     475            // echoedSearchRetrieveRequest
     476            if (config.getEchoRequests()) {
     477                writeEchoedSearchRetrieveRequest(out, request,
     478                                                 request.getQuery());
     479            }
     480
     481            // diagnostics
     482            writeDiagnosticList(out, request.getDiagnostics());
     483
     484            // extraResponseData
     485            if (result.hasExtraResponseData()) {
     486                out.writeStartElement(SRU_NS, "extraResponseData");
     487                result.writeExtraResponseData(out);
     488                out.writeEndElement(); // "extraResponseData" element
     489            }
     490
     491            endResponse(out);
     492        } finally {
     493            result.close();
     494        }
    521495    }
    522496
Note: See TracChangeset for help on using the changeset viewer.