/******************************************************************************* * Copyright (c) 2016 Sierra Wireless and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.html. * * Contributors: * Sierra Wireless - initial API and implementation *******************************************************************************/ package org.eclipse.leshan.core.californium; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; import org.eclipse.leshan.core.request.exception.RequestRejectedException; import org.eclipse.leshan.core.response.LwM2mResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class SyncRequestObserver<T extends LwM2mResponse> extends AbstractRequestObserver<T> { private static final Logger LOG = LoggerFactory.getLogger(SyncRequestObserver.class); private CountDownLatch latch = new CountDownLatch(1); private AtomicReference<T> ref = new AtomicReference<>(null); private AtomicBoolean coapTimeout = new AtomicBoolean(false); private AtomicReference<RuntimeException> exception = new AtomicReference<>(); private Long timeout; public SyncRequestObserver(Request coapRequest, Long timeout) { super(coapRequest); this.timeout = timeout; } @Override public void onResponse(Response coapResponse) { LOG.debug("Received coap response: {}", coapResponse); try { T lwM2mResponseT = buildResponse(coapResponse); if (lwM2mResponseT != null) { ref.set(lwM2mResponseT); } } catch (RuntimeException e) { exception.set(e); } finally { latch.countDown(); } } @Override public void onTimeout() { coapTimeout.set(true); latch.countDown(); } @Override public void onCancel() { LOG.debug(String.format("Synchronous request cancelled %s", coapRequest)); latch.countDown(); } @Override public void onReject() { exception.set(new RequestRejectedException("Request %s rejected", coapRequest.getURI())); latch.countDown(); } public T waitForResponse() throws InterruptedException { try { boolean timeElapsed = false; if (timeout != null) { timeElapsed = !latch.await(timeout, TimeUnit.MILLISECONDS); } else { latch.await(); } if (timeElapsed || coapTimeout.get()) { coapRequest.cancel(); } } finally { coapRequest.removeMessageObserver(this); } if (exception.get() != null) { coapRequest.cancel(); throw exception.get(); } return ref.get(); } }