/* * ============================================================================ * * Copyright (C) 2011 - 2013 Talend Inc. - www.talend.com * * This source code is available under agreement available at * %InstallDIR%\license.txt * * You should have received a copy of the agreement * along with this program; if not, write to Talend SA * 9 rue Pages 92150 Suresnes, France * * ============================================================================ */ package org.talend.esb.auxiliary.storage.client.rest; import java.net.ConnectException; import java.util.Properties; import javax.ws.rs.NotFoundException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.ProcessingException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.apache.cxf.jaxrs.client.WebClient; import org.talend.esb.auxiliary.storage.client.common.AuxiliaryStorageClient; import org.talend.esb.auxiliary.storage.common.AuxiliaryObjectFactory; import org.talend.esb.auxiliary.storage.common.exception.ObjectAlreadyExistsException; import org.talend.esb.auxiliary.storage.common.exception.ObjectNotFoundException; import org.talend.esb.auxiliary.storage.common.exception.AuxiliaryStorageException; import org.talend.esb.auxiliary.storage.common.exception.IllegalParameterException; public class AuxiliaryStorageClientRest<E> extends AbstractAuxiliaryStorageClientRest<E> implements AuxiliaryStorageClient<E> { private static final String CALL_PATH = "/auxstorage/{key}"; AuxiliaryObjectFactory<E> factory; public AuxiliaryStorageClientRest() { super(); } public AuxiliaryStorageClientRest(Properties props) { super(props); } @Override public AuxiliaryObjectFactory<E> getAuxiliaryObjectFactory(){ return this.factory; } @Override public void setAuxiliaryObjectFactory(AuxiliaryObjectFactory<E> factory){ this.factory = factory; } private AuxiliaryObjectFactory<E> findAuxiliaryObjectFactory(){ if(getAuxiliaryObjectFactory()==null){ throw new IllegalParameterException("Auxiliary factory is null"); } return getAuxiliaryObjectFactory(); } @Override public E getStoredObject(String key) { String ctx = lookupObject(key, true); return findAuxiliaryObjectFactory().unmarshallObject(ctx); } @Override public void removeStoredObject(String contextKey) { findAuxiliaryObjectFactory(); deleteObject(contextKey, true); } @Override public String saveObject(E ctx) { return saveObject(ctx, true); } private String saveObject(final E ctx, final boolean retry) { String key = findAuxiliaryObjectFactory().createObjectKey(ctx); if (key == null || key.isEmpty()) { throw new IllegalParameterException("Object key can't be empty"); } WebClient client = getWebClient() .accept(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON) .path(CALL_PATH, key); try{ Response resp = client.put(findAuxiliaryObjectFactory().marshalObject(ctx)); if (resp.getStatus() == 404) { if (!retry) { return null; } if (null != client) { client.reset(); } switchServerURL(client.getBaseURI().toString()); return saveObject(ctx, false); } return key; } catch(WebApplicationException e){ handleWebException(e); } catch (Exception e) { if (retry && (e instanceof ConnectException || e instanceof ProcessingException)) { if (null != client) { client.reset(); } switchServerURL(client.getBaseURI().toString(), e); return saveObject(ctx); } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IllegalStateException("Upload failed: ", e); } finally { if (null != client) { client.reset(); } } return null; } private String lookupObject(final String contextKey, final boolean retry) { if (contextKey == null || contextKey.isEmpty()) { throw new IllegalParameterException("Object key can't be empty"); } WebClient client = getWebClient() .accept(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON) .path(CALL_PATH, contextKey); String object = null; try { object = client.get(String.class); } catch (NotFoundException e) { return null; } catch (WebApplicationException e) { handleWebException(e); } catch (Exception e) { if (retry && (e instanceof ConnectException || e instanceof ProcessingException)) { if (null != client) { client.reset(); } switchServerURL(client.getBaseURI().toString(), e); return lookupObject(contextKey, false); } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IllegalStateException("Lookup failed: ", e); } finally { if (null != client) { client.reset(); } } return object; } private void deleteObject(final String key, final boolean retry) { if (key == null || key.isEmpty()) { throw new IllegalParameterException("Object key can't be empty"); } WebClient client = getWebClient() .accept(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON) .path(CALL_PATH, key); try { client.delete(); } catch (NotFoundException e) { return; } catch (WebApplicationException e) { handleWebException(e); } catch (Exception e) { if (retry && (e instanceof ConnectException || e instanceof ProcessingException)) { if (null != client) { client.reset(); } switchServerURL(client.getBaseURI().toString(), e); deleteObject(key, false); } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IllegalStateException("Delete failed: ", e); } finally { if (null != client) { client.reset(); } } } /** * This method is supposed to be used as exception mapper * from <code>WebApplicationException</code>, sent in REST response, * to <code>AuxiliaryStorageException</code>. * * @param exception Exception to convert from. */ private void handleWebException(WebApplicationException exception) { Response response = exception.getResponse(); if (response == null) { throw new AuxiliaryStorageException("Mapping exception error: response is null"); } int responseStatus = response.getStatus(); if (Status.BAD_REQUEST.getStatusCode() == responseStatus) { throw new IllegalParameterException("Bad request server error"); } else if (Status.NOT_FOUND.getStatusCode() == responseStatus) { throw new ObjectNotFoundException("Object not found in auxiliary storage"); } else if (Status.CONFLICT.getStatusCode() == responseStatus) { throw new ObjectAlreadyExistsException("Object already exists in auxiliary storage"); } else if (Status.INTERNAL_SERVER_ERROR.getStatusCode() == responseStatus) { throw new AuxiliaryStorageException("Internal server error"); } else { throw new AuxiliaryStorageException("Unknown server error"); } } }