use of co.cask.cdap.common.HandlerException in project cdap by caskdata.
the class DatasetInstanceHandler method executeAdmin.
/**
* Executes an admin operation on a dataset instance.
*
* @param namespaceId namespace of the dataset instance
* @param name name of the dataset instance
* @param method the admin operation to execute (e.g. "exists", "truncate", "upgrade")
* @throws Exception
*/
@POST
@Path("/data/datasets/{name}/admin/{method}")
public void executeAdmin(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("name") String name, @PathParam("method") String method) throws Exception {
DatasetId instance = ConversionHelpers.toDatasetInstanceId(namespaceId, name);
try {
DatasetAdminOpResponse response = instanceService.executeAdmin(instance, method);
responder.sendJson(HttpResponseStatus.OK, response);
} catch (HandlerException e) {
responder.sendStatus(e.getFailureStatus());
}
}
use of co.cask.cdap.common.HandlerException in project cdap by caskdata.
the class DatasetInstanceService method executeAdmin.
/**
* Executes an admin operation on a dataset instance.
*
* @param instance the instance to execute the admin operation on
* @param method the type of admin operation to execute
* @return the {@link DatasetAdminOpResponse} from the HTTP handler
* @throws NamespaceNotFoundException if the requested namespace was not found
* @throws IOException if there was a problem in checking if the namespace exists over HTTP
* @throws UnauthorizedException if perimeter security and authorization are enabled, and the current user does not
* have -
* <ol>
* <li>{@link Action#ADMIN} privileges on the #instance (for "drop" or "truncate") </li>
* <li>any privileges on the #instance (for "exists")</li>
* <ol>
*/
DatasetAdminOpResponse executeAdmin(DatasetId instance, String method) throws Exception {
ensureNamespaceExists(instance.getParent());
Object result = null;
// NOTE: one cannot directly call create and drop, instead this should be called thru
// POST/DELETE @ /data/datasets/{instance-id}. Because we must create/drop metadata for these at same time
Principal principal = authenticationContext.getPrincipal();
switch(method) {
case "exists":
ensureAccess(instance);
result = opExecutorClient.exists(instance);
break;
case "truncate":
if (instanceManager.get(instance) == null) {
throw new DatasetNotFoundException(instance);
}
authorizationEnforcer.enforce(instance, principal, Action.ADMIN);
opExecutorClient.truncate(instance);
publishAudit(instance, AuditType.TRUNCATE);
break;
case "upgrade":
if (instanceManager.get(instance) == null) {
throw new DatasetNotFoundException(instance);
}
authorizationEnforcer.enforce(instance, principal, Action.ADMIN);
opExecutorClient.upgrade(instance);
publishAudit(instance, AuditType.UPDATE);
break;
default:
throw new HandlerException(HttpResponseStatus.NOT_FOUND, "Invalid admin operation: " + method);
}
return new DatasetAdminOpResponse(result, null);
}
use of co.cask.cdap.common.HandlerException in project cdap by caskdata.
the class HttpRequestHandler method exceptionCaught.
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
Throwable cause = e.getCause();
// avoid handling exception more than once from a handler, to avoid a possible infinite recursion
switch(exceptionsHandled.incrementAndGet()) {
case 1:
// if this is the first error, break and handle the error normally (below)
break;
case 2:
// if its the second time, log and return
LOG.error("Not handling exception due to already having handled an exception in Request Handler {}", ctx.getChannel(), cause);
// fall through
default:
// in an exception and cause recursion
return;
}
if (cause instanceof HandlerException && ((HandlerException) cause).getFailureStatus() != HttpResponseStatus.INTERNAL_SERVER_ERROR) {
LOG.debug("Exception raised in Request Handler {}", ctx.getChannel(), cause);
} else {
LOG.error("Exception raised in Request Handler {}", ctx.getChannel(), cause);
}
if (ctx.getChannel().isConnected() && !channelClosed) {
HttpResponse response = cause instanceof HandlerException ? ((HandlerException) cause).createFailureResponse() : new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
Channels.write(ctx, e.getFuture(), response);
e.getFuture().addListener(ChannelFutureListener.CLOSE);
}
}
use of co.cask.cdap.common.HandlerException in project cdap by caskdata.
the class HttpRequestHandler method getDiscoverable.
private WrappedDiscoverable getDiscoverable(final HttpRequest httpRequest, final InetSocketAddress address) {
EndpointStrategy strategy = serviceLookup.getDiscoverable(address.getPort(), httpRequest);
if (strategy == null) {
throw new HandlerException(HttpResponseStatus.SERVICE_UNAVAILABLE, String.format("No endpoint strategy found for request : %s", httpRequest.getUri()));
}
Discoverable discoverable = strategy.pick();
if (discoverable == null) {
throw new HandlerException(HttpResponseStatus.SERVICE_UNAVAILABLE, String.format("No discoverable found for request : %s", httpRequest.getUri()));
}
return new WrappedDiscoverable(discoverable);
}
use of co.cask.cdap.common.HandlerException in project cdap by caskdata.
the class HttpRequestHandler method messageReceived.
@Override
public void messageReceived(final ChannelHandlerContext ctx, MessageEvent event) throws Exception {
if (channelClosed) {
return;
}
final Channel inboundChannel = event.getChannel();
Object msg = event.getMessage();
if (msg instanceof HttpChunk) {
// This case below should never happen this would mean we get Chunks before HTTPMessage.
if (chunkSender == null) {
throw new HandlerException(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Chunk received and event sender is null");
}
chunkSender.send(msg);
} else if (msg instanceof HttpRequest) {
// Discover and forward event.
HttpRequest request = (HttpRequest) msg;
request = applyProxyRules(request);
// Suspend incoming traffic until connected to the outbound service.
inboundChannel.setReadable(false);
WrappedDiscoverable discoverable = getDiscoverable(request, (InetSocketAddress) inboundChannel.getLocalAddress());
// If no event sender, make new connection, otherwise reuse existing one.
MessageSender sender = discoveryLookup.get(discoverable);
if (sender == null || !sender.isConnected()) {
InetSocketAddress address = discoverable.getSocketAddress();
ChannelFuture future = clientBootstrap.connect(address);
final Channel outboundChannel = future.getChannel();
outboundChannel.getPipeline().addAfter("request-encoder", "outbound-handler", new OutboundHandler(inboundChannel));
if (Arrays.equals(Constants.Security.SSL_URI_SCHEME.getBytes(), discoverable.getPayload())) {
SSLContext clientContext;
try {
clientContext = SSLContext.getInstance("TLS");
clientContext.init(null, PermissiveTrustManagerFactory.getTrustManagers(), null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException("SSL is enabled for app-fabric but failed to create SSLContext in the router " + "client.", e);
}
SSLEngine engine = clientContext.createSSLEngine();
engine.setUseClientMode(true);
engine.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" });
outboundChannel.getPipeline().addFirst("ssl", new SslHandler(engine));
LOG.trace("Adding ssl handler to the pipeline.");
}
sender = new MessageSender(inboundChannel, future);
discoveryLookup.put(discoverable, sender);
// Remember the in-flight outbound channel
inboundChannel.setAttachment(outboundChannel);
outboundChannel.getCloseFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
inboundChannel.getPipeline().execute(new Runnable() {
@Override
public void run() {
// close the inbound channel as well if it carries the in-flight request
if (outboundChannel.equals(inboundChannel.getAttachment())) {
closeOnFlush(inboundChannel);
}
}
});
}
});
} else {
Channel outboundChannel = (Channel) inboundChannel.getAttachment();
if (outboundChannel != null) {
// Set outbound channel to be readable in case previous request has set it as non-readable
outboundChannel.setReadable(true);
}
}
// Send the message.
sender.send(request);
inboundChannel.setReadable(true);
//Save the channelFuture for subsequent chunks
if (request.isChunked()) {
chunkSender = sender;
}
} else {
super.messageReceived(ctx, event);
}
}
Aggregations