Updated Branches: refs/heads/master 32499e86b -> f3e0efc4f
REST exception handling modifications Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/f3e0efc4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/f3e0efc4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/f3e0efc4 Branch: refs/heads/master Commit: f3e0efc4f655073d99adf711cfed4875f1fceace Parents: 32499e8 Author: Pradeep Fernando <[email protected]> Authored: Tue Dec 17 11:48:11 2013 +0530 Committer: Pradeep Fernando <[email protected]> Committed: Tue Dec 17 11:48:11 2013 +0530 ---------------------------------------------------------------------- .../org/apache/stratos/rest/endpoint/Utils.java | 40 ++++++++++++++++++++ .../endpoint/exception/RestAPIException.java | 20 ++++++++++ .../handlers/CustomExceptionMapper.java | 37 ++++++++++++++++++ .../handlers/StratosAuthenticationHandler.java | 19 ++++++++-- .../handlers/StratosAuthorizingHandler.java | 14 +++++-- .../rest/endpoint/services/StratosAdmin.java | 2 +- .../src/main/webapp/WEB-INF/cxf-servlet.xml | 2 + .../src/main/webapp/WEB-INF/web.xml | 4 +- 8 files changed, 128 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java new file mode 100644 index 0000000..638fb63 --- /dev/null +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/Utils.java @@ -0,0 +1,40 @@ +package org.apache.stratos.rest.endpoint;/* +* Copyright (c) 2005-2012, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +public class Utils { + + + public static String buildMessage(int errorCode, String errorMessage) { + String jsonResponse = "{\"Error\":{" + + " \"errorCode\": \" " + errorCode + "\"," + + " \"errorMessage\": \" " + errorMessage + "\"," + + "}" + + "}"; + return jsonResponse; + } + + public static String buildMessage(String errorMessage) { + String jsonResponse = "{\"Error\":{" + + " \"errorCode\": \" " + -1234 + "\"," + + " \"errorMessage\": \" " + errorMessage + "\"," + + "}" + + "}"; + return jsonResponse; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/exception/RestAPIException.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/exception/RestAPIException.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/exception/RestAPIException.java index c483fef..f10d2a2 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/exception/RestAPIException.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/exception/RestAPIException.java @@ -19,11 +19,14 @@ package org.apache.stratos.rest.endpoint.exception; +import javax.ws.rs.core.Response; + public class RestAPIException extends Exception { private static final long serialVersionUID = 1L; private String message; + private Response.Status httpStatusCode; public RestAPIException() { super(); @@ -34,11 +37,23 @@ public class RestAPIException extends Exception { this.message = message; } + public RestAPIException(Response.Status httpStatusCode,String message, Throwable cause) { + super(message, cause); + this.message = message; + this.httpStatusCode = httpStatusCode; + } + public RestAPIException(String message) { super(message); this.message = message; } + public RestAPIException(Response.Status httpStatusCode, String message) { + super(message); + this.message = message; + this.httpStatusCode = httpStatusCode; + } + public RestAPIException(Throwable cause) { super(cause); } @@ -47,4 +62,9 @@ public class RestAPIException extends Exception { return message; } + public Response.Status getHTTPStatusCode() { + return httpStatusCode; + } + + } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomExceptionMapper.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomExceptionMapper.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomExceptionMapper.java new file mode 100644 index 0000000..3fe6ea4 --- /dev/null +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomExceptionMapper.java @@ -0,0 +1,37 @@ +package org.apache.stratos.rest.endpoint.handlers;/* +* Copyright (c) 2005-2012, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import org.apache.stratos.rest.endpoint.Utils; +import org.apache.stratos.rest.endpoint.exception.RestAPIException; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +public class CustomExceptionMapper implements ExceptionMapper<RestAPIException> { + public Response toResponse(RestAPIException restAPIException) { + // if no specific error message specified, spitting out a generaic error message + String errorMessage = (restAPIException.getMessage() != null)? + restAPIException.getMessage():"Error while fullfilling the request"; + // if no specific error specified we are throwing the bad request http status code by default + Response.Status httpStatus= (restAPIException.getHTTPStatusCode() != null)? + restAPIException.getHTTPStatusCode():Response.Status.BAD_REQUEST; + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON). + entity(Utils.buildMessage(httpStatus.getStatusCode(),errorMessage)).build(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java index 457026d..f9a42fd 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java @@ -26,6 +26,8 @@ import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.message.Message; import org.apache.cxf.security.SecurityContext; import org.apache.stratos.rest.endpoint.ServiceHolder; +import org.apache.stratos.rest.endpoint.Utils; +import org.apache.stratos.rest.endpoint.exception.RestAPIException; import org.apache.stratos.rest.endpoint.security.StratosSecurityContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.common.AuthenticationException; @@ -35,6 +37,7 @@ import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; /** @@ -61,7 +64,8 @@ public class StratosAuthenticationHandler implements RequestHandler { if ((username == null) || (password == null) || username.equals("") || password.equals("")) { log.error("username or password is seen as null/empty values."); - return Response.status(401).header("WWW-Authenticate", "Basic").build(); + return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic"). + type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Username/Password cannot be null")).build(); } try { RealmService realmService = ServiceHolder.getRealmService(); @@ -72,7 +76,9 @@ public class StratosAuthenticationHandler implements RequestHandler { UserRealm userRealm = AnonymousSessionUtil.getRealmByTenantDomain(registryService, realmService, tenantDomain); if (userRealm == null) { log .error("Invalid domain or unactivated tenant login"); - throw new AuthenticationException("Invalid domain or unactivated tenant login"); + // is this the correct HTTP code for this scenario ? (401) + return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic"). + type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Tenant not found")).build(); } username = MultitenantUtils.getTenantAwareUsername(username); if (userRealm.getUserStoreManager().authenticate(username, password)) { // if authenticated @@ -90,10 +96,15 @@ public class StratosAuthenticationHandler implements RequestHandler { } else { log.warn("unable to authenticate the request"); // authentication failed, request the authetication, add the realm name if needed to the value of WWW-Authenticate - return Response.status(401).header("WWW-Authenticate", "Basic").build(); + return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic"). + type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Authentication failed. Please " + + "check your username/password")).build(); } } catch (Exception exception) { - return Response.status(401).header("WWW-Authenticate", "Basic").build(); + log.error("Authentication failed",exception); + // server error in the eyes of the client. Hence 5xx HTTP code. + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON). + entity(Utils.buildMessage("Unexpected error. Please contact the system admin")).build(); } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java index 3227df2..0902182 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthorizingHandler.java @@ -29,6 +29,7 @@ import org.apache.cxf.message.Message; import org.apache.cxf.security.SecurityContext; import org.apache.cxf.service.Service; import org.apache.cxf.service.model.BindingOperationInfo; +import org.apache.stratos.rest.endpoint.Utils; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.user.api.AuthorizationManager; @@ -36,6 +37,7 @@ import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -69,12 +71,18 @@ public class StratosAuthorizingHandler implements RequestHandler { SecurityContext securityContext = message.get(SecurityContext.class); Method method = getTargetMethod(message); if (!authorize(securityContext, method)) { - return Response.status(Response.Status.FORBIDDEN).build(); + log.warn("User :"+ securityContext.getUserPrincipal().getName() + "trying to perform unauthrorized action" + + " against the resource :"+ method); + return Response.status(Response.Status.FORBIDDEN).type(MediaType.APPLICATION_JSON). + entity(Utils.buildMessage("The user does not have required permissions to " + + "perform this operation")).build(); } return null; - } catch (Exception ex) { - return Response.status(Response.Status.FORBIDDEN).build(); + } catch (Exception exception) { + log.error("Unexpercted error occured while REST api, authorization process",exception); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON). + entity(Utils.buildMessage("Unexpected error. Please contact the system admin")).build(); } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java index 850a8ff..bdc7c00 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java +++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java @@ -331,7 +331,7 @@ public class StratosAdmin extends AbstractAdmin { @AuthorizationAction("/permission/protected/manage/monitor/tenants") public void unsubscribe(String alias){ try { - ServiceUtils.unsubscribe(alias,getTenantDomain()); + ServiceUtils.unsubscribe(alias, getTenantDomain()); } catch (Exception exception) { log.error(exception); } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/cxf-servlet.xml ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/cxf-servlet.xml index 32164e2..dfb7263 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -31,6 +31,7 @@ </jaxrs:serviceBeans> <jaxrs:providers> + <ref bean="exceptionHandler"/> <ref bean="authenticationFilter"/> <ref bean="authorizationFilter"/> </jaxrs:providers> @@ -46,6 +47,7 @@ <bean id="authorizationFilter" class="org.apache.stratos.rest.endpoint.handlers.StratosAuthorizingHandler"> <property name="securedObject" ref="stratosRestEndpointBean"/> </bean> + <bean id="exceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.CustomExceptionMapper"/> <!--The below config enables OAuth based authentication/authorization for REST API--> <!--bean id="OAuthFilter" class="org.apache.stratos.rest.endpoint.handlers.OAuthHandler"> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/f3e0efc4/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/web.xml b/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/web.xml index 9e8eb4d..7cef351 100644 --- a/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/web.xml +++ b/components/org.apache.stratos.rest.endpoint/src/main/webapp/WEB-INF/web.xml @@ -26,13 +26,13 @@ <display-name>S2 Admin Endpoint</display-name> <servlet> - <servlet-name>S2AdminEndpoint</servlet-name> + <servlet-name>StratosAdminEndpoint</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> - <servlet-name>S2AdminEndpoint</servlet-name> + <servlet-name>StratosAdminEndpoint</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
