From 0b39b68e4e72cbcf0f4d28488d54ce06117efa9c Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Thu, 1 Mar 2012 19:58:34 -0600 Subject: Added CMSException. The CMSException was added to simplify error handling in REST services. The exception may include an error message and some other attributes. When the server throws a CMSException (or its subclass), the exception will be marshalled into XML and unmarshalled by the client, then thrown again as a new exception which can be caught by the application. Ticket #100 --- .../netscape/cms/servlet/base/CMSException.java | 165 +++++++++++++++++++++ .../cms/servlet/base/CMSResourceService.java | 17 ++- 2 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 base/common/src/com/netscape/cms/servlet/base/CMSException.java (limited to 'base/common/src/com/netscape/cms/servlet/base') diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSException.java b/base/common/src/com/netscape/cms/servlet/base/CMSException.java new file mode 100644 index 000000000..eda5566ac --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/CMSException.java @@ -0,0 +1,165 @@ +package com.netscape.cms.servlet.base; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +public class CMSException extends RuntimeException { + + private static final long serialVersionUID = 6000910362260369923L; + + public int code; + + public CMSException(String message) { + super(message); + code = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); + } + + public CMSException(int code, String message) { + super(message); + this.code = code; + } + + public CMSException(Response.Status status, String message) { + super(message); + code = status.getStatusCode(); + } + + public CMSException(String message, Throwable cause) { + super(message, cause); + code = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); + } + + public CMSException(int code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public CMSException(Response.Status status, String message, Throwable cause) { + super(message, cause); + code = status.getStatusCode(); + } + + public CMSException(Data data) { + super(data.message); + code = data.code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public Data getData() { + Data data = new Data(); + data.className = getClass().getName(); + data.code = code; + data.message = getMessage(); + return data; + } + + @XmlRootElement(name="CMSException") + public static class Data { + + @XmlElement(name="ClassName") + public String className; + + @XmlElement(name="Code") + public int code; + + @XmlElement(name="Message") + public String message; + + @XmlElement(name="Attributes") + @XmlJavaTypeAdapter(MapAdapter.class) + public Map attributes = new LinkedHashMap(); + + public String getAttribute(String name) { + return attributes.get(name); + } + + public void setAttribute(String name, String value) { + attributes.put(name, value); + } + } + + public static class MapAdapter extends XmlAdapter> { + + public AttributeList marshal(Map map) { + AttributeList list = new AttributeList(); + for (Map.Entry entry : map.entrySet()) { + Attribute attribute = new Attribute(); + attribute.name = entry.getKey(); + attribute.value = entry.getValue(); + list.attributes.add(attribute); + } + return list; + } + + public Map unmarshal(AttributeList list) { + Map map = new LinkedHashMap(); + for (Attribute attribute : list.attributes) { + map.put(attribute.name, attribute.value); + } + return map; + } + } + + public static class AttributeList { + @XmlElement(name="Attribute") + public List attributes = new ArrayList(); + } + + public static class Attribute { + + @XmlAttribute + public String name; + + @XmlValue + public String value; + } + + @Provider + public static class Mapper implements ExceptionMapper { + + public Response toResponse(CMSException exception) { + // convert CMSException into HTTP response with XML content + return Response + .status(exception.getCode()) + .entity(exception.getData()) + .type(MediaType.TEXT_XML) + .build(); + } + } + + public static void main(String args[]) throws Exception { + Data data = new Data(); + data.className = CMSException.class.getName(); + data.code = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); + data.message = "An error has occured"; + data.setAttribute("attr1", "value1"); + data.setAttribute("attr2", "value2"); + + JAXBContext context = JAXBContext.newInstance(Data.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.marshal(data, System.out); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java index acddba559..24c3cd74d 100644 --- a/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java +++ b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java @@ -20,9 +20,11 @@ package com.netscape.cms.servlet.base; import java.security.cert.CertificateEncodingException; import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.Context; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Response.ResponseBuilder; import com.netscape.certsrv.apps.CMS; @@ -35,13 +37,24 @@ import com.netscape.cms.servlet.cert.model.CertificateData; * */ public class CMSResourceService { + public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; // caching parameters - protected static final int DEFAULT_LONG_CACHE_LIFETIME = 1000; + public static final int DEFAULT_LONG_CACHE_LIFETIME = 1000; + + @Context + protected UriInfo uriInfo; + + @Context + protected Request request; + + public Response createOKResponse(Object object) { + return Response.ok(object).build(); + } - protected Response sendConditionalGetResponse(int ctime, Object object, Request request) { + public Response sendConditionalGetResponse(int ctime, Object object) { CacheControl cc = new CacheControl(); cc.setMaxAge(ctime); EntityTag tag = new EntityTag(Integer.toString(object.hashCode())); -- cgit