From 7da562b59cdae26e07cb4b1112e9dbe71deb2895 Mon Sep 17 00:00:00 2001 From: Dustin Jenkins <Dustin.Jenkins@nrc-cnrc.gc.ca> Date: Wed, 15 Jul 2015 17:03:47 -0700 Subject: [PATCH] Story 1734: Added GET with JSON. --- .../ac/server/web/users/CreateUserAction.java | 4 +- .../ac/server/web/users/GetUserAction.java | 4 +- .../cadc/ac/server/web/users/UsersAction.java | 25 ++++++ .../ac/server/web/users/UsersServlet.java | 25 +++++- .../web/users/GetUserIDsActionTest.java | 2 + .../ac/server/web/users/UsersActionTest.java | 89 +++++++++++++++---- .../ac/server/web/users/UsersServletTest.java | 47 ++++++++++ 7 files changed, 176 insertions(+), 20 deletions(-) create mode 100644 projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java index af90bfed..ad3c1b0b 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/CreateUserAction.java @@ -93,8 +93,8 @@ public class CreateUserAction extends UsersAction UserPersistence userPersistence = getUserPersistence(); UserRequest userRequest = UserRequestReader.read(this.inputStream); User<? extends Principal> newUser = userPersistence.addUser(userRequest); - this.response.setContentType("application/xml"); - UserWriter.write(newUser, this.response.getOutputStream()); + this.response.setContentType(acceptedContentType); + writeUser(newUser, this.response.getWriter()); logUserInfo(newUser.getUserID().getName()); return null; } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java index a87116e7..22f9cf63 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/GetUserAction.java @@ -88,8 +88,8 @@ public class GetUserAction extends UsersAction { UserPersistence userPersistence = getUserPersistence(); User<? extends Principal> user = userPersistence.getUser(userID); - this.response.setContentType("application/xml"); - UserWriter.write(user, this.response.getOutputStream()); + this.response.setContentType(acceptedContentType); + writeUser(user, this.response.getWriter()); return null; } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java index 697357e9..54537466 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersAction.java @@ -69,6 +69,8 @@ package ca.nrc.cadc.ac.server.web.users; import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; import java.security.AccessControlException; import java.security.Principal; import java.security.PrivilegedActionException; @@ -77,6 +79,7 @@ import java.security.PrivilegedExceptionAction; import javax.security.auth.Subject; import javax.servlet.http.HttpServletResponse; +import ca.nrc.cadc.ac.User; import org.apache.log4j.Logger; import ca.nrc.cadc.ac.UserNotFoundException; @@ -88,8 +91,12 @@ public abstract class UsersAction implements PrivilegedExceptionAction<Object> { private static final Logger log = Logger.getLogger(UsersAction.class); + static final String DEFAULT_CONTENT_TYPE = "text/xml"; + static final String JSON_CONTENT_TYPE = "application/json"; + protected UserLogInfo logInfo; protected HttpServletResponse response; + protected String acceptedContentType = DEFAULT_CONTENT_TYPE; UsersAction(UserLogInfo logInfo) { @@ -204,4 +211,22 @@ public abstract class UsersAction this.logInfo.userName = userName; } + public void setAcceptedContentType(final String acceptedContentType) + { + this.acceptedContentType = acceptedContentType; + } + + protected final <T extends Principal> void writeUser(final User<T> user, + final Writer writer) + throws IOException + { + if (acceptedContentType.equals(DEFAULT_CONTENT_TYPE)) + { + ca.nrc.cadc.ac.xml.UserWriter.write(user, writer); + } + else if (acceptedContentType.equals(JSON_CONTENT_TYPE)) + { + ca.nrc.cadc.ac.json.UserWriter.write(user, writer); + } + } } diff --git a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java index 37f09e37..260bc47f 100644 --- a/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java +++ b/projects/cadcAccessControl-Server/src/ca/nrc/cadc/ac/server/web/users/UsersServlet.java @@ -3,7 +3,7 @@ ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2014. (c) 2014. + * (c) 2015. (c) 2015. * Government of Canada Gouvernement du Canada * National Research Council Conseil national de recherches * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 @@ -75,6 +75,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import ca.nrc.cadc.util.StringUtil; import org.apache.log4j.Logger; import ca.nrc.cadc.auth.AuthenticationUtil; @@ -83,6 +84,7 @@ public class UsersServlet extends HttpServlet { private static final Logger log = Logger.getLogger(UsersServlet.class); + /** * Create a UserAction and run the action safely. */ @@ -91,12 +93,14 @@ public class UsersServlet extends HttpServlet { long start = System.currentTimeMillis(); UserLogInfo logInfo = new UserLogInfo(request); + try { log.info(logInfo.start()); Subject subject = AuthenticationUtil.getSubject(request); logInfo.setSubject(subject); UsersAction action = UsersActionFactory.getUsersAction(request, logInfo); + action.setAcceptedContentType(getAcceptedContentType(request)); action.doAction(subject, response); } catch (IllegalArgumentException e) @@ -158,4 +162,23 @@ public class UsersServlet extends HttpServlet doAction(request, response); } + /** + * Obtain the requested (Accept) content type. + * + * @param request The HTTP Request. + * @return String content type. + */ + String getAcceptedContentType(final HttpServletRequest request) + { + final String requestedContentType = request.getHeader("Accept"); + + if (!StringUtil.hasText(requestedContentType)) + { + return UsersAction.DEFAULT_CONTENT_TYPE; + } + else + { + return requestedContentType; + } + } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserIDsActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserIDsActionTest.java index 386148bb..11136572 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserIDsActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/GetUserIDsActionTest.java @@ -110,6 +110,7 @@ public class GetUserIDsActionTest @Ignore public void testRun() throws Exception { + /* try { Collection<HttpPrincipal> userIDs = new ArrayList<HttpPrincipal>(); @@ -159,6 +160,7 @@ public class GetUserIDsActionTest log.error(t.getMessage(), t); fail("unexpected error: " + t.getMessage()); } + */ } } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java index 8c185028..67cba1aa 100644 --- a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersActionTest.java @@ -68,35 +68,90 @@ */ package ca.nrc.cadc.ac.server.web.users; +import ca.nrc.cadc.ac.User; import ca.nrc.cadc.ac.UserNotFoundException; +import ca.nrc.cadc.auth.HttpPrincipal; import ca.nrc.cadc.net.TransientException; import ca.nrc.cadc.util.Log4jInit; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.*; import java.security.AccessControlException; import javax.servlet.http.HttpServletResponse; + import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.junit.BeforeClass; import org.junit.Test; + import static org.junit.Assert.*; /** - * * @author jburke */ public class UsersActionTest { private final static Logger log = Logger.getLogger(UsersActionTest.class); - + @BeforeClass public static void setUpClass() { Log4jInit.setLevel("ca.nrc.cadc.ac", Level.INFO); } + @Test + public void writeUserXML() throws Exception + { + final UsersAction usersAction = new UsersAction(null) + { + @Override + public Object run() throws Exception + { + // Do nothing. + return null; + } + }; + + final User<HttpPrincipal> user = + new User<HttpPrincipal>(new HttpPrincipal("CADCtest")); + final Writer writer = new StringWriter(); + + usersAction.writeUser(user, writer); + + assertEquals("Wrong XML output.", + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + + "<user>\r\n" + + " <userID>\r\n" + + " <identity type=\"HTTP\">CADCtest</identity>\r\n" + + " </userID>\r\n" + + "</user>\r\n", writer.toString()); + } + + @Test + public void writeUserJSON() throws Exception + { + final UsersAction usersAction = new UsersAction(null) + { + @Override + public Object run() throws Exception + { + // Do nothing. + return null; + } + }; + + final User<HttpPrincipal> user = + new User<HttpPrincipal>(new HttpPrincipal("CADCtest")); + final Writer writer = new StringWriter(); + + usersAction.setAcceptedContentType(UsersAction.JSON_CONTENT_TYPE); + usersAction.writeUser(user, writer); + + assertEquals("Wrong JSON output.", + "{\"user\":{\"userID\":{\"identity\":{\"name\":\"CADCtest\",\"type\":\"HTTP\"}}}}", + writer.toString()); + } + @Test public void testDoActionAccessControlException() throws Exception { @@ -105,7 +160,7 @@ public class UsersActionTest Exception e = new AccessControlException(""); testDoAction(message, responseCode, e); } - + @Test public void testDoActionIllegalArgumentException() throws Exception { @@ -123,7 +178,7 @@ public class UsersActionTest Exception e = new UserNotFoundException("foo"); testDoAction(message, responseCode, e); } - + @Test public void testDoActionUnsupportedOperationException() throws Exception { @@ -132,17 +187,19 @@ public class UsersActionTest Exception e = new UnsupportedOperationException(); testDoAction(message, responseCode, e); } - + @Test public void testDoActionTransientException() throws Exception { try { - HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); + HttpServletResponse response = EasyMock + .createMock(HttpServletResponse.class); EasyMock.expect(response.isCommitted()).andReturn(Boolean.FALSE); response.setContentType("text/plain"); EasyMock.expectLastCall().once(); - EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(new StringWriter())); + EasyMock.expect(response.getWriter()) + .andReturn(new PrintWriter(new StringWriter())); EasyMock.expectLastCall().once(); response.setStatus(503); EasyMock.expectLastCall().once(); @@ -165,17 +222,19 @@ public class UsersActionTest fail("unexpected error: " + t.getMessage()); } } - + private void testDoAction(String message, int responseCode, Exception e) - throws Exception + throws Exception { try { - HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); + HttpServletResponse response = EasyMock + .createMock(HttpServletResponse.class); EasyMock.expect(response.isCommitted()).andReturn(Boolean.FALSE); response.setContentType("text/plain"); EasyMock.expectLastCall().once(); - EasyMock.expect(response.getWriter()).andReturn(new PrintWriter(new StringWriter())); + EasyMock.expect(response.getWriter()) + .andReturn(new PrintWriter(new StringWriter())); EasyMock.expectLastCall().once(); response.setStatus(responseCode); EasyMock.expectLastCall().once(); @@ -200,7 +259,7 @@ public class UsersActionTest public class UsersActionImpl extends UsersAction { Exception exception; - + public UsersActionImpl(UserLogInfo logInfo) { super(logInfo); @@ -216,5 +275,5 @@ public class UsersActionTest this.exception = e; } } - + } diff --git a/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java new file mode 100644 index 00000000..8e0a27f5 --- /dev/null +++ b/projects/cadcAccessControl-Server/test/src/ca/nrc/cadc/ac/server/web/users/UsersServletTest.java @@ -0,0 +1,47 @@ +package ca.nrc.cadc.ac.server.web.users; + + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Test; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + + +public class UsersServletTest +{ + @Test + public void getAcceptedContentTypeJSON() throws Exception + { + final HttpServletRequest mockRequest = + createMock(HttpServletRequest.class); + final UsersServlet testSubject = new UsersServlet(); + + expect(mockRequest.getHeader("Accept")). + andReturn("application/json").once(); + + replay(mockRequest); + + assertEquals("Wrong content type.", "application/json", + testSubject.getAcceptedContentType(mockRequest)); + + verify(mockRequest); + } + + @Test + public void getAcceptedContentTypeDefault() throws Exception + { + final HttpServletRequest mockRequest = + createMock(HttpServletRequest.class); + final UsersServlet testSubject = new UsersServlet(); + + expect(mockRequest.getHeader("Accept")).andReturn(null).once(); + + replay(mockRequest); + + assertEquals("Wrong content type.", "text/xml", + testSubject.getAcceptedContentType(mockRequest)); + + verify(mockRequest); + } +} -- GitLab