Statistics
| Branch: | Tag: | Revision:

root / src / org / gss_project / gss / server / rest / GroupsHandler.java @ 1205:fbeae20462e6

History | View | Annotate | Download (12 kB)

1
/*
2
 * Copyright 2008, 2009 Electronic Business Systems Ltd.
3
 *
4
 * This file is part of GSS.
5
 *
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.
10
 *
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.
15
 *
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/>.
18
 */
19
package org.gss_project.gss.server.rest;
20

    
21
import org.gss_project.gss.common.exceptions.DuplicateNameException;
22
import org.gss_project.gss.common.exceptions.InsufficientPermissionsException;
23
import org.gss_project.gss.common.exceptions.ObjectNotFoundException;
24
import org.gss_project.gss.common.exceptions.RpcException;
25
import org.gss_project.gss.server.domain.Group;
26
import org.gss_project.gss.server.domain.User;
27
import org.gss_project.gss.server.ejb.TransactionHelper;
28

    
29
import java.io.IOException;
30
import java.net.URLDecoder;
31
import java.net.URLEncoder;
32
import java.util.List;
33
import java.util.concurrent.Callable;
34

    
35
import javax.servlet.http.HttpServletRequest;
36
import javax.servlet.http.HttpServletResponse;
37

    
38
import org.apache.commons.logging.Log;
39
import org.apache.commons.logging.LogFactory;
40
import org.json.JSONArray;
41
import org.json.JSONException;
42
import org.json.JSONObject;
43

    
44

    
45
/**
46
 * A class that handles operations on the 'groups' namespace.
47
 *
48
 * @author past
49
 */
50
public class GroupsHandler extends RequestHandler {
51
        /**
52
         * The logger.
53
         */
54
        private static Log logger = LogFactory.getLog(GroupsHandler.class);
55

    
56
    /**
57
     * Serve the groups namespace for the user.
58
     *
59
     * @param req The servlet request we are processing
60
     * @param resp The servlet response we are processing
61
     * @throws IOException if an input/output error occurs
62
         */
63
        void serveGroups(HttpServletRequest req, HttpServletResponse resp) throws IOException {
64
            String parentUrl = getContextPath(req, true);
65
        String path = getInnerPath(req, PATH_GROUPS);
66
                if (path.equals(""))
67
                        path = "/";
68

    
69
            User user = getUser(req);
70
            User owner = getOwner(req);
71
            if (!owner.equals(user)) {
72
                    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
73
                    return;
74
            }
75
            if (path.equals("/"))
76
                        // Request to serve all groups
77
                try {
78
                    List<Group> groups = getService().getGroups(owner.getId());
79
                    JSONArray json = new JSONArray();
80
                    for (Group group: groups) {
81
                            JSONObject j = new JSONObject();
82
                            j.put("name", group.getName()).
83
                                    put("uri", parentUrl + URLEncoder.encode(group.getName(),"UTF-8"));
84
                                json.put(j);
85
                    }
86

    
87
                    sendJson(req, resp, json.toString());
88
                    } catch (ObjectNotFoundException e) {
89
                            logger.error("User not found", e);
90
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
91
                            return;
92
                    } catch (RpcException e) {
93
                            logger.error("", e);
94
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
95
                            return;
96
                    } catch (JSONException e) {
97
                            logger.error("", e);
98
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
99
                            return;
100
                        }
101
                else {
102
                    // Chop any trailing slash
103
                path = path.endsWith("/")? path.substring(0, path.length()-1): path;
104
                // Chop any leading slash
105
                path = path.startsWith("/")? path.substring(1): path;
106
                int slash = path.indexOf('/');
107
                        try {
108
                        if (slash != -1) {
109
                                // Request to serve group member
110
                                if (logger.isDebugEnabled())
111
                                        logger.debug("Serving member " + path.substring(slash + 1) +
112
                                                                " from group " + path.substring(0, slash));
113
                                Group group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
114
                                group = getService().expandGroup(group);
115
                                for (User 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());
123

    
124
                                            sendJson(req, resp, json.toString());
125
                                        }
126
                        } else {
127
                                // Request to serve group
128
                                if (logger.isDebugEnabled())
129
                                        logger.debug("Serving group " + path);
130
                                    Group group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
131
                                    group = getService().expandGroup(group);
132
                                JSONArray json = new JSONArray();
133
                                for (User u: group.getMembers())
134
                                            json.put(parentUrl + u.getUsername());
135

    
136
                                sendJson(req, resp, json.toString());
137
                        }
138
                        } catch (ObjectNotFoundException e) {
139
                            logger.error("", e);
140
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
141
                            return;
142
                        } catch (RpcException e) {
143
                            logger.error("", e);
144
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
145
                            return;
146
                        } catch (JSONException e) {
147
                                logger.error("", e);
148
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
149
                                return;
150
                        }
151
            }
152
            // Workaround for IE's broken caching behavior.
153
                resp.setHeader("Expires", "-1");
154
        }
155

    
156
        /**
157
         * Handle POST requests in the groups namespace.
158
         *
159
     * @param req The servlet request we are processing
160
     * @param resp The servlet response we are processing
161
     * @throws IOException if an input/output error occurs
162
         */
163
        void postGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
164
            // Identify the requested resource path
165
        String path = getInnerPath(req, PATH_GROUPS);
166
                if (path.equals(""))
167
                        path = "/";
168

    
169
                try {
170
                    User user = getUser(req);
171
                final User owner = getOwner(req);
172
                if (!owner.equals(user))
173
                        throw new InsufficientPermissionsException("User " + user.getUsername()
174
                                                + " does not have permission to modify the groups owned by "
175
                                                + owner.getUsername());
176
                    if (path.equals("/")) {
177
                        // Request to add group
178
                            final String group = req.getParameter(GROUP_PARAMETER);
179
                            if (!isValidResourceName(group)) {
180
                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
181
                                return;
182
                        }
183
                            if (logger.isDebugEnabled())
184
                                    logger.debug("Adding group " + group);
185
                                    new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
186
                                                @Override
187
                                                public Void call() throws Exception {
188
                                                        getService().createGroup(owner.getId(), group);
189
                                                        return null;
190
                                                }
191
                                        });
192
                                resp.setStatus(HttpServletResponse.SC_CREATED);
193
                    } else {
194
                        // Request to add group member
195
                        String username = req.getParameter(USERNAME_PARAMETER);
196
                            if (!isValidResourceName(username)) {
197
                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
198
                                return;
199
                        }
200
                            // Chop any trailing slash
201
                        path = path.endsWith("/")? path.substring(0, path.length()-1): path;
202
                        // Chop any leading slash
203
                        path = path.startsWith("/")? path.substring(1): path;
204
                        if (logger.isDebugEnabled())
205
                                logger.debug("Adding member " + username +
206
                                                        " to group " + path);
207
                        final Group group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
208
                        final User member = getService().findUser(username);
209
                        if (member == null) {
210
                                resp.sendError(HttpServletResponse.SC_NOT_FOUND, "User " + username + " not found");
211
                                return;
212
                        }
213
                        new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
214
                                        @Override
215
                                        public Void call() throws Exception {
216
                                                getService().addUserToGroup(owner.getId(), group.getId(), member.getId());
217
                                                return null;
218
                                        }
219
                                });
220
                        resp.setStatus(HttpServletResponse.SC_CREATED);
221
                    }
222
                    // Workaround for IE's broken caching behavior.
223
                        resp.setHeader("Expires", "-1");
224
                } catch (ObjectNotFoundException e) {
225
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
226
                } catch (IllegalArgumentException e) {
227
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
228
                } catch (DuplicateNameException e) {
229
                        resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
230
                } catch (RpcException e) {
231
                        logger.error("", e);
232
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
233
                } catch (InsufficientPermissionsException e) {
234
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
235
                } catch (Exception e) {
236
                        logger.error("", e);
237
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
238
                }
239

    
240
        }
241

    
242
        /**
243
         * Handle DELETE requests in the groups namespace.
244
         *
245
     * @param req The servlet request we are processing
246
     * @param resp The servlet response we are processing
247
     * @throws IOException if an input/output error occurs
248
         */
249
        void deleteGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
250
        String path = getInnerPath(req, PATH_GROUPS);
251
                if (path.equals(""))
252
                        path = "/";
253

    
254
            if (path.equals("/"))
255
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, METHOD_GET + ", " + METHOD_POST);
256
                else {
257
                    // Chop any trailing slash
258
                path = path.endsWith("/")? path.substring(0, path.length()-1): path;
259
                // Chop any leading slash
260
                path = path.startsWith("/")? path.substring(1): path;
261
                int slash = path.indexOf('/');
262
                try {
263
                    User user = getUser(req);
264
                    final User owner = getOwner(req);
265
                    if (!owner.equals(user))
266
                            throw new InsufficientPermissionsException("User " + user.getUsername()
267
                                                    + " does not have permission to modify the groups owned by "
268
                                                    + owner.getUsername());
269
                    if (slash != -1) {
270
                            // Request to delete group member
271
                            if (logger.isDebugEnabled())
272
                                    logger.debug("Removing member " + path.substring(slash + 1) +
273
                                                            " from group " + path.substring(0, slash));
274
                            final Group group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
275
                            for (final User u: group.getMembers())
276
                                    if (u.getUsername().equals(path.substring(slash + 1)))
277
                                            new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
278
                                                    @Override
279
                                                    public Void call() throws Exception {
280
                                                            getService().removeMemberFromGroup(owner.getId(), group.getId(), u.getId());
281
                                                            return null;
282
                                                    }
283
                                            });
284
                    } else {
285
                            if (logger.isDebugEnabled())
286
                                    logger.debug("Removing group " + path);
287
                                final Group group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
288
                                new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
289
                                            @Override
290
                                            public Void call() throws Exception {
291
                                                    getService().deleteGroup(owner.getId(), group.getId());
292
                                                    return null;
293
                                            }
294
                                    });
295
                    }
296
                        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
297
                        // Workaround for IE's broken caching behavior.
298
                            resp.setHeader("Expires", "-1");
299
                } catch (RpcException e) {
300
                            logger.error("", e);
301
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
302
                } catch (ObjectNotFoundException e) {
303
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
304
                        } catch (InsufficientPermissionsException e) {
305
                                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
306
                        } catch (Exception e) {
307
                            logger.error("", e);
308
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
309
                        }
310
            }
311
        }
312

    
313
}