Changeset 2024


Ignore:
Timestamp:
07/10/12 16:29:35 (12 years ago)
Author:
oschonef
Message:
  • be more robust, when parsing responses
  • add mechanism to send invalid requests (NB: use to provoke errors when testing endpoints for protocol conformance)
Location:
SRUClient/trunk/src/main/java/eu/clarin/sru/client
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractRequest.java

    r1971 r2024  
    2929    private static final String VERSION_1_2               = "1.2";
    3030    private static final String PARAM_EXTENSION_PREFIX    = "x-";
     31    /** for end-point conformance testing only. never use in production */
     32    public static final String X_MALFORMED_VERSION       =
     33            "x-malformed-version";
     34    /** for end-point conformance testing only. never use in production */
     35    public static final String X_MALFORMED_OPERATION     =
     36            "x-maformed-operation";
     37    /** for end-point conformance testing only. never use in production */
     38    public static final String MALFORMED_OMIT            = "omit";
     39
    3140    protected enum SRUOperation {
    3241        EXPLAIN, SCAN, SEARCH_RETRIEVE
    33     }
     42    } // enum SRUOperation
     43
     44    protected class URIBuilder {
     45        private final StringBuilder sb;
     46        private boolean firstParam = true;
     47
     48        private URIBuilder(String endpointURI) {
     49            this.sb = new StringBuilder(endpointURI);
     50        }
     51
     52
     53        public URIBuilder append(String name, String value) {
     54            if (name == null) {
     55                throw new NullPointerException("name == null");
     56            }
     57            if (name.isEmpty()) {
     58                throw new IllegalArgumentException("name is empty");
     59            }
     60            if (value == null) {
     61                throw new NullPointerException("vale == null");
     62            }
     63            if (value.isEmpty()) {
     64                throw new IllegalArgumentException("value is empty");
     65            }
     66
     67            if (firstParam) {
     68                sb.append('?');
     69                firstParam = false;
     70            } else {
     71                sb.append('&');
     72            }
     73            sb.append(name).append('=').append(value);
     74            return this;
     75        }
     76
     77
     78        public URIBuilder append(String name, int value) {
     79            return append(name, Integer.toString(value));
     80        }
     81
     82
     83        private URI makeURI() {
     84            return URI.create(sb.toString());
     85        }
     86    } // class
    3487    protected final String endpointURI;
    3588    protected SRUVersion version;
    3689    protected Map<String, String> extraRequestData;
     90    private SRUVersion versionPreformed;
    3791
    3892
     
    57111    public SRUVersion getVersion() {
    58112        return version;
     113    }
     114
     115
     116    public SRUVersion getVersionPerformed() {
     117        return versionPreformed;
    59118    }
    60119
     
    106165            throw new NullPointerException("defaultVersion == null");
    107166        }
    108         StringBuilder uri = new StringBuilder(endpointURI);
    109 
    110         // operation
    111         uri.append('?').append(PARAM_OPERATION).append('=');
    112         switch (getOperation()) {
    113         case EXPLAIN:
    114             uri.append(OP_EXPLAIN);
    115             break;
    116         case SCAN:
    117             uri.append(OP_SCAN);
    118             break;
    119         case SEARCH_RETRIEVE:
    120             uri.append(OP_SEARCH_RETRIEVE);
    121             break;
    122         default:
    123             throw new SRUClientException(
    124                     "unsupported operation: " + getOperation());
    125         } // switch
    126 
    127         // version
    128         SRUVersion v = (version != null) ? version : defaultVersion;
    129         uri.append('&').append(PARAM_VERSION).append('=');
    130         switch (v) {
    131         case VERSION_1_1:
    132             uri.append(VERSION_1_1);
    133             break;
    134         case VERSION_1_2:
    135             uri.append(VERSION_1_2);
    136             break;
    137         default:
    138             throw new SRUClientException("unsupported version: " + v);
    139         } // switch
     167        URIBuilder uriBuilder = new URIBuilder(endpointURI);
     168
     169        /*
     170         * append operation parameter
     171         *
     172         * NB: Setting "x-operation-version" as an extra request parameter makes
     173         * the client to send invalid requests. This is intended to use for
     174         * testing endpoints for protocol conformance (i.e. provoke an error)
     175         * and SHOULD NEVER be used in production!
     176         */
     177        final String malformedOperation =
     178                getExtraRequestData(X_MALFORMED_OPERATION);
     179        if (malformedOperation == null) {
     180            switch (getOperation()) {
     181            case EXPLAIN:
     182                uriBuilder.append(PARAM_OPERATION, OP_EXPLAIN);
     183                break;
     184            case SCAN:
     185                uriBuilder.append(PARAM_OPERATION, OP_SCAN);
     186                break;
     187            case SEARCH_RETRIEVE:
     188                uriBuilder.append(PARAM_OPERATION, OP_SEARCH_RETRIEVE);
     189                break;
     190            default:
     191                throw new SRUClientException(
     192                        "unsupported operation: " + getOperation());
     193            } // switch
     194        } else {
     195            if (!malformedOperation.equals(MALFORMED_OMIT)) {
     196                uriBuilder.append(PARAM_OPERATION, malformedOperation);
     197            }
     198        }
     199
     200        /*
     201         * append version parameter
     202         *
     203         * NB: Setting "x-malformed-version" as an extra request parameter makes
     204         * the client to send invalid requests. This is intended to use for
     205         * testing endpoints for protocol conformance (i.e. provoke an error)
     206         * and SHOULD NEVER be used in production!
     207         */
     208        final String malformedVersion =
     209                getExtraRequestData(X_MALFORMED_VERSION);
     210        if (malformedVersion == null) {
     211            versionPreformed = (version != null) ? version : defaultVersion;
     212            switch (versionPreformed) {
     213            case VERSION_1_1:
     214                uriBuilder.append(PARAM_VERSION, VERSION_1_1);
     215                break;
     216            case VERSION_1_2:
     217                uriBuilder.append(PARAM_VERSION, VERSION_1_2);
     218                break;
     219            default:
     220                throw new SRUClientException("unsupported version: " +
     221                        versionPreformed);
     222            } // switch
     223        } else {
     224            if (!malformedVersion.equalsIgnoreCase(MALFORMED_OMIT)) {
     225                uriBuilder.append(PARAM_VERSION, malformedVersion);
     226            }
     227        }
    140228
    141229        // request specific parameters
    142         addParametersToURI(uri);
     230        addParametersToURI(uriBuilder);
    143231
    144232        // extraRequestData
     
    146234            for (Map.Entry<String, String> entry :
    147235                extraRequestData.entrySet()) {
    148                 uri.append('&').append(entry.getKey()).append('=')
    149                         .append(entry.getValue());
    150             }
    151         }
    152         return URI.create(uri.toString());
     236                String key = entry.getKey();
     237                if (key.equals(X_MALFORMED_OPERATION) ||
     238                        key.equals(X_MALFORMED_VERSION)) {
     239                    continue;
     240                }
     241                uriBuilder.append(key, entry.getValue());
     242            }
     243        }
     244        return uriBuilder.makeURI();
    153245    }
    154246
     
    157249
    158250
    159     protected abstract void addParametersToURI(StringBuilder uri)
     251    protected abstract void addParametersToURI(URIBuilder uri)
    160252            throws SRUClientException;
    161253
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUClient.java

    r2022 r2024  
    1313
    1414import javax.xml.stream.XMLStreamException;
     15import javax.xml.stream.XMLStreamReader;
    1516
    1617import org.apache.commons.lang.NullArgumentException;
     
    2425import org.apache.http.impl.client.DefaultHttpClient;
    2526import org.apache.http.params.CoreProtocolPNames;
     27import org.apache.http.util.EntityUtils;
    2628import org.slf4j.Logger;
    2729import org.slf4j.LoggerFactory;
     
    282284
    283285    private HttpResponse executeRequest(URI uri) throws SRUClientException {
     286        HttpGet request = null;
     287        HttpResponse response = null;
    284288        try {
    285289            logger.debug("executing HTTP request: {}", uri.toString());
    286             HttpGet request = new HttpGet(uri);
    287             HttpResponse response = httpClient.execute(request);
    288             StatusLine status = response.getStatusLine();
    289             if (status.getStatusCode() != HttpStatus.SC_OK) {
    290                 if (status.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
    291                     throw new SRUClientException("not found: " + uri);
    292                 } else {
    293                     throw new SRUClientException("unexpected status: " +
    294                             status.getStatusCode());
    295                 }
    296             }
    297             return response;
    298         } catch (ClientProtocolException e) {
    299             throw new SRUClientException("client protocol exception", e);
    300         } catch (UnknownHostException e) {
    301             throw new SRUClientException("unknown host: " + uri.getHost(), e);
    302         } catch (IOException e) {
    303             throw new SRUClientException("input/output error", e);
    304         }
    305     }
    306 
    307 
    308     private void parseExplainResponse(SRUXMLStreamReader reader,
    309             SRUExplainRequest request, SRUExplainHandler handler)
     290            try {
     291                request = new HttpGet(uri);
     292                response = httpClient.execute(request);
     293                StatusLine status = response.getStatusLine();
     294                if (status.getStatusCode() != HttpStatus.SC_OK) {
     295                    if (status.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
     296                        throw new SRUClientException("not found: " + uri);
     297                    } else {
     298                        throw new SRUClientException("unexpected status: " +
     299                                status.getStatusCode());
     300                    }
     301                }
     302                return response;
     303            } catch (ClientProtocolException e) {
     304                throw new SRUClientException("client protocol exception", e);
     305            } catch (UnknownHostException e) {
     306                throw new SRUClientException("unknown host: " + uri.getHost(),
     307                        e);
     308            } catch (IOException e) {
     309                throw new SRUClientException("input/output error", e);
     310            }
     311        } catch (SRUClientException e) {
     312            /*
     313             * if an error occurred, make sure we are freeing up the resources
     314             * we've used
     315             */
     316            if (response != null) {
     317                try {
     318                    EntityUtils.consume(response.getEntity());
     319                } catch (IOException ex) {
     320                    /* IGNORE */
     321                }
     322            }
     323            if (request != null) {
     324                request.abort();
     325            }
     326            throw e;
     327        }
     328    }
     329
     330
     331    private void parseExplainResponse(final SRUXMLStreamReader reader,
     332            final SRUAbstractRequest request, final SRUExplainHandler handler)
    310333            throws SRUClientException {
    311334        logger.debug("parsing 'explain' response");
     
    317340            SRUVersion version = parseVersion(reader);
    318341            logger.debug("version = {}, requested = {}",
    319                     version, this.defaultVersion);
     342                    version, request.getVersionPerformed());
    320343
    321344            // explainResponse/record
     
    376399
    377400
    378     private void parseScanResponse(SRUXMLStreamReader reader,
    379             SRUScanRequest request, SRUScanHandler handler)
     401    private void parseScanResponse(final SRUXMLStreamReader reader,
     402            final SRUScanRequest request, final SRUScanHandler handler)
    380403            throws SRUClientException {
    381         logger.debug("parsing 'scanResponse' response");
    382404        try {
    383             // scanResponse
    384             reader.readStart(SRU_NS, "scanResponse", true);
    385 
    386             // scanResponse/version
    387             SRUVersion version = parseVersion(reader);
    388             logger.debug("version = {}, requested = {}",
    389                     version, this.defaultVersion);
    390 
    391             // scanResponse/terms
    392             if (reader.readStart(SRU_NS, "terms", false)) {
    393                 boolean first = true;
    394                 while (reader.readStart(SRU_NS, "term", first)) {
    395                     if (first) {
    396                         first = false;
    397                         handler.onStartTerms();
     405            /*
     406             * if the endpoint cannot determine the operation, it should create
     407             * a explain response.
     408             */
     409            if (reader.peekStart(SRU_NS, "explainResponse")) {
     410                parseExplainResponse(reader, request, new SRUExplainHandler() {
     411                    @Override
     412                    public void onRequestStatistics(int bytes, long millisTotal,
     413                            long millisNetwork, long millisParsing) {
    398414                    }
    399415
    400                     // scanResponse/terms/value
    401                     String value = reader.readContent(SRU_NS, "value", true);
    402 
    403                     // scanResponse/terms/numberOfRecords
    404                     int numberOfRecords = reader.readContent(SRU_NS,
    405                             "numberOfRecords", false, -1);
    406 
    407                     // scanResponse/terms/displayTerm
    408                     String displayTerm = reader.readContent(SRU_NS,
    409                             "displayTerm", false);
    410 
    411                     // scanResponse/terms/whereInList
    412                     String s = reader.readContent(SRU_NS, "whereInList", false);
    413                     WhereInList whereInList = null;
    414                     if (s != null) {
    415                         if ("first".equals(s)) {
    416                             whereInList = WhereInList.FIRST;
    417                         } else if ("last".equals(s)) {
    418                             whereInList = WhereInList.LAST;
    419                         } else if ("only".equals(s)) {
    420                             whereInList = WhereInList.ONLY;
    421                         } else if ("inner".equals(s)) {
    422                             whereInList = WhereInList.INNER;
    423                         } else {
    424                             throw new SRUClientException(
    425                                     "invalid value for 'whereInList': " + s);
    426                         }
     416
     417                    @Override
     418                    public void onExtraResponseData(XMLStreamReader reader)
     419                            throws XMLStreamException, SRUClientException {
    427420                    }
    428                     logger.debug("value = {}, numberOfRecords = {}, "
    429                             + "displayTerm = {}, whereInList = {}",
    430                             new Object[] { value, numberOfRecords, displayTerm,
    431                                     whereInList });
    432                     handler.onTerm(value, numberOfRecords,
    433                             displayTerm, whereInList);
    434 
    435                     // scanResponse/terms/extraTermData
    436                     if (reader.readStart(SRU_NS, "extraTermData", first)) {
    437                         reader.consumeWhitespace();
    438                         proxy.reset(reader);
    439                         try {
    440                             handler.onExtraTermData(value, proxy);
    441                         } catch (XMLStreamException e) {
    442                             throw new SRUClientException("handler "
    443                                     + "triggered error while parsing "
    444                                     + "'extraTermData'", e);
    445                         }
    446                         reader.consumeWhitespace();
    447                         reader.readEnd(SRU_NS, "extraTermData", true);
     421
     422
     423                    @Override
     424                    public void onDiagnostics(List<SRUDiagnostic> diagnostics)
     425                            throws SRUClientException {
     426                        handler.onDiagnostics(diagnostics);
    448427                    }
    449                     reader.readEnd(SRU_NS, "term", true);
    450 
    451                 } // while
    452                 reader.readEnd(SRU_NS, "terms");
    453                 handler.onFinishTerms();
    454             }
    455 
    456             // scanResponse/echoedScanRequest
    457             if (reader.readStart(SRU_NS, "echoedScanRequest", false)) {
    458                 reader.readEnd(SRU_NS, "echoedScanRequest", true);
    459             }
    460 
    461             // scanResponse/diagnostics
    462             final List<SRUDiagnostic> diagnostics = parseDiagnostics(reader);
    463             if (diagnostics != null) {
    464                 handler.onDiagnostics(diagnostics);
    465             }
    466 
    467             // scanResponse/extraResponseData
    468             if (reader.readStart(SRU_NS, "extraResponseData", false)) {
    469                 reader.consumeWhitespace();
    470                 proxy.reset(reader);
    471                 try {
    472                     handler.onExtraResponseData(proxy);
    473                 } catch (XMLStreamException e) {
    474                     throw new SRUClientException("handler triggered "
    475                             + "error while parsing 'extraResponseData'", e);
    476                 }
    477                 reader.consumeWhitespace();
    478                 reader.readEnd(SRU_NS, "extraResponseData", true);
    479             }
    480 
    481             reader.readEnd(SRU_NS, "scanResponse");
     428                });
     429            } else {
     430                logger.debug("parsing 'scanResponse' response");
     431
     432                // scanResponse
     433                reader.readStart(SRU_NS, "scanResponse", true);
     434
     435                // scanResponse/version
     436                SRUVersion version = parseVersion(reader);
     437                logger.debug("version = {}, requested = {}", version,
     438                        request.getVersionPerformed());
     439
     440                // scanResponse/terms
     441                if (reader.readStart(SRU_NS, "terms", false)) {
     442                    boolean first = true;
     443                    while (reader.readStart(SRU_NS, "term", first)) {
     444                        if (first) {
     445                            first = false;
     446                            handler.onStartTerms();
     447                        }
     448
     449                        // scanResponse/terms/value
     450                        String value = reader
     451                                .readContent(SRU_NS, "value", true);
     452
     453                        // scanResponse/terms/numberOfRecords
     454                        int numberOfRecords = reader.readContent(SRU_NS,
     455                                "numberOfRecords", false, -1);
     456
     457                        // scanResponse/terms/displayTerm
     458                        String displayTerm = reader.readContent(SRU_NS,
     459                                "displayTerm", false);
     460
     461                        // scanResponse/terms/whereInList
     462                        String s = reader.readContent(SRU_NS,
     463                                "whereInList", false);
     464                        WhereInList whereInList = null;
     465                        if (s != null) {
     466                            if ("first".equals(s)) {
     467                                whereInList = WhereInList.FIRST;
     468                            } else if ("last".equals(s)) {
     469                                whereInList = WhereInList.LAST;
     470                            } else if ("only".equals(s)) {
     471                                whereInList = WhereInList.ONLY;
     472                            } else if ("inner".equals(s)) {
     473                                whereInList = WhereInList.INNER;
     474                            } else {
     475                                throw new SRUClientException(
     476                                        "invalid value for 'whereInList': " + s);
     477                            }
     478                        }
     479                        logger.debug("value = {}, numberOfRecords = {}, "
     480                                + "displayTerm = {}, whereInList = {}",
     481                                new Object[] { value, numberOfRecords,
     482                                        displayTerm, whereInList });
     483                        handler.onTerm(value, numberOfRecords, displayTerm,
     484                                whereInList);
     485
     486                        // scanResponse/terms/extraTermData
     487                        if (reader.readStart(SRU_NS, "extraTermData", first)) {
     488                            reader.consumeWhitespace();
     489                            proxy.reset(reader);
     490                            try {
     491                                handler.onExtraTermData(value, proxy);
     492                            } catch (XMLStreamException e) {
     493                                throw new SRUClientException("handler "
     494                                        + "triggered error while parsing "
     495                                        + "'extraTermData'", e);
     496                            }
     497                            reader.consumeWhitespace();
     498                            reader.readEnd(SRU_NS, "extraTermData", true);
     499                        }
     500                        reader.readEnd(SRU_NS, "term", true);
     501
     502                    } // while
     503                    reader.readEnd(SRU_NS, "terms");
     504                    handler.onFinishTerms();
     505                }
     506
     507                // scanResponse/echoedScanRequest
     508                if (reader.readStart(SRU_NS, "echoedScanRequest", false)) {
     509                    reader.readEnd(SRU_NS, "echoedScanRequest", true);
     510                }
     511
     512                // scanResponse/diagnostics
     513                final List<SRUDiagnostic> diagnostics = parseDiagnostics(reader);
     514                if (diagnostics != null) {
     515                    handler.onDiagnostics(diagnostics);
     516                }
     517
     518                // scanResponse/extraResponseData
     519                if (reader.readStart(SRU_NS, "extraResponseData", false)) {
     520                    reader.consumeWhitespace();
     521                    proxy.reset(reader);
     522                    try {
     523                        handler.onExtraResponseData(proxy);
     524                    } catch (XMLStreamException e) {
     525                        throw new SRUClientException("handler triggered "
     526                                + "error while parsing 'extraResponseData'", e);
     527                    }
     528                    reader.consumeWhitespace();
     529                    reader.readEnd(SRU_NS, "extraResponseData", true);
     530                }
     531
     532                reader.readEnd(SRU_NS, "scanResponse");
     533            }
    482534        } catch (XMLStreamException e) {
    483535            throw new SRUClientException(e.getMessage(), e);
     
    486538
    487539
    488     private void parseSearchRetrieveResponse(SRUXMLStreamReader reader,
    489             SRUSearchRetrieveRequest request, SRUSearchRetrieveHandler handler)
    490             throws SRUClientException {
    491         logger.debug("parsing 'serarchRetrieve' response");
     540    private void parseSearchRetrieveResponse(final SRUXMLStreamReader reader,
     541            final SRUSearchRetrieveRequest request,
     542            final SRUSearchRetrieveHandler handler) throws SRUClientException {
    492543        try {
    493             // searchRetrieveResponse
    494             reader.readStart(SRU_NS, "searchRetrieveResponse", true);
    495 
    496             // searchRetrieveResponse/version
    497             SRUVersion version = parseVersion(reader);
    498             logger.debug("version = {}, requested = {}",
    499                     version, this.defaultVersion);
    500 
    501             // searchRetrieveResponse/numberOfRecords
    502             int numberOfRecords = reader.readContent(SRU_NS,
    503                     "numberOfRecords", true, -1);
    504 
    505             // searchRetrieveResponse/resultSetId
    506             int resultSetId = reader.readContent(SRU_NS,
    507                     "resultSetId", false, -1);
    508 
    509             // searchRetrieveResponse/resultSetIdleTime
    510             int resultSetIdleTime = reader.readContent(SRU_NS,
    511                     "resultSetIdleTime", false, -1);
    512 
    513             logger.debug("numberOfRecords = {}, resultSetId = {}, "
    514                     + "resultSetIdleTime = {}", new Object[] {
    515                                                     numberOfRecords,
    516                                                     resultSetId,
    517                                                     resultSetIdleTime
    518                                                 });
    519 
    520             // searchRetrieveResponse/results
    521             if (numberOfRecords > 0) {
    522                 reader.readStart(SRU_NS, "records", true);
    523 
    524                 // searchRetrieveResponse/records/record
    525                 boolean first = true;
    526                 while (reader.readStart(SRU_NS, "record", first)) {
    527                     if (first) {
    528                         first = false;
    529                         handler.onStartRecords(numberOfRecords,
    530                                 resultSetId, resultSetIdleTime);
     544            /*
     545             * if the endpoint cannot determine the operation, it should create
     546             * a explain response.
     547             */
     548            if (reader.peekStart(SRU_NS, "explainResponse")) {
     549                parseExplainResponse(reader, request, new SRUExplainHandler() {
     550                    @Override
     551                    public void onRequestStatistics(int bytes, long millisTotal,
     552                            long millisNetwork, long millisParsing) {
    531553                    }
    532554
    533                     String schema = reader.readContent(SRU_NS,
    534                             "recordSchema", true);
    535 
    536                     SRURecordPacking packing = parseRecordPacking(reader);
    537 
    538                     logger.debug("schema = {}, packing = {}, requested packing = {}",
    539                             new Object[] { schema, packing,
    540                                     request.getRecordPacking() });
    541 
    542                     if ((request.getRecordPacking() != null) &&
    543                             (packing != request.getRecordPacking())) {
    544                         logger.warn("requested '{}' record packing, but server responded with '{}' record packing",
    545                                 request.getRecordPacking().toProtocolString(),
    546                                 packing.toProtocolString());
    547                         // XXX: only throw if client is pedantic?
    548                         throw new SRUClientException(
    549                                 "requested '" +
    550                                         request.getRecordPacking()
    551                                                 .toProtocolString() +
    552                                         "' record packing, but server responded with '" +
    553                                         packing.toProtocolString() +
    554                                         "' record packing");
     555
     556                    @Override
     557                    public void onExtraResponseData(XMLStreamReader reader)
     558                            throws XMLStreamException, SRUClientException {
    555559                    }
    556560
    557                     // searchRetrieveResponse/record/recordData
    558                     reader.readStart(SRU_NS, "recordData", true);
     561
     562                    @Override
     563                    public void onDiagnostics(List<SRUDiagnostic> diagnostics)
     564                            throws SRUClientException {
     565                        handler.onDiagnostics(diagnostics);
     566                    }
     567                });
     568            } else {
     569                logger.debug("parsing 'serarchRetrieve' response");
     570
     571                // searchRetrieveResponse
     572                reader.readStart(SRU_NS, "searchRetrieveResponse", true);
     573
     574                // searchRetrieveResponse/version
     575                SRUVersion version = parseVersion(reader);
     576                logger.debug("version = {}, requested = {}", version,
     577                        request.getVersionPerformed());
     578
     579                // searchRetrieveResponse/numberOfRecords
     580                int numberOfRecords = reader.readContent(SRU_NS,
     581                        "numberOfRecords", true, -1);
     582
     583                // searchRetrieveResponse/resultSetId
     584                int resultSetId = reader.readContent(SRU_NS,
     585                        "resultSetId", false, -1);
     586
     587                // searchRetrieveResponse/resultSetIdleTime
     588                int resultSetIdleTime = reader.readContent(SRU_NS,
     589                        "resultSetIdleTime", false, -1);
     590
     591                logger.debug("numberOfRecords = {}, resultSetId = {}, "
     592                        + "resultSetIdleTime = {}", new Object[] {
     593                        numberOfRecords, resultSetId, resultSetIdleTime });
     594
     595                // searchRetrieveResponse/results
     596                if (numberOfRecords > 0) {
     597                    reader.readStart(SRU_NS, "records", true);
     598
     599                    // searchRetrieveResponse/records/record
     600                    boolean first = true;
     601                    while (reader.readStart(SRU_NS, "record", first)) {
     602                        if (first) {
     603                            first = false;
     604                            handler.onStartRecords(numberOfRecords,
     605                                    resultSetId, resultSetIdleTime);
     606                        }
     607
     608                        String schema = reader.readContent(SRU_NS,
     609                                "recordSchema", true);
     610
     611                        SRURecordPacking packing = parseRecordPacking(reader);
     612
     613                        logger.debug("schema = {}, packing = {}, requested packing = {}",
     614                                new Object[] { schema, packing,
     615                                        request.getRecordPacking() });
     616
     617                        if ((request.getRecordPacking() != null) &&
     618                                (packing != request.getRecordPacking())) {
     619                            logger.warn("requested '{}' record packing, but server responded with '{}' record packing",
     620                                    request.getRecordPacking()
     621                                            .toProtocolString(), packing
     622                                            .toProtocolString());
     623                            // XXX: only throw if client is pedantic?
     624                            throw new SRUClientException(
     625                                    "requested '" +
     626                                            request.getRecordPacking()
     627                                                    .toProtocolString() +
     628                                            "' record packing, but server responded with '" +
     629                                            packing.toProtocolString() +
     630                                            "' record packing");
     631                        }
     632
     633                        // searchRetrieveResponse/record/recordData
     634                        reader.readStart(SRU_NS, "recordData", true);
     635                        reader.consumeWhitespace();
     636
     637                        SRURecordData recordData = null;
     638                        SRUDiagnostic surrogate = null;
     639                        SRUXMLStreamReader recordReader = null;
     640
     641                        if (packing == SRURecordPacking.STRING) {
     642                            /*
     643                             * read content into temporary buffer and then use
     644                             * a new XML reader to parse record data
     645                             */
     646                            final String data = reader.readString(true);
     647                            InputStream in =
     648                                    new ByteArrayInputStream(data.getBytes());
     649                            // FIXME: namespace context?
     650                            recordReader = createReader(in, false);
     651                        } else {
     652                            recordReader = reader;
     653                        }
     654
     655                        if (SRU_DIAGNOSTIC_RECORD_SCHEMA.equals(schema)) {
     656                            surrogate = parseDiagnostic(recordReader, true);
     657                        } else {
     658                            SRURecordDataParser parser = parsers.get(schema);
     659                            if (parser != null) {
     660                                try {
     661                                    proxy.reset(recordReader);
     662                                    recordData = parser.parse(proxy);
     663                                } catch (XMLStreamException e) {
     664                                    throw new SRUClientException(
     665                                            "error parsing record", e);
     666                                }
     667                            } else {
     668                                // FIXME: handle this better?
     669                                logger.debug("no record parser found for schema '{}'",
     670                                        schema);
     671                            }
     672                        }
     673
     674                        if (packing == SRURecordPacking.STRING) {
     675                            recordReader.closeCompletly();
     676                        }
     677
     678                        reader.consumeWhitespace();
     679                        reader.readEnd(SRU_NS, "recordData", true);
     680
     681                        String identifier = null;
     682                        if (version == SRUVersion.VERSION_1_2) {
     683                            identifier = reader.readContent(SRU_NS,
     684                                    "recordIdentifier", false);
     685                        }
     686
     687                        int position = reader.readContent(SRU_NS,
     688                                "recordPosition", false, -1);
     689
     690                        logger.debug("recordIdentifier = {}, recordPosition = {}",
     691                                identifier, position);
     692
     693                        // notify handler
     694                        if (surrogate != null) {
     695                            handler.onSurrogateRecord(identifier,
     696                                    position, surrogate);
     697                        } else {
     698                            if (recordData != null) {
     699                                handler.onRecord(identifier,
     700                                        position, recordData);
     701                            }
     702                        }
     703
     704                        if (reader.readStart(SRU_NS, "extraRecordData", false)) {
     705                            reader.consumeWhitespace();
     706                            proxy.reset(reader);
     707                            try {
     708                                handler.onExtraRecordData(identifier,
     709                                        position, proxy);
     710                            } catch (XMLStreamException e) {
     711                                throw new SRUClientException("handler "
     712                                        + "triggered error while parsing "
     713                                        + "'extraRecordData'", e);
     714                            }
     715                            reader.consumeWhitespace();
     716                            reader.readEnd(SRU_NS, "extraRecordData", true);
     717                        }
     718
     719                        reader.readEnd(SRU_NS, "record");
     720                    } // while
     721                    reader.readEnd(SRU_NS, "records");
     722                }
     723
     724                int nextRecordPosition = reader.readContent(SRU_NS,
     725                        "nextRecordPosition", false, -1);
     726                logger.debug("nextRecordPosition = {}", nextRecordPosition);
     727                handler.onFinishRecords(nextRecordPosition);
     728
     729                // searchRetrieveResponse/echoedSearchRetrieveResponse
     730                if (reader.readStart(SRU_NS,
     731                        "echoedSearchRetrieveRequest", false)) {
     732                    reader.readEnd(SRU_NS, "echoedSearchRetrieveRequest", true);
     733                }
     734
     735                // searchRetrieveResponse/diagnostics
     736                final List<SRUDiagnostic> diagnostics = parseDiagnostics(reader);
     737                if (diagnostics != null) {
     738                    handler.onDiagnostics(diagnostics);
     739                }
     740
     741                // explainResponse/extraResponseData
     742                if (reader.readStart(SRU_NS, "extraResponseData", false)) {
    559743                    reader.consumeWhitespace();
    560 
    561                     SRURecordData recordData = null;
    562                     SRUDiagnostic surrogate = null;
    563                     SRUXMLStreamReader recordReader = null;
    564 
    565                     if (packing == SRURecordPacking.STRING) {
    566                         /*
    567                          * read content into temporary buffer and then use a new
    568                          * XML reader to parse record data
    569                          */
    570                         final String data = reader.readString(true);
    571                         InputStream in = new ByteArrayInputStream(
    572                                 data.getBytes());
    573                         // FIXME: namespace context?
    574                         recordReader = createReader(in, false);
    575                     } else {
    576                         recordReader = reader;
     744                    proxy.reset(reader);
     745                    try {
     746                        handler.onExtraResponseData(proxy);
     747                    } catch (XMLStreamException e) {
     748                        throw new SRUClientException("handler triggered "
     749                                + "error while parsing 'extraResponseData'", e);
    577750                    }
    578 
    579                     if (SRU_DIAGNOSTIC_RECORD_SCHEMA.equals(schema)) {
    580                         surrogate = parseDiagnostic(recordReader, true);
    581                     } else {
    582                         SRURecordDataParser parser = parsers.get(schema);
    583                         if (parser != null) {
    584                             try {
    585                                 proxy.reset(recordReader);
    586                                 recordData = parser.parse(proxy);
    587                             } catch (XMLStreamException e) {
    588                                 throw new SRUClientException(
    589                                         "error parsing record", e);
    590                             }
    591                         } else {
    592                             // FIXME: handle this better?
    593                             logger.debug(
    594                                     "no record parser found for schema '{}'",
    595                                     schema);
    596                         }
    597                     }
    598 
    599                     if (packing == SRURecordPacking.STRING) {
    600                         recordReader.closeCompletly();
    601                     }
    602 
    603751                    reader.consumeWhitespace();
    604                     reader.readEnd(SRU_NS, "recordData", true);
    605 
    606                     String identifier = null;
    607                     if (version == SRUVersion.VERSION_1_2) {
    608                         identifier = reader.readContent(SRU_NS,
    609                                 "recordIdentifier", false);
    610                     }
    611 
    612                     int position = reader.readContent(SRU_NS, "recordPosition",
    613                             false, -1);
    614 
    615                     logger.debug("recordIdentifier = {}, recordPosition = {}",
    616                             identifier, position);
    617 
    618                     // notify handler
    619                     if (surrogate != null) {
    620                         handler.onSurrogateRecord(identifier, position,
    621                                 surrogate);
    622                     } else {
    623                         if (recordData != null) {
    624                             handler.onRecord(identifier, position, recordData);
    625                         }
    626                     }
    627 
    628                     if (reader.readStart(SRU_NS, "extraRecordData", false)) {
    629                         reader.consumeWhitespace();
    630                         proxy.reset(reader);
    631                         try {
    632                             handler.onExtraRecordData(identifier, position,
    633                                     proxy);
    634                         } catch (XMLStreamException e) {
    635                             throw new SRUClientException("handler "
    636                                     + "triggered error while parsing "
    637                                     + "'extraRecordData'", e);
    638                         }
    639                         reader.consumeWhitespace();
    640                         reader.readEnd(SRU_NS, "extraRecordData", true);
    641                     }
    642 
    643                     reader.readEnd(SRU_NS, "record");
    644                 } // while
    645                 reader.readEnd(SRU_NS, "records");
    646             }
    647 
    648             int nextRecordPosition = reader.readContent(SRU_NS,
    649                     "nextRecordPosition", false, -1);
    650             logger.debug("nextRecordPosition = {}", nextRecordPosition);
    651             handler.onFinishRecords(nextRecordPosition);
    652 
    653             // searchRetrieveResponse/echoedSearchRetrieveResponse
    654             if (reader.readStart(SRU_NS, "echoedSearchRetrieveRequest", false)) {
    655                 reader.readEnd(SRU_NS, "echoedSearchRetrieveRequest", true);
    656             }
    657 
    658             // searchRetrieveResponse/diagnostics
    659             final List<SRUDiagnostic> diagnostics = parseDiagnostics(reader);
    660             if (diagnostics != null) {
    661                 handler.onDiagnostics(diagnostics);
    662             }
    663 
    664             // explainResponse/extraResponseData
    665             if (reader.readStart(SRU_NS, "extraResponseData", false)) {
    666                 reader.consumeWhitespace();
    667                 proxy.reset(reader);
    668                 try {
    669                     handler.onExtraResponseData(proxy);
    670                 } catch (XMLStreamException e) {
    671                     throw new SRUClientException("handler triggered "
    672                             + "error while parsing 'extraResponseData'", e);
    673                 }
    674                 reader.consumeWhitespace();
    675                 reader.readEnd(SRU_NS, "extraResponseData", true);
    676             }
    677 
    678             reader.readEnd(SRU_NS, "searchRetrieveResponse");
     752                    reader.readEnd(SRU_NS, "extraResponseData", true);
     753                }
     754
     755                reader.readEnd(SRU_NS, "searchRetrieveResponse");
     756            }
    679757        } catch (XMLStreamException e) {
    680758            throw new SRUClientException(e.getMessage(), e);
     
    701779            SRUXMLStreamReader reader) throws XMLStreamException,
    702780            SRUClientException {
    703         logger.debug("XXX: try diagnostics: {}", reader.dumpState());
    704781        if (reader.readStart(SRU_NS, "diagnostics", false)) {
    705782            List<SRUDiagnostic> diagnostics = null;
     
    745822        }
    746823    }
     824
    747825
    748826    private static SRURecordPacking parseRecordPacking(SRUXMLStreamReader reader)
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRequest.java

    r1971 r2024  
    3030
    3131    @Override
    32     protected void addParametersToURI(StringBuilder uri)
     32    protected void addParametersToURI(URIBuilder uriBuilder)
    3333            throws SRUClientException {
    3434        // recordPacking
    3535        if (recordPacking != null) {
    36             uri.append('&').append(PARAM_RECORD_PACKING).append('=');
    3736            switch (recordPacking) {
    3837            case XML:
    39                 uri.append(RECORD_PACKING_XML);
     38                uriBuilder.append(PARAM_RECORD_PACKING, RECORD_PACKING_XML);
    4039                break;
    4140            case STRING:
    42                 uri.append(RECORD_PACKING_STRING);
     41                uriBuilder.append(PARAM_RECORD_PACKING, RECORD_PACKING_STRING);
    4342                break;
    4443            default:
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUScanRequest.java

    r1971 r2024  
    6161
    6262    @Override
    63     protected void addParametersToURI(StringBuilder uri)
     63    protected void addParametersToURI(URIBuilder uriBuilder)
    6464            throws SRUClientException {
    6565        // scanClause
    66         uri.append('&').append(PARAM_SCAN_CLAUSE)
    67             .append('=').append(scanClause);
    68        
    69         // reponsePosition
     66        uriBuilder.append(PARAM_SCAN_CLAUSE, scanClause);
     67
     68        // responsePosition
    7069        if (responsePosition > -1) {
    71             uri.append('&').append(PARAM_RESPONSE_POSITION)
    72                 .append('=').append(responsePosition);
     70            uriBuilder.append(PARAM_RESPONSE_POSITION, responsePosition);
    7371        }
    74        
     72
    7573        // maximumTerms
    7674        if (maximumTerms > -1) {
    77             uri.append('&').append(PARAM_MAXIMUM_TERMS)
    78                 .append('=').append(maximumTerms);
     75            uriBuilder.append(PARAM_MAXIMUM_TERMS, maximumTerms);
    7976        }
    8077    }
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveRequest.java

    r1971 r2024  
    9797
    9898    @Override
    99     protected void addParametersToURI(StringBuilder uri)
     99    protected void addParametersToURI(URIBuilder uriBuilder)
    100100            throws SRUClientException {
    101101        // query
    102         uri.append('&').append(PARAM_QUERY).append('=').append(query);
    103        
     102        uriBuilder.append(PARAM_QUERY, query);
     103
    104104        // startRecord
    105105        if (startRecord > 0) {
    106             uri.append('&').append(PARAM_START_RECORD)
    107                 .append('=').append(startRecord);
     106            uriBuilder.append(PARAM_START_RECORD, startRecord);
    108107        }
    109        
     108
    110109        // maximumRecords
    111110        if (maximumRecords > -1) {
    112             uri.append('&').append(PARAM_MAXIMUM_RECORDS)
    113                 .append('=').append(maximumRecords);
     111            uriBuilder.append(PARAM_MAXIMUM_RECORDS, maximumRecords);
    114112        }
    115113
    116114        // recordPacking
    117115        if (recordPacking != null) {
    118             uri.append('&').append(PARAM_RECORD_PACKING).append('=');
    119116            switch (recordPacking) {
    120117            case XML:
    121                 uri.append(RECORD_PACKING_XML);
     118                uriBuilder.append(PARAM_RECORD_PACKING, RECORD_PACKING_XML);
    122119                break;
    123120            case STRING:
    124                 uri.append(RECORD_PACKING_STRING);
     121                uriBuilder.append(PARAM_RECORD_PACKING, RECORD_PACKING_STRING);
    125122                break;
    126123            default:
     
    132129        // recordSchema
    133130        if (recordSchema != null) {
    134             uri.append('&').append(PARAM_RECORD_SCHEMA)
    135                 .append('=').append(recordSchema);
     131            uriBuilder.append(PARAM_RECORD_SCHEMA, recordSchema);
    136132        }
    137        
     133
    138134        // resultSetTTL
    139135        if (resultSetTTL > -1) {
    140             uri.append('&').append(PARAM_RESULT_SET_TTL)
    141                 .append('=').append(resultSetTTL);
     136            uriBuilder.append(PARAM_RESULT_SET_TTL, resultSetTTL);
    142137        }
    143138    }
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUXMLStreamReader.java

    r1985 r2024  
    467467        }
    468468        // System.err.println("--> ok @ " + dumpState());
     469    }
     470
     471
     472    boolean peekStart(String namespaceURI, String localName)
     473            throws XMLStreamException {
     474        if (!reader.isEndElement()) {
     475            while (reader.hasNext()) {
     476                // System.err.println("  LOOP: " + dumpState());
     477                if (reader.isWhiteSpace()) {
     478                    reader.next();
     479                    continue;
     480                }
     481                if (reader.isStartElement()) {
     482                    if (namespaceURI.equals(reader.getNamespaceURI()) &&
     483                            localName.equals(reader.getLocalName())) {
     484                        return true;
     485                    } else {
     486                        return false;
     487                    }
     488                }
     489                if (reader.isCharacters() || reader.isEndElement()) {
     490                    break;
     491                }
     492                reader.next();
     493            } // while
     494        }
     495        return false;
    469496    }
    470497
  • SRUClient/trunk/src/main/java/eu/clarin/sru/client/TestClient.java

    r2021 r2024  
    130130                request.setScanClause("cmd.collections");
    131131                request.setMaximumTerms(2);
     132//                request.setExtraRequestData(
     133//                        SRUScanRequest.X_MALFORMED_OPERATION,
     134//                        SRUScanRequest.MALFORMED_OMIT);
     135//                request.setExtraRequestData(
     136//                        SRUAbstractRequest.X_MALFORMED_VERSION,
     137//                        SRUAbstractRequest.MALFORMED_OMIT);
    132138                client.scan(request, handler);
    133139            } catch (SRUClientException e) {
     
    144150                request.setRecordPacking(SRURecordPacking.XML);
    145151                request.setExtraRequestData("x-indent-response", "4");
     152//                request.setExtraRequestData(
     153//                        SRUScanRequest.X_MALFORMED_OPERATION,
     154//                        "invalid");
     155//                request.setExtraRequestData(
     156//                        SRUScanRequest.X_MALFORMED_VERSION,
     157//                        SRUScanRequest.MALFORMED_OMIT);
    146158                client.searchRetrieve(request, handler);
    147159            } catch (SRUClientException e) {
Note: See TracChangeset for help on using the changeset viewer.