2 * Copyright 2008, 2009 Electronic Business Systems Ltd.
4 * This file is part of GSS.
6 * GSS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GSS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
19 package gr.ebs.gss.server.rest;
21 import gr.ebs.gss.client.exceptions.DuplicateNameException;
22 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
23 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
24 import gr.ebs.gss.client.exceptions.RpcException;
25 import gr.ebs.gss.server.domain.User;
26 import gr.ebs.gss.server.domain.dto.GroupDTO;
27 import gr.ebs.gss.server.domain.dto.UserDTO;
28 import gr.ebs.gss.server.ejb.TransactionHelper;
30 import java.io.IOException;
31 import java.net.URLDecoder;
32 import java.net.URLEncoder;
33 import java.util.List;
34 import java.util.concurrent.Callable;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.json.JSONArray;
42 import org.json.JSONException;
43 import org.json.JSONObject;
47 * A class that handles operations on the 'groups' namespace.
51 public class GroupsHandler extends RequestHandler {
55 private static Log logger = LogFactory.getLog(GroupsHandler.class);
58 * Serve the groups namespace for the user.
60 * @param req The servlet request we are processing
61 * @param resp The servlet response we are processing
62 * @throws IOException if an input/output error occurs
64 void serveGroups(HttpServletRequest req, HttpServletResponse resp) throws IOException {
65 String parentUrl = getContextPath(req, true);
66 String path = getInnerPath(req, PATH_GROUPS);
70 User user = getUser(req);
71 User owner = getOwner(req);
72 if (!owner.equals(user)) {
73 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
77 // Request to serve all groups
79 List<GroupDTO> groups = getService().getGroups(owner.getId());
80 JSONArray json = new JSONArray();
81 for (GroupDTO group: groups) {
82 JSONObject j = new JSONObject();
83 j.put("name", group.getName()).
84 put("uri", parentUrl + URLEncoder.encode(group.getName(),"UTF-8"));
88 sendJson(req, resp, json.toString());
89 } catch (ObjectNotFoundException e) {
90 logger.error("User not found", e);
91 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
93 } catch (RpcException e) {
95 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
97 } catch (JSONException e) {
99 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
103 // Chop any trailing slash
104 path = path.endsWith("/")? path.substring(0, path.length()-1): path;
105 // Chop any leading slash
106 path = path.startsWith("/")? path.substring(1): path;
107 int slash = path.indexOf('/');
110 // Request to serve group member
111 if (logger.isDebugEnabled())
112 logger.debug("Serving member " + path.substring(slash + 1) +
113 " from group " + path.substring(0, slash));
114 GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
115 for (UserDTO u: group.getMembers())
116 if (u.getUsername().equals(path.substring(slash + 1))) {
117 // Build the proper parent URL
118 String pathInfo = req.getPathInfo();
119 parentUrl = parentUrl.replaceFirst(pathInfo, "");
120 JSONObject json = new JSONObject();
121 json.put("username", u.getUsername()).put("name", u.getName()).
122 put("home", parentUrl + u.getUsername());
124 sendJson(req, resp, json.toString());
127 // Request to serve group
128 if (logger.isDebugEnabled())
129 logger.debug("Serving group " + path);
130 GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
131 JSONArray json = new JSONArray();
132 for (UserDTO u: group.getMembers())
133 json.put(parentUrl + u.getUsername());
135 sendJson(req, resp, json.toString());
137 } catch (ObjectNotFoundException e) {
139 resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
141 } catch (RpcException e) {
143 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
145 } catch (JSONException e) {
147 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
151 // Workaround for IE's broken caching behavior.
152 resp.setHeader("Expires", "-1");
156 * Handle POST requests in the groups namespace.
158 * @param req The servlet request we are processing
159 * @param resp The servlet response we are processing
160 * @throws IOException if an input/output error occurs
162 void postGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
163 // Identify the requested resource path
164 String path = getInnerPath(req, PATH_GROUPS);
169 User user = getUser(req);
170 final User owner = getOwner(req);
171 if (!owner.equals(user))
172 throw new InsufficientPermissionsException("User " + user.getUsername()
173 + " does not have permission to modify the groups owned by "
174 + owner.getUsername());
175 if (path.equals("/")) {
176 // Request to add group
177 final String group = req.getParameter(GROUP_PARAMETER);
178 if (logger.isDebugEnabled())
179 logger.debug("Adding group " + group);
180 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
182 public Void call() throws Exception {
183 getService().createGroup(owner.getId(), group);
187 resp.setStatus(HttpServletResponse.SC_CREATED);
189 // Request to add group member
190 String username = req.getParameter(USERNAME_PARAMETER);
191 // Chop any trailing slash
192 path = path.endsWith("/")? path.substring(0, path.length()-1): path;
193 // Chop any leading slash
194 path = path.startsWith("/")? path.substring(1): path;
195 if (logger.isDebugEnabled())
196 logger.debug("Adding member " + username +
197 " to group " + path);
198 final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
199 final User member = getService().findUser(username);
200 if (member == null) {
201 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "User " + username + " not found");
204 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
206 public Void call() throws Exception {
207 getService().addUserToGroup(owner.getId(), group.getId(), member.getId());
211 resp.setStatus(HttpServletResponse.SC_CREATED);
213 // Workaround for IE's broken caching behavior.
214 resp.setHeader("Expires", "-1");
215 } catch (ObjectNotFoundException e) {
216 resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
217 } catch (IllegalArgumentException e) {
218 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
219 } catch (DuplicateNameException e) {
220 resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
221 } catch (RpcException e) {
223 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
224 } catch (InsufficientPermissionsException e) {
225 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
226 } catch (Exception e) {
228 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
234 * Handle DELETE requests in the groups namespace.
236 * @param req The servlet request we are processing
237 * @param resp The servlet response we are processing
238 * @throws IOException if an input/output error occurs
240 void deleteGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
241 String path = getInnerPath(req, PATH_GROUPS);
245 if (path.equals("/"))
246 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, METHOD_GET + ", " + METHOD_POST);
248 // Chop any trailing slash
249 path = path.endsWith("/")? path.substring(0, path.length()-1): path;
250 // Chop any leading slash
251 path = path.startsWith("/")? path.substring(1): path;
252 int slash = path.indexOf('/');
254 User user = getUser(req);
255 final User owner = getOwner(req);
256 if (!owner.equals(user))
257 throw new InsufficientPermissionsException("User " + user.getUsername()
258 + " does not have permission to modify the groups owned by "
259 + owner.getUsername());
261 // Request to delete group member
262 if (logger.isDebugEnabled())
263 logger.debug("Removing member " + path.substring(slash + 1) +
264 " from group " + path.substring(0, slash));
265 final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
266 for (final UserDTO u: group.getMembers())
267 if (u.getUsername().equals(path.substring(slash + 1)))
268 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
270 public Void call() throws Exception {
271 getService().removeMemberFromGroup(owner.getId(), group.getId(), u.getId());
276 if (logger.isDebugEnabled())
277 logger.debug("Removing group " + path);
278 final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
279 new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
281 public Void call() throws Exception {
282 getService().deleteGroup(owner.getId(), group.getId());
287 resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
288 // Workaround for IE's broken caching behavior.
289 resp.setHeader("Expires", "-1");
290 } catch (RpcException e) {
292 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
293 } catch (ObjectNotFoundException e) {
294 resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
295 } catch (InsufficientPermissionsException e) {
296 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
297 } catch (Exception e) {
299 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);