package org.odata4j.exceptions; import java.util.HashMap; import java.util.Map; import javax.ws.rs.core.Response.StatusType; import org.odata4j.core.OError; import org.odata4j.core.Throwables; /** * A static factory to create {@link ODataProducerException} instances. * <p>This factory is used after deserialization of error responses retrieved from an OData * producer; it returns one of the following exceptions based on the HTTP status of the response: * <ul><li>{@link BadRequestException},</li> * <li>{@link ForbiddenException},</li> * <li>{@link MethodNotAllowedException},</li> * <li>{@link NotAcceptableException},</li> * <li>{@link NotAuthorizedException},</li> * <li>{@link NotFoundException},</li> * <li>{@link NotImplementedException},</li> * <li>{@link ServerErrorException},</li> * <li>{@link UnsupportedMediaTypeException}</li></ul> * In case the HTTP status cannot be mapped to a specific sub-class, an unspecific ODataProducerException is thrown.</p> */ public class ODataProducerExceptions { private static ODataProducerExceptions SINGLETON = new ODataProducerExceptions(); private ODataProducerExceptions() {} private Map<Integer, ExceptionFactory<?>> exceptionFactories = null; private void initializeExceptionMap() throws InstantiationException, IllegalAccessException { exceptionFactories = new HashMap<Integer, ExceptionFactory<?>>(); add(new BadRequestException.Factory()); add(new ForbiddenException.Factory()); add(new MethodNotAllowedException.Factory()); add(new NotAcceptableException.Factory()); add(new NotAuthorizedException.Factory()); add(new NotFoundException.Factory()); add(new NotImplementedException.Factory()); add(new ServerErrorException.Factory()); add(new UnsupportedMediaTypeException.Factory()); } private static void ensureThatExceptionFactoryMapIsInitialized() throws InstantiationException, IllegalAccessException { if (SINGLETON.exceptionFactories == null) SINGLETON.initializeExceptionMap(); } /** * Adds an {@link ExceptionFactory} and thus makes the created exception available (and catchable) for OData consumers. * * @param exceptionFactory the exception factory to add */ public static void add(final ExceptionFactory<?> exceptionFactory) { try { ensureThatExceptionFactoryMapIsInitialized(); SINGLETON.exceptionFactories.put(exceptionFactory.getStatusCode(), exceptionFactory); } catch (Exception e) { Throwables.propagate(e); } } /** * Restores this factory to its initial state. */ public static void restore() { try { SINGLETON.initializeExceptionMap(); } catch (Exception e) { Throwables.propagate(e); } } /** * Creates a new {@link ODataProducerException}. * * @param status the HTTP status received in conjunction with this error * @param error the OData error message returned by the producer * @return an instance of {@link ODataProducerException} */ public static ODataProducerException create(final StatusType status, final OError error) { try { ensureThatExceptionFactoryMapIsInitialized(); ExceptionFactory<?> exceptionFactory = SINGLETON.exceptionFactories.get(status.getStatusCode()); if (exceptionFactory != null) return exceptionFactory.createException(error); else return unspecificException(status, error); } catch (Exception e) { Throwables.propagate(e); return null; } } private static ODataProducerException unspecificException(final StatusType status, final OError error) { return new ODataProducerException(error) { private static final long serialVersionUID = 1L; @Override public StatusType getHttpStatus() { return status; } }; } }