Java tutorial
/* * 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 2014 * * 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. * */ package org.dataone.proto.trove.mn.http.client; import java.io.BufferedInputStream; import java.io.IOException; import java.io.StringWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.dataone.proto.trove.net.ErrorElements; import org.dataone.service.exceptions.AuthenticationTimeout; 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.UnsupportedMetadataType; import org.dataone.service.exceptions.UnsupportedType; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * Really good code. * * @author rnafh */ public class HttpExceptionHandler { /** * * @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 HttpException */ public static void deserializeAndThrowException(HttpResponse response) throws NotFound, InvalidToken, ServiceFailure, NotAuthorized, NotFound, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, InvalidCredentials, InvalidRequest, IOException, AuthenticationTimeout, UnsupportedMetadataType, HttpException { // use content-type to determine what format the response is Header[] h = response.getHeaders("content-type"); String contentType = null; if (h.length == 1) { contentType = h[0].getValue(); } else { throw new IOException("Should not get more than one content-type returned"); } ErrorElements ee = null; if (contentType.contains("xml")) { ee = deserializeXml(response); } else if (contentType.contains("html")) { ee = deserializeHtml(response); } else if (contentType.contains("json")) { ee = deserializeJson(response); } else if (contentType.contains("csv")) { ee = deserializeCsv(response); } else if (contentType.contains("text/plain")) { ee = deserializeTextPlain(response); } else // attempt the default... { ee = deserializeXml(response); } String exceptionName = ee.getName(); if (exceptionName == null) { throw new HttpException(response.getStatusLine().getReasonPhrase() + ": " + ee.getDescription()); } // last updated 27-Jan-2011 if (ee.getName().equals("AuthenticationTimeout")) { throw new AuthenticationTimeout(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("IdentifierNotUnique")) { throw new IdentifierNotUnique(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("InsufficientResources")) { throw new InsufficientResources(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("InvalidCredentials")) { throw new InvalidCredentials(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("InvalidRequest")) { throw new InvalidRequest(ee.getDetailCode(), ee.getDescription()); } else if (exceptionName.equals("InvalidSystemMetadata")) { throw new InvalidSystemMetadata("1180", ee.getDescription()); } else if (ee.getName().equals("InvalidToken")) { throw new InvalidToken(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("NotAuthorized")) { throw new NotAuthorized(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("NotFound")) { throw new NotFound(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("NotImplemented")) { throw new NotImplemented(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("ServiceFailure")) { throw new ServiceFailure(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("UnsupportedMetadataType")) { throw new UnsupportedMetadataType(ee.getDetailCode(), ee.getDescription()); } else if (ee.getName().equals("UnsupportedType")) { throw new UnsupportedType(ee.getDetailCode(), ee.getDescription()); } else { throw new ServiceFailure(ee.getDetailCode(), ee.getDescription()); } } private static ErrorElements deserializeHtml(HttpResponse response) throws IllegalStateException, IOException { ErrorElements ee = new ErrorElements(); ee.setCode(response.getStatusLine().getStatusCode()); // ee.setDetailCode(detailCode); if (response.getEntity() != null) { String body = IOUtils.toString(response.getEntity().getContent()); ee.setDescription("parser for deserializing HTML not written yet. Providing message body:\n" + body); } return ee; } private static ErrorElements deserializeJson(HttpResponse response) throws IllegalStateException, IOException { ErrorElements ee = new ErrorElements(); ee.setCode(response.getStatusLine().getStatusCode()); // ee.setDetailCode(detailCode); if (response.getEntity() != null) { String body = IOUtils.toString(response.getEntity().getContent()); ee.setDescription("parser for deserializing JSON not written yet. Providing message body:\n" + body); } return ee; } private static ErrorElements deserializeCsv(HttpResponse response) throws IllegalStateException, IOException { ErrorElements ee = new ErrorElements(); ee.setCode(response.getStatusLine().getStatusCode()); // ee.setDetailCode(detailCode); if (response.getEntity() != null) { String body = IOUtils.toString(response.getEntity().getContent()); ee.setDescription("parser for deserializing CSV not written yet. Providing message body:\n" + body); } return ee; } private static ErrorElements deserializeTextPlain(HttpResponse response) throws IllegalStateException, IOException { ErrorElements ee = new ErrorElements(); ee.setCode(response.getStatusLine().getStatusCode()); // ee.setDetailCode(detailCode); if (response.getEntity() != null) { String body = IOUtils.toString(response.getEntity().getContent()); ee.setDescription("parser for deserializing CSV not written yet. Providing message body:\n" + body); } return ee; } private static ErrorElements deserializeXml(HttpResponse response) throws IllegalStateException, IOException // throws NotFound, InvalidToken, ServiceFailure, NotAuthorized, // NotFound, IdentifierNotUnique, UnsupportedType, // InsufficientResources, InvalidSystemMetadata, NotImplemented, // InvalidCredentials, InvalidRequest, IOException { { ErrorElements ee = new ErrorElements(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); Document doc; int httpCode = response.getStatusLine().getStatusCode(); if (response.getEntity() != null) { BufferedInputStream bErrorStream = new BufferedInputStream(response.getEntity().getContent()); bErrorStream.mark(5000); // good for resetting up to 5000 bytes String detailCode = null; String description = null; String name = null; int errorCode = -1; try { DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.parse(bErrorStream); Element root = doc.getDocumentElement(); root.normalize(); if (root.getNodeName().equalsIgnoreCase("error")) { if (root.hasAttribute("errorCode")) { try { errorCode = Integer.getInteger(root.getAttribute("errorCode")); } catch (NumberFormatException nfe) { System.out.println("errorCode unexpectedly not able to parse to int," + " using http status for creating exception"); errorCode = httpCode; } } if (errorCode != httpCode) // throw new ServiceFailure("1000","errorCode in message body doesn't match httpStatus"); { System.out.println("errorCode in message body doesn't match httpStatus," + " using errorCode for creating exception"); } if (root.hasAttribute("detailCode")) { detailCode = root.getAttribute("detailCode"); } else { detailCode = "detail code is Not Set!"; } if (root.hasAttribute("name")) { name = root.getAttribute("name"); } else { name = "Exception"; } Node child = root.getFirstChild(); do { if (child.getNodeType() == Node.ELEMENT_NODE) { if (child.getNodeName().equalsIgnoreCase("description")) { Element element = (Element) child; description = element.getTextContent(); break; } } } while ((child = child.getNextSibling()) != null); } else { description = domToString(doc); detailCode = "detail code was never Set!"; } } catch (TransformerException e) { description = deserializeNonXMLErrorStream(bErrorStream, e); } catch (SAXException e) { description = deserializeNonXMLErrorStream(bErrorStream, e); } catch (IOException e) { description = deserializeNonXMLErrorStream(bErrorStream, e); } catch (ParserConfigurationException e) { description = deserializeNonXMLErrorStream(bErrorStream, e); } ee.setCode(errorCode); ee.setName(name); ee.setDetailCode(detailCode); ee.setDescription(description); } return ee; } /* * helper method for deserializeAndThrowException. Used for problems parsing errorStream as XML */ private static String deserializeNonXMLErrorStream(BufferedInputStream errorStream, Exception e) { String errorString = null; try { errorStream.reset(); errorString = e.getMessage() + "\n" + IOUtils.toString(errorStream); } catch (IOException e1) { errorString = "errorStream could not be reset/reread"; } return errorString; } private static String domToString(Document document) throws ParserConfigurationException, TransformerConfigurationException, TransformerException { DocumentBuilder documentBuilder = null; Transformer transformer = null; StringWriter strWtr = new StringWriter(); documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //xml, html, text transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); String result = null; if (document != null) { StreamResult strResult = new StreamResult(strWtr); transformer.transform(new DOMSource(document.getDocumentElement()), strResult); result = strResult.getWriter().toString(); } return result; } }