Statistics
| Branch: | Tag: | Revision:

root / src / gr / ebs / gss / server / rest / GroupsHandler.java @ 41ccd791

History | View | Annotate | Download (11.9 kB)

1 14ad7326 pastith
/*
2 14ad7326 pastith
 * Copyright 2008, 2009 Electronic Business Systems Ltd.
3 14ad7326 pastith
 *
4 14ad7326 pastith
 * This file is part of GSS.
5 14ad7326 pastith
 *
6 14ad7326 pastith
 * GSS is free software: you can redistribute it and/or modify
7 14ad7326 pastith
 * it under the terms of the GNU General Public License as published by
8 14ad7326 pastith
 * the Free Software Foundation, either version 3 of the License, or
9 14ad7326 pastith
 * (at your option) any later version.
10 14ad7326 pastith
 *
11 14ad7326 pastith
 * GSS is distributed in the hope that it will be useful,
12 14ad7326 pastith
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 14ad7326 pastith
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 14ad7326 pastith
 * GNU General Public License for more details.
15 14ad7326 pastith
 *
16 14ad7326 pastith
 * You should have received a copy of the GNU General Public License
17 14ad7326 pastith
 * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18 14ad7326 pastith
 */
19 14ad7326 pastith
package gr.ebs.gss.server.rest;
20 14ad7326 pastith
21 14ad7326 pastith
import gr.ebs.gss.client.exceptions.DuplicateNameException;
22 14ad7326 pastith
import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
23 14ad7326 pastith
import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
24 14ad7326 pastith
import gr.ebs.gss.client.exceptions.RpcException;
25 14ad7326 pastith
import gr.ebs.gss.server.domain.User;
26 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.GroupDTO;
27 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.UserDTO;
28 3b6b7f25 Dimitris Routsis
import gr.ebs.gss.server.ejb.TransactionHelper;
29 14ad7326 pastith
30 14ad7326 pastith
import java.io.IOException;
31 9869aeb7 koutsoub
import java.net.URLDecoder;
32 9869aeb7 koutsoub
import java.net.URLEncoder;
33 14ad7326 pastith
import java.util.List;
34 2f1a60e0 Dimitris Routsis
import java.util.concurrent.Callable;
35 14ad7326 pastith
36 14ad7326 pastith
import javax.servlet.http.HttpServletRequest;
37 14ad7326 pastith
import javax.servlet.http.HttpServletResponse;
38 14ad7326 pastith
39 14ad7326 pastith
import org.apache.commons.logging.Log;
40 14ad7326 pastith
import org.apache.commons.logging.LogFactory;
41 14ad7326 pastith
import org.json.JSONArray;
42 14ad7326 pastith
import org.json.JSONException;
43 14ad7326 pastith
import org.json.JSONObject;
44 14ad7326 pastith
45 14ad7326 pastith
46 14ad7326 pastith
/**
47 14ad7326 pastith
 * A class that handles operations on the 'groups' namespace.
48 14ad7326 pastith
 *
49 14ad7326 pastith
 * @author past
50 14ad7326 pastith
 */
51 14ad7326 pastith
public class GroupsHandler extends RequestHandler {
52 14ad7326 pastith
        /**
53 14ad7326 pastith
         * The logger.
54 14ad7326 pastith
         */
55 14ad7326 pastith
        private static Log logger = LogFactory.getLog(GroupsHandler.class);
56 14ad7326 pastith
57 14ad7326 pastith
    /**
58 14ad7326 pastith
     * Serve the groups namespace for the user.
59 14ad7326 pastith
     *
60 14ad7326 pastith
     * @param req The servlet request we are processing
61 14ad7326 pastith
     * @param resp The servlet response we are processing
62 14ad7326 pastith
     * @throws IOException if an input/output error occurs
63 14ad7326 pastith
         */
64 14ad7326 pastith
        void serveGroups(HttpServletRequest req, HttpServletResponse resp) throws IOException {
65 14ad7326 pastith
            String parentUrl = getContextPath(req, true);
66 14ad7326 pastith
        String path = getInnerPath(req, PATH_GROUPS);
67 14ad7326 pastith
                if (path.equals(""))
68 14ad7326 pastith
                        path = "/";
69 14ad7326 pastith
70 14ad7326 pastith
            User user = getUser(req);
71 14ad7326 pastith
            User owner = getOwner(req);
72 14ad7326 pastith
            if (!owner.equals(user)) {
73 14ad7326 pastith
                    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
74 14ad7326 pastith
                    return;
75 14ad7326 pastith
            }
76 da7b63f2 pastith
            if (path.equals("/"))
77 da7b63f2 pastith
                        // Request to serve all groups
78 14ad7326 pastith
                try {
79 da7b63f2 pastith
                    List<GroupDTO> groups = getService().getGroups(owner.getId());
80 da7b63f2 pastith
                    JSONArray json = new JSONArray();
81 da7b63f2 pastith
                    for (GroupDTO group: groups) {
82 da7b63f2 pastith
                            JSONObject j = new JSONObject();
83 da7b63f2 pastith
                            j.put("name", group.getName()).
84 9869aeb7 koutsoub
                                    put("uri", parentUrl + URLEncoder.encode(group.getName(),"UTF-8"));
85 da7b63f2 pastith
                                json.put(j);
86 da7b63f2 pastith
                    }
87 da7b63f2 pastith
88 da7b63f2 pastith
                    sendJson(req, resp, json.toString());
89 14ad7326 pastith
                    } catch (ObjectNotFoundException e) {
90 14ad7326 pastith
                            logger.error("User not found", e);
91 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
92 14ad7326 pastith
                            return;
93 14ad7326 pastith
                    } catch (RpcException e) {
94 14ad7326 pastith
                            logger.error("", e);
95 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
96 14ad7326 pastith
                            return;
97 da7b63f2 pastith
                    } catch (JSONException e) {
98 da7b63f2 pastith
                            logger.error("", e);
99 da7b63f2 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
100 da7b63f2 pastith
                            return;
101 da7b63f2 pastith
                        }
102 da7b63f2 pastith
                else {
103 14ad7326 pastith
                    // Chop any trailing slash
104 14ad7326 pastith
                path = path.endsWith("/")? path.substring(0, path.length()-1): path;
105 14ad7326 pastith
                // Chop any leading slash
106 14ad7326 pastith
                path = path.startsWith("/")? path.substring(1): path;
107 14ad7326 pastith
                int slash = path.indexOf('/');
108 14ad7326 pastith
                        try {
109 14ad7326 pastith
                        if (slash != -1) {
110 14ad7326 pastith
                                // Request to serve group member
111 14ad7326 pastith
                                if (logger.isDebugEnabled())
112 14ad7326 pastith
                                        logger.debug("Serving member " + path.substring(slash + 1) +
113 14ad7326 pastith
                                                                " from group " + path.substring(0, slash));
114 9869aeb7 koutsoub
                                GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
115 14ad7326 pastith
                                for (UserDTO u: group.getMembers())
116 14ad7326 pastith
                                        if (u.getUsername().equals(path.substring(slash + 1))) {
117 14ad7326 pastith
                                                    // Build the proper parent URL
118 14ad7326 pastith
                                                    String pathInfo = req.getPathInfo();
119 14ad7326 pastith
                                                    parentUrl = parentUrl.replaceFirst(pathInfo, "");
120 14ad7326 pastith
                                            JSONObject json = new JSONObject();
121 14ad7326 pastith
                                                json.put("username", u.getUsername()).put("name", u.getName()).
122 14ad7326 pastith
                                                                put("home", parentUrl + u.getUsername());
123 14ad7326 pastith
124 14ad7326 pastith
                                            sendJson(req, resp, json.toString());
125 14ad7326 pastith
                                        }
126 14ad7326 pastith
                        } else {
127 14ad7326 pastith
                                // Request to serve group
128 14ad7326 pastith
                                if (logger.isDebugEnabled())
129 14ad7326 pastith
                                        logger.debug("Serving group " + path);
130 9869aeb7 koutsoub
                                    GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
131 14ad7326 pastith
                                JSONArray json = new JSONArray();
132 14ad7326 pastith
                                for (UserDTO u: group.getMembers())
133 14ad7326 pastith
                                            json.put(parentUrl + u.getUsername());
134 14ad7326 pastith
135 14ad7326 pastith
                                sendJson(req, resp, json.toString());
136 14ad7326 pastith
                        }
137 14ad7326 pastith
                        } catch (ObjectNotFoundException e) {
138 14ad7326 pastith
                            logger.error("", e);
139 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
140 14ad7326 pastith
                            return;
141 14ad7326 pastith
                        } catch (RpcException e) {
142 14ad7326 pastith
                            logger.error("", e);
143 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
144 14ad7326 pastith
                            return;
145 14ad7326 pastith
                        } catch (JSONException e) {
146 14ad7326 pastith
                                logger.error("", e);
147 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
148 14ad7326 pastith
                                return;
149 14ad7326 pastith
                        }
150 14ad7326 pastith
            }
151 b722599f droutsis
            // Workaround for IE's broken caching behavior.
152 b722599f droutsis
                resp.setHeader("Expires", "-1");
153 14ad7326 pastith
        }
154 14ad7326 pastith
155 14ad7326 pastith
        /**
156 14ad7326 pastith
         * Handle POST requests in the groups namespace.
157 14ad7326 pastith
         *
158 14ad7326 pastith
     * @param req The servlet request we are processing
159 14ad7326 pastith
     * @param resp The servlet response we are processing
160 14ad7326 pastith
     * @throws IOException if an input/output error occurs
161 14ad7326 pastith
         */
162 14ad7326 pastith
        void postGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
163 14ad7326 pastith
            // Identify the requested resource path
164 14ad7326 pastith
        String path = getInnerPath(req, PATH_GROUPS);
165 14ad7326 pastith
                if (path.equals(""))
166 14ad7326 pastith
                        path = "/";
167 14ad7326 pastith
168 14ad7326 pastith
                try {
169 14ad7326 pastith
                    User user = getUser(req);
170 2f1a60e0 Dimitris Routsis
                final User owner = getOwner(req);
171 14ad7326 pastith
                if (!owner.equals(user))
172 14ad7326 pastith
                        throw new InsufficientPermissionsException("User " + user.getUsername()
173 14ad7326 pastith
                                                + " does not have permission to modify the groups owned by "
174 14ad7326 pastith
                                                + owner.getUsername());
175 14ad7326 pastith
                    if (path.equals("/")) {
176 14ad7326 pastith
                        // Request to add group
177 2f1a60e0 Dimitris Routsis
                            final String group = req.getParameter(GROUP_PARAMETER);
178 4315bcc5 Panagiotis Astithas
                            if (!isValidResourceName(group)) {
179 4315bcc5 Panagiotis Astithas
                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
180 4315bcc5 Panagiotis Astithas
                                return;
181 4315bcc5 Panagiotis Astithas
                        }
182 14ad7326 pastith
                            if (logger.isDebugEnabled())
183 14ad7326 pastith
                                    logger.debug("Adding group " + group);
184 2f1a60e0 Dimitris Routsis
                                    new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
185 2f1a60e0 Dimitris Routsis
                                                @Override
186 2f1a60e0 Dimitris Routsis
                                                public Void call() throws Exception {
187 2f1a60e0 Dimitris Routsis
                                                        getService().createGroup(owner.getId(), group);
188 2f1a60e0 Dimitris Routsis
                                                        return null;
189 2f1a60e0 Dimitris Routsis
                                                }
190 2f1a60e0 Dimitris Routsis
                                        });
191 14ad7326 pastith
                                resp.setStatus(HttpServletResponse.SC_CREATED);
192 14ad7326 pastith
                    } else {
193 14ad7326 pastith
                        // Request to add group member
194 14ad7326 pastith
                        String username = req.getParameter(USERNAME_PARAMETER);
195 4315bcc5 Panagiotis Astithas
                            if (!isValidResourceName(username)) {
196 4315bcc5 Panagiotis Astithas
                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
197 4315bcc5 Panagiotis Astithas
                                return;
198 4315bcc5 Panagiotis Astithas
                        }
199 14ad7326 pastith
                            // Chop any trailing slash
200 14ad7326 pastith
                        path = path.endsWith("/")? path.substring(0, path.length()-1): path;
201 14ad7326 pastith
                        // Chop any leading slash
202 14ad7326 pastith
                        path = path.startsWith("/")? path.substring(1): path;
203 14ad7326 pastith
                        if (logger.isDebugEnabled())
204 14ad7326 pastith
                                logger.debug("Adding member " + username +
205 14ad7326 pastith
                                                        " to group " + path);
206 2f1a60e0 Dimitris Routsis
                        final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
207 2f1a60e0 Dimitris Routsis
                        final User member = getService().findUser(username);
208 52359e20 pastith
                        if (member == null) {
209 52359e20 pastith
                                resp.sendError(HttpServletResponse.SC_NOT_FOUND, "User " + username + " not found");
210 52359e20 pastith
                                return;
211 52359e20 pastith
                        }
212 2f1a60e0 Dimitris Routsis
                        new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
213 2f1a60e0 Dimitris Routsis
                                        @Override
214 2f1a60e0 Dimitris Routsis
                                        public Void call() throws Exception {
215 2f1a60e0 Dimitris Routsis
                                                getService().addUserToGroup(owner.getId(), group.getId(), member.getId());
216 2f1a60e0 Dimitris Routsis
                                                return null;
217 2f1a60e0 Dimitris Routsis
                                        }
218 2f1a60e0 Dimitris Routsis
                                });
219 14ad7326 pastith
                        resp.setStatus(HttpServletResponse.SC_CREATED);
220 14ad7326 pastith
                    }
221 b722599f droutsis
                    // Workaround for IE's broken caching behavior.
222 b722599f droutsis
                        resp.setHeader("Expires", "-1");
223 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
224 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
225 c25c6507 Dimitris Routsis
                } catch (IllegalArgumentException e) {
226 c25c6507 Dimitris Routsis
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
227 14ad7326 pastith
                } catch (DuplicateNameException e) {
228 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
229 14ad7326 pastith
                } catch (RpcException e) {
230 14ad7326 pastith
                        logger.error("", e);
231 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
232 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
233 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
234 2f1a60e0 Dimitris Routsis
                } catch (Exception e) {
235 2f1a60e0 Dimitris Routsis
                        logger.error("", e);
236 2f1a60e0 Dimitris Routsis
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
237 14ad7326 pastith
                }
238 2f1a60e0 Dimitris Routsis
239 14ad7326 pastith
        }
240 14ad7326 pastith
241 14ad7326 pastith
        /**
242 14ad7326 pastith
         * Handle DELETE requests in the groups namespace.
243 14ad7326 pastith
         *
244 14ad7326 pastith
     * @param req The servlet request we are processing
245 14ad7326 pastith
     * @param resp The servlet response we are processing
246 14ad7326 pastith
     * @throws IOException if an input/output error occurs
247 14ad7326 pastith
         */
248 14ad7326 pastith
        void deleteGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
249 14ad7326 pastith
        String path = getInnerPath(req, PATH_GROUPS);
250 14ad7326 pastith
                if (path.equals(""))
251 14ad7326 pastith
                        path = "/";
252 14ad7326 pastith
253 14ad7326 pastith
            if (path.equals("/"))
254 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, METHOD_GET + ", " + METHOD_POST);
255 14ad7326 pastith
                else {
256 14ad7326 pastith
                    // Chop any trailing slash
257 14ad7326 pastith
                path = path.endsWith("/")? path.substring(0, path.length()-1): path;
258 14ad7326 pastith
                // Chop any leading slash
259 14ad7326 pastith
                path = path.startsWith("/")? path.substring(1): path;
260 14ad7326 pastith
                int slash = path.indexOf('/');
261 14ad7326 pastith
                try {
262 14ad7326 pastith
                    User user = getUser(req);
263 2f1a60e0 Dimitris Routsis
                    final User owner = getOwner(req);
264 14ad7326 pastith
                    if (!owner.equals(user))
265 14ad7326 pastith
                            throw new InsufficientPermissionsException("User " + user.getUsername()
266 14ad7326 pastith
                                                    + " does not have permission to modify the groups owned by "
267 14ad7326 pastith
                                                    + owner.getUsername());
268 14ad7326 pastith
                    if (slash != -1) {
269 14ad7326 pastith
                            // Request to delete group member
270 14ad7326 pastith
                            if (logger.isDebugEnabled())
271 14ad7326 pastith
                                    logger.debug("Removing member " + path.substring(slash + 1) +
272 14ad7326 pastith
                                                            " from group " + path.substring(0, slash));
273 2f1a60e0 Dimitris Routsis
                            final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
274 2f1a60e0 Dimitris Routsis
                            for (final UserDTO u: group.getMembers())
275 14ad7326 pastith
                                    if (u.getUsername().equals(path.substring(slash + 1)))
276 2f1a60e0 Dimitris Routsis
                                            new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
277 2f1a60e0 Dimitris Routsis
                                                    @Override
278 2f1a60e0 Dimitris Routsis
                                                    public Void call() throws Exception {
279 2f1a60e0 Dimitris Routsis
                                                            getService().removeMemberFromGroup(owner.getId(), group.getId(), u.getId());
280 2f1a60e0 Dimitris Routsis
                                                            return null;
281 2f1a60e0 Dimitris Routsis
                                                    }
282 2f1a60e0 Dimitris Routsis
                                            });
283 14ad7326 pastith
                    } else {
284 14ad7326 pastith
                            if (logger.isDebugEnabled())
285 14ad7326 pastith
                                    logger.debug("Removing group " + path);
286 2f1a60e0 Dimitris Routsis
                                final GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
287 2f1a60e0 Dimitris Routsis
                                new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
288 2f1a60e0 Dimitris Routsis
                                            @Override
289 2f1a60e0 Dimitris Routsis
                                            public Void call() throws Exception {
290 2f1a60e0 Dimitris Routsis
                                                    getService().deleteGroup(owner.getId(), group.getId());
291 2f1a60e0 Dimitris Routsis
                                                    return null;
292 2f1a60e0 Dimitris Routsis
                                            }
293 2f1a60e0 Dimitris Routsis
                                    });
294 14ad7326 pastith
                    }
295 14ad7326 pastith
                        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
296 b722599f droutsis
                        // Workaround for IE's broken caching behavior.
297 b722599f droutsis
                            resp.setHeader("Expires", "-1");
298 14ad7326 pastith
                } catch (RpcException e) {
299 14ad7326 pastith
                            logger.error("", e);
300 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
301 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
302 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
303 14ad7326 pastith
                        } catch (InsufficientPermissionsException e) {
304 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
305 2f1a60e0 Dimitris Routsis
                        } catch (Exception e) {
306 2f1a60e0 Dimitris Routsis
                            logger.error("", e);
307 2f1a60e0 Dimitris Routsis
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
308 14ad7326 pastith
                        }
309 14ad7326 pastith
            }
310 14ad7326 pastith
        }
311 14ad7326 pastith
312 14ad7326 pastith
}