/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.protocol.mgmt;
import java.io.IOException;
import java.util.concurrent.Executor;
import org.jboss.remoting3.Channel;
/**
* The context for handling a management request. Besides providing basic state associated with the request,
* one of the primary purposes of the {@code ManagementRequestContext} is to support asynchronous task execution
* by request handlers. Handlers should avoid doing blocking tasks in the remoting threads that invoke them, so
* the asynchronous task execution facilities of this class allow that work to be offloaded to other threads. Handlers
* also should be careful about performing IO writes using threads that have invoked management operations, as those
* threads may be interrupted if the caller cancels the operation, and if that interruption happens during IO the
* remote channel will be incorrectly closed. The asynchronous task execution facilities of this class allow the IO
* writes to be done in a separate thread.
*
* @param <A> the type of the attachment that can be retrieved from the context
*
* @author Emanuel Muckenhuber
*/
public interface ManagementRequestContext<A> {
/**
* Get the current batch id for the overall operation.
*
* @return the batch id
*/
Integer getOperationId();
/**
* Get any attachment used to maintain shared state across possibly multiple requests associated with a
* larger overall operation.
* {@see org.jboss.as.protocol.mgmt.ActiveOperation#getAttachment()}
*
* @return the attachment, can be {@code null}
*/
A getAttachment();
/**
* Get the underlying channel.
*
* @return the channel
*/
Channel getChannel();
/**
* Get the protocol header.
*
* @return the protocol header
*/
ManagementProtocolHeader getRequestHeader();
/**
* Execute a cancellable task at some point in the future, using this object's internal {@link Executor}.
* Equivalent to {@code executeAsync(task, true)}.
* <p>
* If the executor {@link java.util.concurrent.RejectedExecutionException rejects} the task, or if the task itself
* throws an exception during execution, the
* {@link ActiveOperation.ResultHandler#failed(Throwable) failed method} of the
* {@code ResultHander} associated with the request will be invoked, and if it returns {@code true} a failure
* message will be sent to the remote client.
* </p>
*
* @param task the task
*
* @return {@code true} if the task was accepted for execution; {@code false} if the executor rejected it
*/
boolean executeAsync(final AsyncTask<A> task);
/**
* Execute a possibly cancellable task at some point in the future, using this object's internal {@link Executor}.
* <p>
* If the executor {@link java.util.concurrent.RejectedExecutionException rejects} the task, or if the task itself
* throws an exception during execution, the
* {@link ActiveOperation.ResultHandler#failed(Throwable) failed method} of the
* {@code ResultHander} associated with the request will be invoked, and if it returns {@code true} a failure
* message will be sent to the remote client.
* </p>
*
* @param task the task
* @param cancellable {@code true} if the task can be cancelled as part of overall request cancellation
*
* @return {@code true} if the task was accepted for execution; {@code false} if the executor rejected it
*/
boolean executeAsync(final AsyncTask<A> task, boolean cancellable);
/**
* Execute a cancellable task at some point in the future, using the given {@link Executor}.
* Equivalent to {@code executeAsync(task, true, executor)}.
* <p>
* If the executor {@link java.util.concurrent.RejectedExecutionException rejects} the task, or if the task itself
* throws an exception during execution, the
* {@link ActiveOperation.ResultHandler#failed(Throwable) failed method} of the
* {@code ResultHander} associated with the request will be invoked, and if it returns {@code true} a failure
* message will be sent to the remote client.
* </p>
*
* @param task the task
* @param executor the executor
*
* @return {@code true} if the task was accepted for execution; {@code false} if the executor rejected it
*/
boolean executeAsync(final AsyncTask<A> task, Executor executor);
/**
* Execute a possibly cancellable task at some point in the future, using the given {@link Executor}.
* Equivalent to {@code executeAsync(task, true, executor)}.
* <p>
* If the executor {@link java.util.concurrent.RejectedExecutionException rejects} the task, or if the task itself
* throws an exception during execution, the
* {@link ActiveOperation.ResultHandler#failed(Throwable) failed method} of the
* {@code ResultHander} associated with the request will be invoked, and if it returns {@code true} a failure
* message will be sent to the remote client.
* </p>
*
* @param task the task
* @param cancellable {@code true} if the task can be cancelled as part of overall request cancellation
* @param executor the executor
*
* @return {@code true} if the task was accepted for execution; {@code false} if the executor rejected it
*/
boolean executeAsync(final AsyncTask<A> task, boolean cancellable, Executor executor);
/**
* Initiates writing a new message to the remote side, using the given header.
*
* @param header the protocol header
* @return the message output stream to use for writing further data associated with the message
* @throws IOException
*/
FlushableDataOutput writeMessage(final ManagementProtocolHeader header) throws IOException;
/** A task that can be executed asynchronously by a {@link ManagementRequestContext} */
interface AsyncTask<A> {
/**
* Execute the task.
* <p>
* If the task throws an exception during execution, the
* {@link ActiveOperation.ResultHandler#failed(Throwable) failed method} of the
* {@code ResultHander} associated with the request will be invoked, and if it returns {@code true} a failure
* message will be sent to the remote client.
* </p>
*
* @param context the request context
* @throws Exception
*/
void execute(final ManagementRequestContext<A> context) throws Exception;
}
/**
* {@link org.jboss.as.protocol.mgmt.ManagementRequestContext.AsyncTask} subinterface implemented
* by tasks where the appropriate request header to use for notifying a remote process of a
* failure varies through the course of the task.
*
* @deprecated this is a bit of a hack, plus we can move this method into AsyncTask with a default impl
* once this module no longer requires JDK 6 source level
*/
@Deprecated
interface MultipleResponseAsyncTask<A> extends AsyncTask<A> {
/**
* Gets the current request header for which an error response should be sent
* @return the header, or {@code null} if the
* {@linkplain ManagementRequestContext#getRequestHeader() default header for the request context}
* should be used
*/
ManagementProtocolHeader getCurrentRequestHeader();
}
}