Changeset 341


Ignore:
Timestamp:
04/13/10 17:09:41 (14 years ago)
Author:
oschonef
Message:
  • further work on OAI support
    • finish argument processing and error reporting
    • implement basic serialization interface
Location:
VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main
Files:
3 added
7 edited
3 moved

Legend:

Unmodified
Added
Removed
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/OAIErrorCode.java

    r321 r341  
    99        NO_RECORDS_MATCH,
    1010        NO_METADATA_FORMATS,
    11         NO_SET_HIERARCHY
     11        NO_SET_HIERARCHY;
     12       
     13        public static String toXmlString(OAIErrorCode code) {
     14                switch (code) {
     15                case BAD_ARGUMENT:
     16                        return "badArgument";
     17                case BAD_RESUMPTION_TOKEN:
     18                        return "badResumptionToken";
     19                case BAD_VERB:
     20                        return "badVerb";
     21                case CANNOT_DISSERMINATE_FORMAT:
     22                        return "cannotDisserminateFormat";
     23                case ID_DOES_NOT_EXIST:
     24                        return "idDoesNotExist";
     25                case NO_RECORDS_MATCH:
     26                        return "noRecordsMatch";
     27                case NO_METADATA_FORMATS:
     28                        return "noMetadataFormats";
     29                case NO_SET_HIERARCHY:
     30                        return "noSetHierarchy";
     31                default:
     32                        // cannot happen
     33                        throw new InternalError("invalid OAIErrorCode");
     34                }
     35        }
     36
    1237} // enum OAIError
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/OAIProvider.java

    r340 r341  
    11package eu.clarin.cmdi.virtualcollectionregistry.oai;
    22
    3 import java.io.PrintWriter;
    43import java.util.ArrayList;
    54import java.util.List;
    65import java.util.Set;
    76
     7import javax.servlet.http.HttpServletResponse;
     8
    89import org.slf4j.Logger;
    910import org.slf4j.LoggerFactory;
    1011
     12import eu.clarin.cmdi.virtualcollectionregistry.oai.impl.VerbContextImpl;
    1113import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.Argument;
    1214import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.GetRecordVerb;
    1315import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.IdentifyVerb;
    1416import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.Verb;
    15 import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.VerbContext;
    1617
    1718public class OAIProvider {
     
    2021        private static final OAIProvider s_instance = new OAIProvider();
    2122        private final List<Verb> verbs;
    22        
     23
    2324        private OAIProvider() {
    2425                super();
     
    2930
    3031        public void process(VerbContextImpl ctx) throws OAIException {
     32                Verb verb = null;
     33               
    3134                String verbName = ctx.getParameter("verb");
    32                 if (verbName == null) {
    33                         throw new OAIException("missing verb");
    34                 }
    35                 if (ctx.isParameterMultivalued("verb")) {
    36                         throw new OAIException("multiple verb arguments");
     35                if (verbName != null) {
     36                        if (!ctx.isRepeatedParameter("verb")) {
     37                                for (Verb v : verbs) {
     38                                        if (verbName.equals(v.getName())) {
     39                                                verb = v;
     40                                                break;
     41                                        }
     42                                } // for
     43                        } else {
     44                                ctx.addError(OAIErrorCode.BAD_VERB, "OAI verb is repeated");
     45                        }
     46                } else {
     47                        ctx.addError(OAIErrorCode.BAD_VERB, "OAI verb is missing");
    3748                }
    3849
    39                 Verb verb = null;
    40                 for (Verb v : verbs) {
    41                         if (verbName.equals(v.getName())) {
    42                                 verb = v;
    43                                 break;
    44                         }
    45                 } // for
     50                if (verb != null) {
     51                        // set verb
     52                        ctx.setVerb(verbName);
    4653
    47                 if (verb != null) {
     54                        // process arguments
    4855                        Set<String> remaining = ctx.getParameterNames();
    4956                        for (Argument arg : verb.getArguments()) {
     
    5158                                if ((value == null) && arg.isRequired()) {
    5259                                        ctx.addError(OAIErrorCode.BAD_ARGUMENT,
    53                                                                         "OAI verb '" + verbName +
    54                                         "' requires argument '" +
    55                                         arg.getName() + "'");
     60                                                                 "OAI verb '" + verbName +
     61                                     "' is missing required argument '" +
     62                                     arg.getName() + "'");
    5663                                } else {
    5764                                        remaining.remove(arg.getName());
    58                                         if (ctx.isParameterMultivalued(arg.getName())) {
     65                                        if (ctx.isRepeatedParameter(arg.getName())) {
    5966                                                ctx.addError(OAIErrorCode.BAD_ARGUMENT,
    60                                                                 "OAI verb '" + verbName +
    61                                                                 "' illegally has multiple values for " +
    62                                                                 "argument '" + arg.getName() + "'");
     67                                                                         "OAI verb '" + verbName +
     68                                                                         "' has repeated values for argument '" +
     69                                                                        arg.getName() + "'");
    6370                                        } else {
    64                                                 logger.debug("key: {}, value: {}",
    65                                                                          arg.getName(), value);
    66                                                 try {
    67                                                         arg.validateArgument(value);
     71                                                if (arg.validateArgument(value)) {
    6872                                                        ctx.setArgument(arg.getName(), value);
    69                                                 } catch (OAIException e) {
     73                                                } else {
    7074                                                        ctx.addError(OAIErrorCode.BAD_ARGUMENT,
    71                                                                         "Value of argument '" +
    72                                                                         arg.getName() + "' of OAI verb '" +
    73                                                                         verbName + "' is invalid: " +
    74                                                                         e.getMessage());
     75                                                                                 "Value of argument '" +
     76                                                                                 arg.getName() + "' of OAI verb '" +
     77                                                                                 verbName + "' is invalid");
    7578                                                }
    7679                                        }
    7780                                }
    78                         } // for
     81                        }  // for
    7982
    80                         if (!remaining.isEmpty()) {
     83                        if (remaining.isEmpty()) {
     84                                logger.debug("processing verb '{}'", verb.getName());
     85                                verb.process(ctx);
     86                        } else {
    8187                                for (String key : remaining) {
    8288                                        ctx.addError(OAIErrorCode.BAD_ARGUMENT,
    83                                                                  "superfluous argument '" + key + "'");
     89                                                                 "OAI verb '" + verbName + "' was submitted " +
     90                                                                 "with illegal argument '" + key + "' "+
     91                                                                 "(value='" + ctx.getParameter(key) + "')");
    8492                                }
    85                         } else {
    86                                 logger.debug("processing verb '{}'", verb.getName());
    87                                 verb.process(ctx);
     93                        }
     94                       
     95                        if (ctx.hasErrors()) {
     96                                OAIOutputStream out =
     97                                        ctx.getOutputStream(HttpServletResponse.SC_BAD_REQUEST);
     98                                for (VerbContext.Error error : ctx.getErrors()) {
     99                                        out.writeStartElement("error");
     100                                        out.writeAttribute("code",
     101                                                        OAIErrorCode.toXmlString(error.getCode()));
     102                                        out.writeCharacters(error.getMessage());
     103                                        out.writeEndElement(); // error element
     104                                }
     105                                out.close();
    88106                        }
    89107                } else {
    90108                        ctx.addError(OAIErrorCode.BAD_VERB, "illegal OAI verb '" +
    91109                                        verbName + "'");
    92                 }
    93 
    94                 if (ctx.hasErrors()) {
    95                         PrintWriter out = new PrintWriter(ctx.getWriter());
    96                         out.println("OAI protocol error:");
    97                         // XXX: just testing ...
    98                         logger.error("OAI-CONTEXT: {}", ctx.getRequestURI());
    99                         for (VerbContext.Error error : ctx.getErrors()) {
    100                                 logger.error("OAI-ERROR ({}): {}",
    101                                                          error.getCode(), error.getMessage());
    102                                 out.println(error.getCode() + ": " + error.getMessage());
    103                         }
    104110                }
    105111        }
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/VerbContext.java

    r340 r341  
    1 package eu.clarin.cmdi.virtualcollectionregistry.oai.verb;
     1package eu.clarin.cmdi.virtualcollectionregistry.oai;
    22
    3 import java.io.Writer;
    43import java.util.List;
     4import java.util.Map;
    55
    6 import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIErrorCode;
    7 import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIProvider;
    86
    97public interface VerbContext {
     
    1614        public OAIProvider getProvider();
    1715
     16        public String getVerb();
     17
    1818        public String getArgument(String name);
     19
     20        public Map<String, String> getArguments();
    1921
    2022        public String getRequestURI();
     
    2628        public List<Error> getErrors();
    2729
    28         public Writer getWriter();
     30        public abstract OAIOutputStream getOutputStream()
     31                throws OAIException;
     32
     33        public abstract OAIOutputStream getOutputStream(int status)
     34                throws OAIException;
    2935
    3036} // interface VerbContext
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/impl/OAIProviderServlet.java

    r340 r341  
    1 package eu.clarin.cmdi.virtualcollectionregistry.oai;
     1package eu.clarin.cmdi.virtualcollectionregistry.oai.impl;
    22
    33import java.io.IOException;
    4 import java.io.Writer;
    5 import java.text.SimpleDateFormat;
    6 import java.util.Date;
    7 import java.util.TimeZone;
    84
    95import javax.servlet.ServletException;
     
    117import javax.servlet.http.HttpServletRequest;
    128import javax.servlet.http.HttpServletResponse;
    13 import javax.xml.XMLConstants;
    14 import javax.xml.stream.XMLOutputFactory;
    15 import javax.xml.stream.XMLStreamWriter;
    169
    1710import org.slf4j.Logger;
    1811import org.slf4j.LoggerFactory;
     12
     13import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIProvider;
    1914
    2015public class OAIProviderServlet extends HttpServlet {
     
    2419        private OAIProvider provider;
    2520
    26         private static final String NS_OAI =
    27                 "http://www.openarchives.org/OAI/2.0/";
    28         private static final String NS_OAI_SCHEMA_LOCATION =
    29                 "http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd";
    30        
    3121        @Override
    3222        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
     
    4737        }
    4838
    49         private void handleRequest(HttpServletRequest req, HttpServletResponse resp)
    50                         throws ServletException, IOException {
     39        private void handleRequest(HttpServletRequest request,
     40                                           HttpServletResponse response)
     41                throws ServletException, IOException {
    5142                try {
    52                         resp.setCharacterEncoding("utf-8");
    53                         VerbContextImpl ctx = new VerbContextImpl(provider, req, resp);
     43                        VerbContextImpl ctx =
     44                                new VerbContextImpl(provider, request, response);
    5445                        provider.process(ctx);
    55                 } catch (OAIException e) {
    56                         logger.error("OAI-ERROR: {}", e.getMessage());
    57                         resp.setContentType("application/xml");
    58                         foo(resp.getWriter());
    59                 }
    60         }
    61 
    62         private void foo(Writer writer) throws ServletException {
    63                 try {
    64                         SimpleDateFormat df =
    65                                 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    66                         df.setTimeZone(TimeZone.getTimeZone("UTC"));
    67                        
    68                         XMLOutputFactory factory = XMLOutputFactory.newInstance();
    69                         XMLStreamWriter out = factory.createXMLStreamWriter(writer);
    70                         out.writeStartDocument("utf-8", "1.0");
    71                         out.setDefaultNamespace(NS_OAI);
    72                         out.writeStartElement("OAI-PMH");
    73                         out.writeNamespace("xsi",
    74                                                            XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
    75                         out.writeAttribute(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI,
    76                                                            "schemaLocation",
    77                                                            NS_OAI + " " + NS_OAI_SCHEMA_LOCATION);
    78                         out.writeStartElement("responseDate");
    79                         out.writeCharacters(df.format(new Date()));
    80                         out.writeEndElement();
    81                         out.writeEndElement();
    82                         out.writeEndDocument();
    8346                } catch (Exception e) {
    84                         throw new ServletException("foo failed", e);
     47                        logger.error("OAI provider error", e);
     48                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
     49                                                           "Internal OAI provider error");
    8550                }
    8651        }
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/impl/VerbContextImpl.java

    r340 r341  
    1 package eu.clarin.cmdi.virtualcollectionregistry.oai;
     1package eu.clarin.cmdi.virtualcollectionregistry.oai.impl;
    22
    3 import java.io.IOException;
    4 import java.io.Writer;
    53import java.util.ArrayList;
    64import java.util.Collections;
     
    1513import javax.servlet.http.HttpServletResponse;
    1614
    17 import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.VerbContext;
     15import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIErrorCode;
     16import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIException;
     17import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIOutputStream;
     18import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIProvider;
     19import eu.clarin.cmdi.virtualcollectionregistry.oai.VerbContext;
     20
    1821
    1922public class VerbContextImpl implements VerbContext {
     
    4144        private final HttpServletRequest request;
    4245        private final HttpServletResponse response;
     46        private String verb = null;
    4347        private Map<String, String> arguments = null;
    4448        private List<Error> errors = null;
    4549
    4650        VerbContextImpl(OAIProvider provider,
    47                                     HttpServletRequest request,
    48                                     HttpServletResponse response) {
    49                 super();
     51                                   HttpServletRequest request,
     52                                   HttpServletResponse response) {
    5053                this.provider = provider;
    51                 this.request  = request;
     54                this.request = request;
    5255                this.response = response;
    5356        }
     
    6467        }
    6568
    66         public boolean isParameterMultivalued(String name) {
     69        public boolean isRepeatedParameter(String name) {
    6770                String[] params = request.getParameterValues(name);
    6871                if (params != null) {
     
    8588        }
    8689       
     90        public void setVerb(String verb) {
     91                this.verb = verb;
     92        }
     93
    8794        public void setArgument(String name, String value) {
     95                if ((name == null) || (value == null)) {
     96                        throw new NullPointerException("name == null || value == null");
     97                }
    8898                if (arguments == null) {
    8999                        arguments = new HashMap<String, String>();
    90100                }
    91101                arguments.put(name, value);
     102        }
     103
     104        @Override
     105        public String getVerb() {
     106                return verb;
    92107        }
    93108
     
    103118                        value = arguments.get(name);
    104119                }
    105                 if (value == null) {
    106                         throw new NullPointerException("bad argument: value == null");
     120                return value;
     121        }
     122
     123        @Override
     124        public Map<String, String> getArguments() {
     125                if (arguments == null) {
     126                        return Collections.emptyMap();
    107127                }
    108                 return value;
     128                return Collections.unmodifiableMap(arguments);
    109129        }
    110130
     
    119139        @Override
    120140        public String getRequestURI() {
    121                 // FIXME: supposed to return request uri
    122                 return null;
     141                return request.getRequestURL().toString();
    123142        }
    124143
     
    137156
    138157        @Override
    139         public Writer getWriter() {
    140                 // FIXME: this is for testing only, need to be re-factored
     158        public OAIOutputStream getOutputStream() throws OAIException {
     159                return this.getOutputStream(HttpServletResponse.SC_OK);
     160        }
     161
     162        @Override
     163        public OAIOutputStream getOutputStream(int status) throws OAIException {
    141164                try {
     165                        response.setStatus(status);
    142166                        response.setCharacterEncoding("utf-8");
    143                         response.setContentType("text/plain");
    144                         response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    145                         return response.getWriter();
    146                 } catch (IOException e) {
     167                        response.setContentType("text/xml");
     168                        return new OAIOutputStreamImpl(this, response.getOutputStream());
     169                } catch (Exception e) {
     170                        throw new OAIException("error creating output stream", e);
    147171                }
    148                 return null;
    149172        }
    150173
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/verb/Argument.java

    r340 r341  
    11package eu.clarin.cmdi.virtualcollectionregistry.oai.verb;
    2 
    3 import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIException;
    4 
    52
    63public class Argument {
     
    4441        }
    4542
    46         public void validateArgument(String value) throws OAIException {
     43        public boolean validateArgument(String value) {
    4744                // XXX: implement validation
     45                return true;
    4846        }
    4947
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/verb/GetRecordVerb.java

    r340 r341  
    22
    33import java.util.Arrays;
     4import java.util.Date;
    45import java.util.List;
    56
     7import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIException;
     8import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIOutputStream;
     9import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIOutputStream.NamespaceDecl;
     10import eu.clarin.cmdi.virtualcollectionregistry.oai.VerbContext;
    611import eu.clarin.cmdi.virtualcollectionregistry.oai.verb.Argument.Name;
    712
    813public class GetRecordVerb extends Verb {
     14        private static final String NS_OAI_DC =
     15                "http://www.openarchives.org/OAI/2.0/oai_dc/";
     16        private static final String NS_OAI_DC_SCHEMA_LOCATION =
     17                "http://www.openarchives.org/OAI/2.0/oai_dc.xsd";
     18        private static final String NS_DC =
     19                "http://purl.org/dc/elements/1.1/";
    920        private static final List<Argument> s_arguments =
    1021                Arrays.asList(new Argument(Name.IDENTIFIER, true),
     
    2233
    2334        @Override
    24         public void process(VerbContext ctx) {
     35        public void process(VerbContext ctx) throws OAIException {
    2536                logger.debug("process GET-RECORD");
     37               
     38                // XXX: testing only ...
     39                OAIOutputStream out = ctx.getOutputStream();
     40                out.writeStartElement("GetRecord");
     41                out.writeStartElement("record");
     42               
     43                out.writeStartElement("header");
     44                out.writeStartElement("identifier");
     45                out.writeCharacters(ctx.getArgument("identifier"));
     46                out.writeEndElement();
     47                out.writeStartElement("datestamp");
     48                out.writeDateAsCharacters(new Date());
     49                out.writeEndElement(); // datestamp element
     50                out.writeEndElement(); // header element
     51
     52                out.writeStartElement("metadata");
     53               
     54                out.writeStartElement(NS_OAI_DC, "dc", Arrays.asList(
     55                                new NamespaceDecl(NS_OAI_DC, "oai_dc", NS_OAI_DC_SCHEMA_LOCATION),
     56                                new NamespaceDecl(NS_DC, "dc")
     57                ));
     58
     59                out.writeStartElement(NS_DC, "title");
     60                out.writeCharacters("Test title");
     61                out.writeEndElement(); // dc:title element
     62                out.writeStartElement(NS_DC, "creator");
     63                out.writeCharacters("Test Creator");
     64                out.writeEndElement(); // dc:creator element
     65
     66                out.writeEndElement(); // oai:dc element
     67
     68                out.writeEndElement(); // metadata element
     69                out.writeEndElement(); // record element
     70                out.writeEndElement(); // GetRecord element
     71                out.close();
    2672        }
    2773
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/verb/IdentifyVerb.java

    r340 r341  
    33import java.util.Collections;
    44import java.util.List;
     5
     6import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIException;
     7import eu.clarin.cmdi.virtualcollectionregistry.oai.VerbContext;
    58
    69public class IdentifyVerb extends Verb {
     
    1720
    1821        @Override
    19         public void process(VerbContext ctx) {
     22        public void process(VerbContext ctx) throws OAIException {
    2023                logger.debug("process IDENTIFY");
    2124        }
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/oai/verb/Verb.java

    r340 r341  
    55import org.slf4j.Logger;
    66import org.slf4j.LoggerFactory;
     7
     8import eu.clarin.cmdi.virtualcollectionregistry.oai.OAIException;
     9import eu.clarin.cmdi.virtualcollectionregistry.oai.VerbContext;
    710
    811public abstract class Verb {
     
    1316        public abstract List<Argument> getArguments();
    1417
    15         public abstract void process(VerbContext ctx);
     18        public abstract void process(VerbContext ctx) throws OAIException;
    1619       
    17 } // abstract class VerbBase
     20} // abstract class Verb
  • VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/webapp/WEB-INF/web.xml

    r320 r341  
    3535    <display-name>Virtual Collection Registry OAI-PMH Provider</display-name>
    3636    <servlet-name>OAI-PMH-Provider</servlet-name>
    37     <servlet-class>eu.clarin.cmdi.virtualcollectionregistry.oai.OAIProviderServlet</servlet-class>
     37    <servlet-class>eu.clarin.cmdi.virtualcollectionregistry.oai.impl.OAIProviderServlet</servlet-class>
    3838    <load-on-startup>2</load-on-startup>
    3939  </servlet>
Note: See TracChangeset for help on using the changeset viewer.