/** * This work was created by participants in the DataONE project, and is * jointly copyrighted by participating institutions in DataONE. For * more information on DataONE, see our web site at http://dataone.org. * * Copyright ${year} * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * $Id$ */ package org.dataone.service.util; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.io.IOUtils; import org.dataone.exceptions.MarshallingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.util.EntityUtils; import org.dataone.service.exceptions.AuthenticationTimeout; import org.dataone.service.exceptions.BaseException; import org.dataone.service.exceptions.IdentifierNotUnique; import org.dataone.service.exceptions.InsufficientResources; import org.dataone.service.exceptions.InvalidCredentials; import org.dataone.service.exceptions.InvalidRequest; import org.dataone.service.exceptions.InvalidSystemMetadata; import org.dataone.service.exceptions.InvalidToken; import org.dataone.service.exceptions.NotAuthorized; import org.dataone.service.exceptions.NotFound; import org.dataone.service.exceptions.NotImplemented; import org.dataone.service.exceptions.ServiceFailure; import org.dataone.service.exceptions.SynchronizationFailed; import org.dataone.service.exceptions.UnsupportedMetadataType; import org.dataone.service.exceptions.UnsupportedType; import org.dataone.service.exceptions.VersionMismatch; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * uniform deserialization of DataONE Exceptions that may be rethrown * * @author waltz, rnahf */ public class ExceptionHandler { protected static Log log = LogFactory.getLog(ExceptionHandler.class); public static InputStream filterErrors(HttpResponse res) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, VersionMismatch, IllegalStateException, IOException, HttpException, SynchronizationFailed { return filterErrors(res,false); } public static InputStream filterErrors(HttpResponse res, boolean allowRedirect) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, VersionMismatch, IllegalStateException, IOException, HttpException, SynchronizationFailed { int code = res.getStatusLine().getStatusCode(); log.info("response httpCode: " + code); // cannot read from an input stream twice. // if (log.isDebugEnabled()) { // log.debug(IOUtils.toString(res.getEntity().getContent())); // } if (code == HttpURLConnection.HTTP_OK) { // fall through } else if (allowRedirect && code == HttpURLConnection.HTTP_SEE_OTHER) { // fall through } else { // error, so throw exception deserializeAndThrowException(res); } return res.getEntity().getContent(); } /** * will filter serialized errors coming from the HEAD request * by deserializing them and putting on the exception thread(?). * Exception state is triggered if http status code is not 200 (OK) * or 204 (NO_CONTENT). Where possible, assembles a dataone exception * from header entries corresponding to the standard base exception parts. * * Because this method functions (like filterErrors) as an adapter method, * returning just the headers from the response, it consumes the entity * contained in the response that is passed in, for proper release of * connection resources. * * @param response - the http response * @return - Header[] from the http response * @throws AuthenticationTimeout * @throws IdentifierNotUnique * @throws InsufficientResources * @throws InvalidCredentials * @throws InvalidRequest * @throws InvalidSystemMetadata * @throws InvalidToken * @throws NotAuthorized * @throws NotFound * @throws NotImplemented * @throws ServiceFailure * @throws UnsupportedMetadataType * @throws UnsupportedQueryType * @throws UnsupportedType * @throws VersionMismatch * @throws IllegalStateException * @throws IOException * @throws HttpException * @throws SynchronizationFailed */ public static Header[] filterErrorsHeader(HttpResponse response, String httpMethod) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, VersionMismatch, IllegalStateException, IOException, HttpException, SynchronizationFailed { try { int code = response.getStatusLine().getStatusCode(); log.info("response httpCode: " + code); if (code != HttpURLConnection.HTTP_OK) { // error, so throw exception if (httpMethod == Constants.HEAD) { deserializeHeadersAndThrowException(code,response.getAllHeaders()); } else { deserializeAndThrowException(response); } } } finally { EntityUtils.consume(response.getEntity()); } return response.getAllHeaders(); } public static void deserializeHeadersAndThrowException(int code, Header[] headers) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, VersionMismatch, IllegalStateException, IOException, HttpException, SynchronizationFailed { Map headersMap = new HashMap(); for (Header header: headers) { if (log.isDebugEnabled()) log.debug(String.format("header: %s = %s", header.getName(), header.getValue() )); headersMap.put(header.getName(), header.getValue()); } if (headersMap.containsKey("DataONE-Exception-Name")) { String d1ExceptionName = headersMap.get("DataONE-Exception-Name"); String detailCode = headersMap.get("DataONE-Exception-DetailCode"); String description = headersMap.get("DataONE-Exception-Description"); String pid = headersMap.get("DataONE-Exception-PID"); d1ExceptionName = d1ExceptionName.replace("org.dataone.service.exceptions.",""); if (d1ExceptionName.equals("AuthenticationTimeout")) { throw new AuthenticationTimeout(detailCode, description, pid, null); } else if (d1ExceptionName.equals("IdentifierNotUnique")) { throw new IdentifierNotUnique(detailCode, description, pid, null); } else if (d1ExceptionName.equals("InsufficientResources")) { throw new InsufficientResources(detailCode, description, pid, null); } else if (d1ExceptionName.equals("InvalidCredentials")) { throw new InvalidCredentials(detailCode, description, pid, null); } else if (d1ExceptionName.equals("InvalidRequest")) { throw new InvalidRequest(detailCode, description, pid, null); } else if (d1ExceptionName.equals("InvalidSystemMetadata")) { throw new InvalidSystemMetadata(detailCode, description, pid, null); } else if (d1ExceptionName.equals("InvalidToken")) { throw new InvalidToken(detailCode, description, pid, null); } else if (d1ExceptionName.equals("NotAuthorized")) { throw new NotAuthorized(detailCode, description, pid, null); } else if (d1ExceptionName.equals("NotFound")) { throw new NotFound(detailCode, description, pid, null); } else if (d1ExceptionName.equals("NotImplemented")) { throw new NotImplemented(detailCode, description, pid, null); } else if (d1ExceptionName.equals("ServiceFailure")) { throw new ServiceFailure(detailCode, description, pid, null); } else if (d1ExceptionName.equals("UnsupportedMetadataType")) { throw new UnsupportedMetadataType(detailCode, description, pid, null); } else if (d1ExceptionName.equals("UnsupportedType")) { throw new UnsupportedType(detailCode, description, pid, null); } else if (d1ExceptionName.equals("SynchronizationFailed")) { throw new SynchronizationFailed(detailCode, description, pid, null); } else if (d1ExceptionName.equals("VersionMismatch")) { throw new VersionMismatch(detailCode, description, pid, null); } else { throw new ServiceFailure(detailCode, "status " + code + ": " + description, pid, null); } } else { throw new ServiceFailure("0000: NON-D1-EXCEPTION", "status: " + code + " response headers: " + ExceptionHandler.serializeHeaderMap(headersMap)); } } /** * * @param headers * @return */ private static String serializeHeaderMap(Map headers) { StringBuffer sb = new StringBuffer(); sb.append("\nheader = value"); for (String key: headers.keySet()) { sb.append("\n" + key + " = " + headers.get(key)); } return sb.toString(); } public static InputStream filterErrors(InputStream is, boolean isException, String contentType) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, VersionMismatch, IllegalStateException, IOException, SynchronizationFailed { if (isException) { deserializeAndThrowException(is, contentType, null, null); } return is; } /** * * @param response * @throws NotFound * @throws InvalidToken * @throws ServiceFailure * @throws NotAuthorized * @throws NotFound * @throws IdentifierNotUnique * @throws UnsupportedType * @throws InsufficientResources * @throws InvalidSystemMetadata * @throws NotImplemented * @throws InvalidCredentials * @throws InvalidRequest * @throws IOException * @throws AuthenticationTimeout * @throws UnsupportedMetadataType * @throws VersionMismatch * @throws HttpException */ public static void deserializeAndThrowException(HttpResponse response) throws NotFound, InvalidToken, ServiceFailure, NotAuthorized, NotFound, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, InvalidCredentials, InvalidRequest, IOException, AuthenticationTimeout, UnsupportedMetadataType, VersionMismatch, HttpException, SynchronizationFailed { // use content-type to determine what format the response is Header[] h = response.getHeaders("content-type"); String contentType = "unset"; if (h.length == 1) { contentType = h[0].getValue(); } else if (h.length > 1) { EntityUtils.consume(response.getEntity()); throw new IOException("Should not get more than one content-type returned"); } Integer statusCode = null; String statusReason = null; InputStream responseStream = null; try { statusCode = new Integer(response.getStatusLine().getStatusCode()); statusReason = response.getStatusLine().getReasonPhrase(); if (response.getEntity() != null) responseStream = response.getEntity().getContent(); } catch (RuntimeException re) { } deserializeAndThrowException(responseStream, contentType, statusCode, statusReason); } /** * Throw the exception that is contained in an HTTP response * * A response from an HTTP call may be determined to have an error. * The reponse is wrapped in an InputStream and its content type is determined. * * @param errorStream * @param contentType * @throws NotFound * @throws InvalidToken * @throws ServiceFailure * @throws NotAuthorized * @throws NotFound * @throws IdentifierNotUnique * @throws UnsupportedType * @throws InsufficientResources * @throws InvalidSystemMetadata * @throws NotImplemented * @throws InvalidCredentials * @throws InvalidRequest * @throws IOException * @throws AuthenticationTimeout * @throws UnsupportedMetadataType * @throws UnsupportedQueryType * @throws VersionMismatch * @throws HttpException */ public static void deserializeAndThrowException(InputStream errorStream, String contentType, Integer statusCode, String reason) throws AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, SynchronizationFailed, VersionMismatch { String defaultMessage = ""; if (contentType == null) { contentType = "unset"; } if (statusCode != null) { defaultMessage = String.valueOf(statusCode) + ": "; } if (reason != null) { defaultMessage = defaultMessage + reason + ": "; } if (contentType.contains("xml")) { try { deserializeXmlAndThrowException(errorStream, defaultMessage); } catch (SAXException e) { deserializeAndThrowServiceFailure(errorStream, e, defaultMessage); } catch (IOException e) { deserializeAndThrowServiceFailure(errorStream, e, defaultMessage); } catch (ParserConfigurationException e) { deserializeAndThrowServiceFailure(errorStream, e, defaultMessage); } } else if (contentType.contains("html")) { deserializeHtmlAndThrowException(errorStream, defaultMessage); } else if (contentType.contains("json")) { deserializeJsonAndThrowException(errorStream, defaultMessage); } else if (contentType.contains("csv")) { deserializeCsvAndThrowException(errorStream, defaultMessage); } else if (contentType.contains("text/plain")) { deserializeTextPlainAndThrowException(errorStream, defaultMessage); } else if (contentType.equals("unset")) { deserializeTextPlainAndThrowException(errorStream, defaultMessage); } else { // attempt the default... deserializeTextPlainAndThrowException(errorStream, defaultMessage); } } /* * Default code is the XML is unreadable for some reason * * @param errorStream * @param e * @throws ServiceFailure * */ private static void deserializeAndThrowServiceFailure(InputStream errorStream, Exception e, String defaultMessage) throws ServiceFailure { TreeMap stackTrace = new TreeMap(); StackTraceElement stackTraceElements[] = e.getStackTrace(); for (int i = 0; i < stackTraceElements.length; ++i) { stackTrace.put(String.valueOf(stackTraceElements[i].getLineNumber()), stackTraceElements[i].toString()); } try { throw new ServiceFailure("-1", defaultMessage + e.getMessage() + "\n" + IOUtils.toString(errorStream), "", stackTrace); } catch (IOException e1) { throw new ServiceFailure("-1", defaultMessage + "errorStream could not be reset/reread" + e1.getMessage(), "", stackTrace); } finally { IOUtils.closeQuietly(errorStream); } } /* * repackage the HTML error as a ServiceFailure with bogus detailCode * * @param errorStream * @throws ServiceFailure * */ private static void deserializeHtmlAndThrowException(InputStream errorStream, String defaultMessage) throws ServiceFailure { try { throw new ServiceFailure("-1", defaultMessage + "parser for deserializing HTML not written yet. Providing message body:\n" + IOUtils.toString(errorStream)); } catch (IOException e1) { throw new ServiceFailure("-1", defaultMessage + "errorStream could not be reset/reread" + e1.getMessage()); } finally { IOUtils.closeQuietly(errorStream); } } /* * repackage the Json error as a ServiceFailure with bogus detailCode * * @param errorStream * @throws ServiceFailure * */ private static void deserializeJsonAndThrowException(InputStream errorStream, String defaultMessage) throws ServiceFailure { try { throw new ServiceFailure("-1", defaultMessage + "parser for deserializing JSON not written yet. Providing message body:\n" + IOUtils.toString(errorStream)); } catch (IOException e1) { throw new ServiceFailure("-1", defaultMessage + "errorStream could not be reset/reread" + e1.getMessage()); } finally { IOUtils.closeQuietly(errorStream); } } /* * repackage the Csv error as a ServiceFailure with bogus detailCode * * @param errorStream * @throws ServiceFailure * */ private static void deserializeCsvAndThrowException(InputStream errorStream, String defaultMessage) throws ServiceFailure { try { throw new ServiceFailure("-1", defaultMessage + "parser for deserializing CSV not written yet. Providing message body:\n" + IOUtils.toString(errorStream)); } catch (IOException e1) { throw new ServiceFailure("-1", defaultMessage + "errorStream could not be reset/reread" + e1.getMessage()); } finally { IOUtils.closeQuietly(errorStream); } } /* * repackage the TextPlain error as a ServiceFailure with bogus detailCode * * @param errorStream * @throws ServiceFailure * */ private static void deserializeTextPlainAndThrowException(InputStream errorStream, String defaultMessage) throws ServiceFailure { try { throw new ServiceFailure("-1", defaultMessage + "Deserializing Text/Plain: Just providing message body:\n" + IOUtils.toString(errorStream) + "\n{EndOfMessage}"); } catch (IOException e1) { throw new ServiceFailure("-1", defaultMessage + "errorStream could not be reset/reread" + e1.getMessage()); } finally { IOUtils.closeQuietly(errorStream); } } /* * Throw the exception returned by the deserializeXml call * @param errorStream * @throws NotFound * @throws ParserConfigurationException * @throws SAXException * @throws IOException * @throws InvalidToken * @throws ServiceFailure * @throws NotAuthorized * @throws NotFound * @throws IdentifierNotUnique * @throws UnsupportedType * @throws InsufficientResources * @throws InvalidSystemMetadata * @throws NotImplemented * @throws InvalidCredentials * @throws InvalidRequest * @throws IOException * @throws AuthenticationTimeout * @throws UnsupportedMetadataType * @throws HttpException * @throws VersionMismatch */ private static void deserializeXmlAndThrowException(InputStream errorStream, String defaultMessage) throws ParserConfigurationException, SAXException, IOException, AuthenticationTimeout, IdentifierNotUnique, InsufficientResources, InvalidCredentials, InvalidRequest, InvalidSystemMetadata, InvalidToken, NotAuthorized, NotFound, NotImplemented, ServiceFailure, UnsupportedMetadataType, UnsupportedType, SynchronizationFailed, VersionMismatch { BaseException be = deserializeXml(errorStream, defaultMessage); if (be instanceof AuthenticationTimeout) { throw (AuthenticationTimeout) be; } else if (be instanceof IdentifierNotUnique) { throw (IdentifierNotUnique) be; } else if (be instanceof InsufficientResources) { throw (InsufficientResources) be; } else if (be instanceof InvalidCredentials) { throw (InvalidCredentials) be; } else if (be instanceof InvalidRequest) { throw (InvalidRequest) be; } else if (be instanceof InvalidSystemMetadata) { throw (InvalidSystemMetadata) be; } else if (be instanceof InvalidToken) { throw (InvalidToken) be; } else if (be instanceof NotAuthorized) { throw (NotAuthorized) be; } else if (be instanceof NotFound) { throw (NotFound) be; } else if (be instanceof NotImplemented) { throw (NotImplemented) be; } else if (be instanceof ServiceFailure) { throw (ServiceFailure) be; } else if (be instanceof UnsupportedMetadataType) { throw (UnsupportedMetadataType) be; } else if (be instanceof UnsupportedType) { throw (UnsupportedType) be; } else if (be instanceof SynchronizationFailed) { throw (SynchronizationFailed) be; } else if (be instanceof VersionMismatch) { throw (VersionMismatch) be; } } /* * deserialize the xml of an errorStream and return the DataONE exception * @param errorStream * @return T * An Exception of the following type: NotFound, * ParserConfigurationException, * SAXException * IOException * InvalidToken * ServiceFailure * NotAuthorized * NotFound * IdentifierNotUnique * UnsupportedType * InsufficientResources * InvalidSystemMetadata * NotImplemented * InvalidCredentials * InvalidRequest * IOException * AuthenticationTimeout * UnsupportedMetadataType * VersionMismatch * HttpException * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ public static BaseException deserializeXml(InputStream errorStream, String defaultMessage) throws ParserConfigurationException, SAXException, IOException { TreeMap trace_information = new TreeMap(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); Document doc; DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.parse(errorStream); Element root = doc.getDocumentElement(); root.normalize(); String detailCode = "-1"; String name = ""; String pid = null; String nodeId = null; if (root.hasAttribute("detailCode")) { detailCode = root.getAttribute("detailCode"); } if (root.hasAttribute("name")) { name = root.getAttribute("name"); } if (root.hasAttribute("pid")) { pid = root.getAttribute("pid"); } if (root.hasAttribute("nodeId")) { nodeId = root.getAttribute("nodeId"); } getTraceValue(root, trace_information); String description = getDescriptionValue(root); // pid can be null if not known or supplied and BaseException works right // detailCode should be -1 if not known or supplied // description should be empty string if not known or not supplied // traceInformation should be empty if not known or not supplied if (name != null & !name.isEmpty()) { if (name.equals("AuthenticationTimeout")) { return new AuthenticationTimeout(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("IdentifierNotUnique")) { return new IdentifierNotUnique(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("InsufficientResources")) { return new InsufficientResources(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("InvalidCredentials")) { return new InvalidCredentials(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("InvalidRequest")) { return new InvalidRequest(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("InvalidSystemMetadata")) { return new InvalidSystemMetadata(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("InvalidToken")) { return new InvalidToken(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("NotAuthorized")) { return new NotAuthorized(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("NotFound")) { return new NotFound(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("NotImplemented")) { return new NotImplemented(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("ServiceFailure")) { return new ServiceFailure(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("UnsupportedMetadataType")) { return new UnsupportedMetadataType(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("UnsupportedType")) { return new UnsupportedType(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("SynchronizationFailed")) { return new SynchronizationFailed(detailCode, description, pid, nodeId, trace_information); } else if (name.equals("VersionMismatch")) { return new VersionMismatch(detailCode, description, pid, nodeId, trace_information); } else { return new ServiceFailure(detailCode, defaultMessage + description, pid, nodeId, trace_information); } } else { return new ServiceFailure(detailCode, defaultMessage + description, pid, nodeId, trace_information); } } /** * Find the description xml element , return the text content of the child * element. * @param e * @return String */ private static String getDescriptionValue(Element e) { String text = ""; NodeList nl = e.getElementsByTagName("description"); if (nl != null && nl.getLength() > 0) { Element el = (Element) nl.item(0); if (el.hasChildNodes() && ((el.getFirstChild().getNodeType() == Element.TEXT_NODE) || el.getFirstChild().getNodeType() == Element.CDATA_SECTION_NODE)) { text = el.getFirstChild().getNodeValue(); } } return text; } /* * populate the provided Trace Information with the trace information in the XML * @param e * @param trace_information */ private static void getTraceValue(Element e, TreeMap trace_information) { String text = ""; NodeList nl = e.getElementsByTagName("traceInformation"); if (nl != null && nl.getLength() > 0) { Element el = (Element) nl.item(0); if (el.hasChildNodes()) { NodeList traceValues = el.getChildNodes(); if (el.hasChildNodes() && ((el.getFirstChild().getNodeType() == Element.TEXT_NODE) || el.getFirstChild().getNodeType() == Element.CDATA_SECTION_NODE)) { trace_information.put(el.getAttribute("key"), el.getFirstChild().getNodeValue()); } } } } /** * return an xml attribute as String * @param e * @param attName * @return String */ private static String getTextAttribute(Element e, String attName) { if (e.hasAttribute(attName)) { String attText = e.getAttribute(attName); return attText; } else { return ""; } } /** * Wrapper for Marshalling method that recasts exceptions * to ServiceFailure; * * @param type * the class of the object to serialize (i.e. * SystemMetadata.class) * @param is * the stream to deserialize from * @throws ServiceFailure */ protected static T deserializeServiceType(Class domainClass, InputStream is) throws ServiceFailure { try { return TypeMarshaller.unmarshalTypeFromStream(domainClass, is); } catch (MarshallingException e) { throw new ServiceFailure("0", "Could not deserialize the " + domainClass.getCanonicalName() + ": " + e.getMessage()); } catch (IOException e) { throw new ServiceFailure("0", "Could not deserialize the " + domainClass.getCanonicalName() + ": " + e.getMessage()); } catch (InstantiationException e) { throw new ServiceFailure("0", "Could not deserialize the " + domainClass.getCanonicalName() + ": " + e.getMessage()); } catch (IllegalAccessException e) { throw new ServiceFailure("0", "Could not deserialize the " + domainClass.getCanonicalName() + ": " + e.getMessage()); } } }