/** * Sets a default handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code true} is received from the peer. * <p> * The default handler sends a <em>detach</em> frame if the link has not been closed * locally already and then frees up the resources maintained for the link by invoking * its <em>free</em> method. * * @param <T> The type of link. * @param link The link to set the handler on. * @throws NullPointerException if link is {@code null}. */ public static <T extends ProtonLink<T>> void setDefaultCloseHandler(final ProtonLink<T> link) { link.closeHandler(remoteClose -> { if (link.isOpen()) { // peer has initiated closing // respond with our detach frame link.close(); } link.free(); }); }
/** * Closes a link to a proton based client. * * @param client The client to detach. * @param error The error condition to convey to the client when closing the link. */ protected final void onLinkDetach(final ProtonLink<?> client, final ErrorCondition error) { if (error == null) { logger.debug("closing link [{}]", client.getName()); } else { logger.debug("closing link [{}]: {}", client.getName(), error.getDescription()); client.setCondition(error); } client.close(); }
/** * Gets the (surrogate) identifier of the AMQP connection that a link is part of. * * @param link The link to determine the connection id for. * @return The identifier retrieved from the link's <em>attachment</em> using key {@link #KEY_CONNECTION_ID} * or {@code null} if the attachments do not contain a value for that a key. */ public static String getConnectionId(final ProtonLink<?> link) { return link.attachments().get(KEY_CONNECTION_ID, String.class); }
/** * Closes the specified link using the given throwable to set the local ErrorCondition object for the link. * * @param link The link to close. * @param t The throwable to use to determine the error condition object. */ private <T extends ProtonLink<T>> void closeLinkWithError(final ProtonLink<T> link, final Throwable t) { final ErrorCondition ec = AmqpContext.getErrorCondition(t); LOG.debug("closing link with error condition [symbol: {}, description: {}]", ec.getCondition(), ec.getDescription()); link.setCondition(ec); link.close(); }
/** * Detach the provided link with an AMQP error condition * * @param link AMQP link to detach * @param error AMQP error condition */ static void detachWithError(ProtonLink<?> link, ErrorCondition error) { log.error("Detaching link {} due to error {}, description: {}", link, error.getCondition(), error.getDescription()); link.setSource(null) .open() .setCondition(error) .close(); }
private static void onTimeOut( final ProtonLink<?> link, final ClientConfigProperties clientConfig, final Future<?> result) { if (link.isOpen() && !HonoProtonHelper.isLinkEstablished(link)) { LOG.debug("link establishment timed out after {}ms", clientConfig.getLinkEstablishmentTimeout()); link.close(); link.free(); result.tryFail(new ServerErrorException(HttpsURLConnection.HTTP_UNAVAILABLE)); } }
private static void onRemoteDetach( final ProtonLink<?> link, final String remoteContainer, final boolean closed, final Handler<String> closeHook) { final ErrorCondition error = link.getRemoteCondition(); final String type = link instanceof ProtonSender ? "sender" : "receiver"; final String address = link instanceof ProtonSender ? link.getTarget().getAddress() : link.getSource().getAddress(); if (error == null) { LOG.debug("{} [{}] detached (with closed={}) by peer [{}]", type, address, closed, remoteContainer); } else { LOG.debug("{} [{}] detached (with closed={}) by peer [{}]: {} - {}", type, address, closed, remoteContainer, error.getCondition(), error.getDescription()); } link.close(); if (HonoProtonHelper.isLinkEstablished(link) && closeHook != null) { closeHook.handle(address); } } }
/** * Sets a handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code false} is received from the peer. * <p> * The resources maintained for the link will be freed up after the given handler has * been invoked. * * @param <T> The type of link. * @param link The link to set the handler on. * @param handler The handler to invoke. * @return The wrapper that has been created around the given handler. * @throws NullPointerException if link or handler are {@code null}. */ public static <T extends ProtonLink<T>> Handler<AsyncResult<T>> setDetachHandler( final ProtonLink<T> link, final Handler<AsyncResult<T>> handler) { Objects.requireNonNull(link); Objects.requireNonNull(handler); final Handler<AsyncResult<T>> wrappedHandler = remoteDetach -> { handler.handle(remoteDetach); link.free(); }; link.detachHandler(wrappedHandler); return wrappedHandler; }
/** * Sets a handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code true} is received from the peer. * <p> * The resources maintained for the link will be freed up after the given handler has * been invoked. * * @param <T> The type of link. * @param link The link to set the handler on. * @param handler The handler to invoke. * @return The wrapper that has been created around the given handler. * @throws NullPointerException if link or handler are {@code null}. */ public static <T extends ProtonLink<T>> Handler<AsyncResult<T>> setCloseHandler( final ProtonLink<T> link, final Handler<AsyncResult<T>> handler) { Objects.requireNonNull(link); Objects.requireNonNull(handler); final Handler<AsyncResult<T>> wrappedHandler = remoteClose -> { handler.handle(remoteClose); link.free(); }; link.closeHandler(wrappedHandler); return wrappedHandler; }
private static void handleUnknownEndpoint(final ProtonConnection con, final ProtonLink<?> link, final ResourceIdentifier address) { LOG.info("client [{}] wants to establish link for unknown endpoint [address: {}]", con.getRemoteContainer(), address); link.setCondition( condition(AmqpError.NOT_FOUND.toString(), String.format("no endpoint registered for address %s", address))); link.close(); }
/** * Sets a handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code false} is received from the peer. * <p> * The resources maintained for the link will be freed up after the given handler has * been invoked. * * @param <T> The type of link. * @param link The link to set the handler on. * @param handler The handler to invoke. * @return The wrapper that has been created around the given handler. * @throws NullPointerException if link or handler are {@code null}. */ public static <T extends ProtonLink<T>> Handler<AsyncResult<T>> setDetachHandler( final ProtonLink<T> link, final Handler<AsyncResult<T>> handler) { Objects.requireNonNull(link); Objects.requireNonNull(handler); final Handler<AsyncResult<T>> wrappedHandler = remoteDetach -> { handler.handle(remoteDetach); link.free(); }; link.detachHandler(wrappedHandler); return wrappedHandler; }
/** * Sets a handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code true} is received from the peer. * <p> * The resources maintained for the link will be freed up after the given handler has * been invoked. * * @param <T> The type of link. * @param link The link to set the handler on. * @param handler The handler to invoke. * @return The wrapper that has been created around the given handler. * @throws NullPointerException if link or handler are {@code null}. */ public static <T extends ProtonLink<T>> Handler<AsyncResult<T>> setCloseHandler( final ProtonLink<T> link, final Handler<AsyncResult<T>> handler) { Objects.requireNonNull(link); Objects.requireNonNull(handler); final Handler<AsyncResult<T>> wrappedHandler = remoteClose -> { handler.handle(remoteClose); link.free(); }; link.closeHandler(wrappedHandler); return wrappedHandler; }
/** * Sets a default handler on a link that is invoked when an AMQP <em>detach</em> frame * with its <em>close</em> property set to {@code true} is received from the peer. * <p> * The default handler sends a <em>detach</em> frame if the link has not been closed * locally already and then frees up the resources maintained for the link by invoking * its <em>free</em> method. * * @param <T> The type of link. * @param link The link to set the handler on. * @throws NullPointerException if link is {@code null}. */ public static <T extends ProtonLink<T>> void setDefaultCloseHandler(final ProtonLink<T> link) { link.closeHandler(remoteClose -> { if (link.isOpen()) { // peer has initiated closing // respond with our detach frame link.close(); } link.free(); }); }
/** * Closes a link for an unknown target address. * <p> * The link is closed with AMQP error code <em>amqp:not-found</em>. * * @param con The connection that the link belongs to. * @param link The link. * @param address The unknown target address. */ protected final void handleUnknownEndpoint(final ProtonConnection con, final ProtonLink<?> link, final ResourceIdentifier address) { LOG.info("client [container: {}] wants to establish link for unknown endpoint [address: {}]", con.getRemoteContainer(), address); link.setCondition( ProtonHelper.condition( AmqpError.NOT_FOUND, String.format("no endpoint registered for address %s", address))); link.close(); }
/** * Closes a link to a proton based client. * * @param client The client to detach. * @param error The error condition to convey to the client when closing the link. */ protected final void onLinkDetach(final ProtonLink<?> client, final ErrorCondition error) { if (error == null) { logger.debug("closing link [{}]", client.getName()); } else { logger.debug("closing link [{}]: {}", client.getName(), error.getDescription()); client.setCondition(error); } client.close(); }
/** * Gets the (surrogate) identifier of the AMQP connection that a link is part of. * * @param link The link to determine the connection id for. * @return The identifier retrieved from the link's <em>attachment</em> using key {@link #KEY_CONNECTION_ID} * or {@code null} if the attachments do not contain a value for that a key. */ public static String getConnectionId(final ProtonLink<?> link) { return link.attachments().get(KEY_CONNECTION_ID, String.class); }
} else if (link.isOpen()) { link.closeHandler(remoteDetach -> { context.owner().cancelTimer(timerId); link.close(); } else { link.free(); });
/** * Closes a link for an unknown target address. * <p> * The link is closed with AMQP error code <em>amqp:not-found</em>. * * @param con The connection that the link belongs to. * @param link The link. * @param address The unknown target address. */ protected final void handleUnknownEndpoint(final ProtonConnection con, final ProtonLink<?> link, final ResourceIdentifier address) { LOG.info("client [container: {}] wants to establish link for unknown endpoint [address: {}]", con.getRemoteContainer(), address); link.setCondition( ProtonHelper.condition( AmqpError.NOT_FOUND, String.format("no endpoint registered for address %s", address))); link.close(); }
/** * Copies properties from a connection's attachments to a link's attachments. * <p> * The properties copied are * <ul> * <li>{@link #KEY_CONNECTION_ID}</li> * </ul> * * @param source The connection. * @param target The link. */ public static void copyProperties(final ProtonConnection source, final ProtonLink<?> target) { Objects.requireNonNull(source); Objects.requireNonNull(target); target.attachments().set(Constants.KEY_CONNECTION_ID, String.class, getConnectionId(source)); }