Statistics
| Branch: | Tag: | Revision:

root / src / gr / ebs / gss / server / rest / FilesHandler.java @ 77dcb3f1

History | View | Annotate | Download (68.7 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.GSSIOException;
23 14ad7326 pastith
import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
24 14ad7326 pastith
import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
25 14ad7326 pastith
import gr.ebs.gss.client.exceptions.QuotaExceededException;
26 14ad7326 pastith
import gr.ebs.gss.client.exceptions.RpcException;
27 f5903adf pastith
import gr.ebs.gss.server.domain.FileUploadStatus;
28 14ad7326 pastith
import gr.ebs.gss.server.domain.User;
29 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.FileBodyDTO;
30 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
31 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.FolderDTO;
32 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.GroupDTO;
33 2f2da9c7 pastith
import gr.ebs.gss.server.domain.dto.PermissionDTO;
34 e150a336 pastith
import gr.ebs.gss.server.ejb.ExternalAPI;
35 14ad7326 pastith
import gr.ebs.gss.server.webdav.Range;
36 14ad7326 pastith
37 14ad7326 pastith
import java.io.BufferedReader;
38 14ad7326 pastith
import java.io.ByteArrayInputStream;
39 14ad7326 pastith
import java.io.ByteArrayOutputStream;
40 14ad7326 pastith
import java.io.File;
41 14ad7326 pastith
import java.io.FileInputStream;
42 14ad7326 pastith
import java.io.FileNotFoundException;
43 14ad7326 pastith
import java.io.IOException;
44 14ad7326 pastith
import java.io.InputStream;
45 95da8819 koutsoub
import java.io.InputStreamReader;
46 14ad7326 pastith
import java.io.OutputStreamWriter;
47 14ad7326 pastith
import java.io.PrintWriter;
48 5e2b8ec6 koutsoub
import java.io.UnsupportedEncodingException;
49 14ad7326 pastith
import java.net.URI;
50 14ad7326 pastith
import java.net.URISyntaxException;
51 47d800f9 pastith
import java.net.URLDecoder;
52 47d800f9 pastith
import java.net.URLEncoder;
53 14ad7326 pastith
import java.util.ArrayList;
54 fc5ef2cc droutsis
import java.util.Collection;
55 8f128261 droutsis
import java.util.Date;
56 14ad7326 pastith
import java.util.HashSet;
57 14ad7326 pastith
import java.util.List;
58 14ad7326 pastith
import java.util.Set;
59 5e2b8ec6 koutsoub
import java.util.StringTokenizer;
60 204107fb Panagiotis Astithas
import java.util.concurrent.Callable;
61 14ad7326 pastith
62 14ad7326 pastith
import javax.servlet.ServletContext;
63 14ad7326 pastith
import javax.servlet.ServletException;
64 14ad7326 pastith
import javax.servlet.ServletOutputStream;
65 14ad7326 pastith
import javax.servlet.http.HttpServletRequest;
66 14ad7326 pastith
import javax.servlet.http.HttpServletResponse;
67 14ad7326 pastith
68 e150a336 pastith
import org.apache.commons.fileupload.FileItemIterator;
69 e150a336 pastith
import org.apache.commons.fileupload.FileItemStream;
70 e150a336 pastith
import org.apache.commons.fileupload.FileUploadException;
71 e150a336 pastith
import org.apache.commons.fileupload.ProgressListener;
72 e150a336 pastith
import org.apache.commons.fileupload.servlet.ServletFileUpload;
73 bda7d76d pastith
import org.apache.commons.fileupload.util.Streams;
74 bda7d76d pastith
import org.apache.commons.httpclient.util.DateParseException;
75 bda7d76d pastith
import org.apache.commons.httpclient.util.DateUtil;
76 14ad7326 pastith
import org.apache.commons.logging.Log;
77 14ad7326 pastith
import org.apache.commons.logging.LogFactory;
78 14ad7326 pastith
import org.json.JSONArray;
79 14ad7326 pastith
import org.json.JSONException;
80 14ad7326 pastith
import org.json.JSONObject;
81 14ad7326 pastith
82 14ad7326 pastith
83 14ad7326 pastith
/**
84 14ad7326 pastith
 * A class that handles operations on the 'files' namespace.
85 14ad7326 pastith
 *
86 14ad7326 pastith
 * @author past
87 14ad7326 pastith
 */
88 14ad7326 pastith
public class FilesHandler extends RequestHandler {
89 14ad7326 pastith
        /**
90 14ad7326 pastith
         * The request parameter name for fetching a different version.
91 14ad7326 pastith
         */
92 14ad7326 pastith
        private static final String VERSION_PARAM = "version";
93 14ad7326 pastith
94 14ad7326 pastith
        /**
95 14ad7326 pastith
         * The request attribute containing the owner of the destination URI
96 14ad7326 pastith
         * in a copy or move request.
97 14ad7326 pastith
         */
98 14ad7326 pastith
        private static final String DESTINATION_OWNER_ATTRIBUTE = "destOwner";
99 14ad7326 pastith
100 e150a336 pastith
        private static final int TRACK_PROGRESS_PERCENT = 5;
101 e150a336 pastith
102 14ad7326 pastith
        /**
103 bda7d76d pastith
         * The form parameter name that contains the signature in a browser POST upload.
104 bda7d76d pastith
         */
105 bda7d76d pastith
        private static final String AUTHORIZATION_PARAMETER = "Authorization";
106 bda7d76d pastith
107 bda7d76d pastith
        /**
108 bda7d76d pastith
         * The form parameter name that contains the date in a browser POST upload.
109 bda7d76d pastith
         */
110 bda7d76d pastith
        private static final String DATE_PARAMETER = "Date";
111 bda7d76d pastith
112 bda7d76d pastith
        /**
113 f5903adf pastith
         * The request parameter name for making an upload progress request.
114 f5903adf pastith
         */
115 f5903adf pastith
        private static final String PROGRESS_PARAMETER = "progress";
116 f5903adf pastith
117 f5903adf pastith
        /**
118 39c34533 pastith
         * The request parameter name for restoring a previous version of a file.
119 39c34533 pastith
         */
120 39c34533 pastith
        private static final String RESTORE_VERSION_PARAMETER = "restoreVersion";
121 39c34533 pastith
122 39c34533 pastith
        /**
123 14ad7326 pastith
         * The logger.
124 14ad7326 pastith
         */
125 14ad7326 pastith
        private static Log logger = LogFactory.getLog(FilesHandler.class);
126 14ad7326 pastith
127 14ad7326 pastith
        /**
128 14ad7326 pastith
         * The servlet context provided by the call site.
129 14ad7326 pastith
         */
130 14ad7326 pastith
        private ServletContext context;
131 14ad7326 pastith
132 14ad7326 pastith
        /**
133 14ad7326 pastith
         * @param servletContext
134 14ad7326 pastith
         */
135 14ad7326 pastith
        public FilesHandler(ServletContext servletContext) {
136 14ad7326 pastith
                context = servletContext;
137 14ad7326 pastith
        }
138 14ad7326 pastith
139 14ad7326 pastith
        /**
140 14ad7326 pastith
     * Serve the specified resource, optionally including the data content.
141 14ad7326 pastith
     *
142 14ad7326 pastith
     * @param req The servlet request we are processing
143 14ad7326 pastith
     * @param resp The servlet response we are creating
144 14ad7326 pastith
     * @param content Should the content be included?
145 14ad7326 pastith
     *
146 14ad7326 pastith
     * @exception IOException if an input/output error occurs
147 14ad7326 pastith
     * @exception ServletException if a servlet-specified error occurs
148 14ad7326 pastith
     * @throws RpcException
149 14ad7326 pastith
     * @throws InsufficientPermissionsException
150 14ad7326 pastith
     * @throws ObjectNotFoundException
151 14ad7326 pastith
     */
152 14ad7326 pastith
        @Override
153 14ad7326 pastith
        protected void serveResource(HttpServletRequest req, HttpServletResponse resp, boolean content)
154 14ad7326 pastith
                    throws IOException, ServletException {
155 14ad7326 pastith
                boolean authDeferred = getAuthDeferred(req);
156 14ad7326 pastith
        String path = getInnerPath(req, PATH_FILES);
157 14ad7326 pastith
                if (path.equals(""))
158 14ad7326 pastith
                        path = "/";
159 8fa7f8ff pastith
                try {
160 8fa7f8ff pastith
                        path = URLDecoder.decode(path, "UTF-8");
161 8fa7f8ff pastith
                } catch (IllegalArgumentException e) {
162 8fa7f8ff pastith
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
163 8fa7f8ff pastith
                        return;
164 8fa7f8ff pastith
                }
165 f5903adf pastith
            String progress = req.getParameter(PROGRESS_PARAMETER);
166 14ad7326 pastith
167 14ad7326 pastith
            if (logger.isDebugEnabled())
168 14ad7326 pastith
                        if (content)
169 14ad7326 pastith
                            logger.debug("Serving resource '" +        path + "' headers and data");
170 14ad7326 pastith
                    else
171 14ad7326 pastith
                            logger.debug("Serving resource '" +        path + "' headers only");
172 14ad7326 pastith
173 14ad7326 pastith
            User user = getUser(req);
174 14ad7326 pastith
            User owner = getOwner(req);
175 14ad7326 pastith
            if (user == null) user = owner;
176 14ad7326 pastith
        boolean exists = true;
177 14ad7326 pastith
        Object resource = null;
178 14ad7326 pastith
        FileHeaderDTO file = null;
179 14ad7326 pastith
        FolderDTO folder = null;
180 14ad7326 pastith
        try {
181 68410d59 pastith
                resource = getService().getResourceAtPath(owner.getId(), path, false);
182 14ad7326 pastith
        } catch (ObjectNotFoundException e) {
183 14ad7326 pastith
            exists = false;
184 14ad7326 pastith
        } catch (RpcException e) {
185 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
186 14ad7326 pastith
                        return;
187 14ad7326 pastith
                }
188 14ad7326 pastith
189 14ad7326 pastith
            if (!exists) {
190 14ad7326 pastith
                        if (authDeferred) {
191 14ad7326 pastith
                                // We do not want to leak information if the request
192 14ad7326 pastith
                                // was not authenticated.
193 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
194 14ad7326 pastith
                                return;
195 14ad7326 pastith
                        }
196 f5903adf pastith
                    // A request for upload progress.
197 f5903adf pastith
                    if (progress != null && content) {
198 f5903adf pastith
                            serveProgress(req, resp, progress, user, null);
199 f5903adf pastith
                                return;
200 f5903adf pastith
                    }
201 f5903adf pastith
202 14ad7326 pastith
                    resp.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI());
203 14ad7326 pastith
                    return;
204 14ad7326 pastith
            }
205 14ad7326 pastith
206 14ad7326 pastith
            if (resource instanceof FolderDTO)
207 14ad7326 pastith
                    folder = (FolderDTO) resource;
208 14ad7326 pastith
            else
209 14ad7326 pastith
                    file = (FileHeaderDTO) resource;
210 14ad7326 pastith
211 14ad7326 pastith
            // Now it's time to perform the deferred authentication check.
212 14ad7326 pastith
                // Since regular signature checking was already performed,
213 1d36b941 pastith
                // we need to check the read-all flag or the signature-in-parameters.
214 c9ffbe84 pastith
                if (authDeferred)
215 1d36b941 pastith
                        if (file != null && !file.isReadForAll() && content) {
216 1d36b941 pastith
                                // Check for GET with the signature in the request parameters.
217 1d36b941 pastith
                                String auth = req.getParameter(AUTHORIZATION_PARAMETER);
218 1d36b941 pastith
                                String dateParam = req.getParameter(DATE_PARAMETER);
219 1d36b941 pastith
                                if (auth == null || dateParam == null) {
220 1d36b941 pastith
                                        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
221 1d36b941 pastith
                                        return;
222 1d36b941 pastith
                                }
223 1d36b941 pastith
224 1d36b941 pastith
                            long timestamp;
225 1d36b941 pastith
                                try {
226 1d36b941 pastith
                                        timestamp = DateUtil.parseDate(dateParam).getTime();
227 1d36b941 pastith
                                } catch (DateParseException e) {
228 1d36b941 pastith
                                    resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
229 1d36b941 pastith
                                    return;
230 1d36b941 pastith
                                }
231 1d36b941 pastith
                            if (!isTimeValid(timestamp)) {
232 1d36b941 pastith
                                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
233 1d36b941 pastith
                                    return;
234 1d36b941 pastith
                            }
235 1d36b941 pastith
236 1d36b941 pastith
                                // Fetch the Authorization parameter and find the user specified in it.
237 1d36b941 pastith
                                String[] authParts = auth.split(" ");
238 1d36b941 pastith
                                if (authParts.length != 2) {
239 1d36b941 pastith
                                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
240 1d36b941 pastith
                                    return;
241 1d36b941 pastith
                            }
242 1d36b941 pastith
                                String username = authParts[0];
243 1d36b941 pastith
                                String signature = authParts[1];
244 1d36b941 pastith
                                user = null;
245 1d36b941 pastith
                                try {
246 1d36b941 pastith
                                        user = getService().findUser(username);
247 1d36b941 pastith
                                } catch (RpcException e) {
248 1d36b941 pastith
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
249 1d36b941 pastith
                                        return;
250 1d36b941 pastith
                                }
251 1d36b941 pastith
                                if (user == null) {
252 1d36b941 pastith
                                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
253 1d36b941 pastith
                                    return;
254 1d36b941 pastith
                            }
255 1d36b941 pastith
                                req.setAttribute(USER_ATTRIBUTE, user);
256 1d36b941 pastith
257 c961594d pastith
                                // Remove the servlet path from the request URI.
258 c961594d pastith
                                String p = req.getRequestURI();
259 c961594d pastith
                                String servletPath = req.getContextPath() + req.getServletPath();
260 c961594d pastith
                                p = p.substring(servletPath.length());
261 1d36b941 pastith
                                // Validate the signature in the Authorization parameter.
262 c961594d pastith
                                String data = req.getMethod() + dateParam + p;
263 1d36b941 pastith
                                if (!isSignatureValid(signature, user, data)) {
264 1d36b941 pastith
                                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
265 1d36b941 pastith
                                    return;
266 1d36b941 pastith
                            }
267 1d36b941 pastith
                        } else if (file != null && !file.isReadForAll() || file == null) {
268 1d36b941 pastith
                                // Check for a read-for-all file request.
269 c9ffbe84 pastith
                                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
270 c9ffbe84 pastith
                                return;
271 c9ffbe84 pastith
                        }
272 14ad7326 pastith
273 14ad7326 pastith
            // If the resource is not a collection, and the resource path
274 14ad7326 pastith
            // ends with "/" or "\", return NOT FOUND.
275 14ad7326 pastith
            if (folder == null)
276 14ad7326 pastith
                        if (path.endsWith("/") || path.endsWith("\\")) {
277 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI());
278 14ad7326 pastith
                            return;
279 14ad7326 pastith
                    }
280 14ad7326 pastith
281 a3349f1f pastith
            // Workaround for IE's broken caching behavior.
282 470a59a7 pastith
            if (folder != null)
283 470a59a7 pastith
                    resp.setHeader("Expires", "-1");
284 a3349f1f pastith
285 f5903adf pastith
            // A request for upload progress.
286 f5903adf pastith
            if (progress != null && content) {
287 f5903adf pastith
                    if (file == null) {
288 f5903adf pastith
                            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
289 f5903adf pastith
                            return;
290 f5903adf pastith
                    }
291 f5903adf pastith
                    serveProgress(req, resp, progress, user, file);
292 f5903adf pastith
                        return;
293 f5903adf pastith
            }
294 f5903adf pastith
295 14ad7326 pastith
                // Fetch the version to retrieve, if specified.
296 14ad7326 pastith
                String verStr = req.getParameter(VERSION_PARAM);
297 14ad7326 pastith
                int version = 0;
298 14ad7326 pastith
                FileBodyDTO oldBody = null;
299 14ad7326 pastith
                if (verStr != null && file != null)
300 14ad7326 pastith
                        try {
301 14ad7326 pastith
                                version = Integer.valueOf(verStr);
302 14ad7326 pastith
                        } catch (NumberFormatException e) {
303 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, req.getRequestURI());
304 14ad7326 pastith
                            return;
305 14ad7326 pastith
                        }
306 14ad7326 pastith
                if (version > 0)
307 14ad7326 pastith
                        try {
308 14ad7326 pastith
                                oldBody = getService().getFileVersion(user.getId(), file.getId(), version);
309 14ad7326 pastith
                        } catch (RpcException e) {
310 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
311 14ad7326 pastith
                                return;
312 14ad7326 pastith
                        } catch (ObjectNotFoundException e) {
313 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
314 14ad7326 pastith
                            return;
315 14ad7326 pastith
                        } catch (InsufficientPermissionsException e) {
316 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
317 14ad7326 pastith
                            return;
318 14ad7326 pastith
                        }
319 14ad7326 pastith
320 14ad7326 pastith
            // Check if the conditions specified in the optional If headers are
321 14ad7326 pastith
            // satisfied. Doing this for folders would require recursive checking
322 14ad7326 pastith
            // for all of their children, which in turn would defy the purpose of
323 14ad7326 pastith
            // the optimization.
324 14ad7326 pastith
            if (folder == null)
325 14ad7326 pastith
                        // Checking If headers.
326 14ad7326 pastith
                    if (!checkIfHeaders(req, resp, file, oldBody))
327 14ad7326 pastith
                                return;
328 14ad7326 pastith
329 14ad7326 pastith
            // Find content type.
330 14ad7326 pastith
            String contentType = null;
331 14ad7326 pastith
            if (file != null) {
332 14ad7326 pastith
                contentType = version>0 ? oldBody.getMimeType() : file.getMimeType();
333 14ad7326 pastith
                if (contentType == null) {
334 14ad7326 pastith
                        contentType = context.getMimeType(file.getName());
335 14ad7326 pastith
                        file.setMimeType(contentType);
336 14ad7326 pastith
                }
337 14ad7326 pastith
            } else
338 14ad7326 pastith
                        contentType = "application/json;charset=UTF-8";
339 14ad7326 pastith
340 14ad7326 pastith
            ArrayList ranges = null;
341 14ad7326 pastith
            long contentLength = -1L;
342 14ad7326 pastith
343 14ad7326 pastith
            if (file != null) {
344 77f75ac4 pastith
                    // Parse range specifier.
345 14ad7326 pastith
                    ranges = parseRange(req, resp, file, oldBody);
346 14ad7326 pastith
                    // ETag header
347 14ad7326 pastith
                    resp.setHeader("ETag", getETag(file, oldBody));
348 77f75ac4 pastith
                    // Last-Modified header.
349 14ad7326 pastith
                    String lastModified = oldBody == null ?
350 14ad7326 pastith
                                            getLastModifiedHttp(file.getAuditInfo()) :
351 14ad7326 pastith
                                            getLastModifiedHttp(oldBody.getAuditInfo());
352 14ad7326 pastith
                    resp.setHeader("Last-Modified", lastModified);
353 77f75ac4 pastith
                    // X-GSS-Metadata header.
354 14ad7326 pastith
                    try {
355 14ad7326 pastith
                                resp.setHeader("X-GSS-Metadata", renderJson(user, file, oldBody));
356 14ad7326 pastith
                        } catch (InsufficientPermissionsException e) {
357 14ad7326 pastith
                                resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
358 14ad7326 pastith
                        return;
359 14ad7326 pastith
                }
360 77f75ac4 pastith
                    // Get content length.
361 14ad7326 pastith
                    contentLength = version>0 ? oldBody.getFileSize() : file.getFileSize();
362 14ad7326 pastith
                    // Special case for zero length files, which would cause a
363 77f75ac4 pastith
                    // (silent) ISE when setting the output buffer size.
364 14ad7326 pastith
                    if (contentLength == 0L)
365 14ad7326 pastith
                                content = false;
366 77f75ac4 pastith
            } else
367 77f75ac4 pastith
                    // Set the folder X-GSS-Metadata header.
368 77f75ac4 pastith
                    try {
369 77f75ac4 pastith
                                resp.setHeader("X-GSS-Metadata", renderJsonMetadata(user, folder));
370 77f75ac4 pastith
                        } catch (InsufficientPermissionsException e) {
371 77f75ac4 pastith
                                resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
372 77f75ac4 pastith
                        return;
373 77f75ac4 pastith
                }
374 14ad7326 pastith
375 14ad7326 pastith
            ServletOutputStream ostream = null;
376 14ad7326 pastith
            PrintWriter writer = null;
377 14ad7326 pastith
378 14ad7326 pastith
            if (content)
379 14ad7326 pastith
                        try {
380 14ad7326 pastith
                            ostream = resp.getOutputStream();
381 14ad7326 pastith
                    } catch (IllegalStateException e) {
382 14ad7326 pastith
                            // If it fails, we try to get a Writer instead if we're
383 14ad7326 pastith
                            // trying to serve a text file
384 14ad7326 pastith
                            if ( contentType == null
385 14ad7326 pastith
                                                    || contentType.startsWith("text")
386 14ad7326 pastith
                                                    || contentType.endsWith("xml") )
387 14ad7326 pastith
                                        writer = resp.getWriter();
388 14ad7326 pastith
                                else
389 14ad7326 pastith
                                        throw e;
390 14ad7326 pastith
                    }
391 14ad7326 pastith
392 14ad7326 pastith
            if (folder != null
393 14ad7326 pastith
                                    || (ranges == null || ranges.isEmpty())
394 14ad7326 pastith
                                                            && req.getHeader("Range") == null
395 14ad7326 pastith
                                                            || ranges == FULL) {
396 14ad7326 pastith
                    // Set the appropriate output headers
397 14ad7326 pastith
                    if (contentType != null) {
398 14ad7326 pastith
                            if (logger.isDebugEnabled())
399 14ad7326 pastith
                                    logger.debug("contentType='" + contentType + "'");
400 14ad7326 pastith
                            resp.setContentType(contentType);
401 14ad7326 pastith
                    }
402 14ad7326 pastith
                    if (file != null && contentLength >= 0) {
403 14ad7326 pastith
                            if (logger.isDebugEnabled())
404 14ad7326 pastith
                                    logger.debug("contentLength=" + contentLength);
405 14ad7326 pastith
                            if (contentLength < Integer.MAX_VALUE)
406 14ad7326 pastith
                                        resp.setContentLength((int) contentLength);
407 14ad7326 pastith
                                else
408 14ad7326 pastith
                                        // Set the content-length as String to be able to use a long
409 14ad7326 pastith
                                    resp.setHeader("content-length", "" + contentLength);
410 14ad7326 pastith
                    }
411 14ad7326 pastith
412 14ad7326 pastith
                    InputStream renderResult = null;
413 14ad7326 pastith
                    if (folder != null)
414 2b90ab8a pastith
                                if (content)
415 14ad7326 pastith
                                        // Serve the directory browser
416 14ad7326 pastith
                                    try {
417 2b90ab8a pastith
                                                renderResult = renderJson(user, folder);
418 14ad7326 pastith
                                        } catch (InsufficientPermissionsException e) {
419 14ad7326 pastith
                                                resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
420 14ad7326 pastith
                                        return;
421 14ad7326 pastith
                                        }
422 14ad7326 pastith
                    // Copy the input stream to our output stream (if requested)
423 14ad7326 pastith
                    if (content) {
424 14ad7326 pastith
                            try {
425 14ad7326 pastith
                                    resp.setBufferSize(output);
426 14ad7326 pastith
                            } catch (IllegalStateException e) {
427 14ad7326 pastith
                                    // Silent catch
428 14ad7326 pastith
                            }
429 14ad7326 pastith
                            try {
430 617fe906 Dimitris Routsis
                                    if(file != null)
431 617fe906 Dimitris Routsis
                                                if (needsContentDisposition(req))
432 617fe906 Dimitris Routsis
                                                    resp.setHeader("Content-Disposition","attachment; filename*=UTF-8''"+URLEncoder.encode(file.getName(),"UTF-8"));
433 617fe906 Dimitris Routsis
                                            else
434 617fe906 Dimitris Routsis
                                                    resp.setHeader("Content-Disposition","inline; filename*=UTF-8''"+URLEncoder.encode(file.getName(),"UTF-8"));
435 14ad7326 pastith
                                    if (ostream != null)
436 14ad7326 pastith
                                                copy(file, renderResult, ostream, req, oldBody);
437 14ad7326 pastith
                                        else
438 14ad7326 pastith
                                                copy(file, renderResult, writer, req, oldBody);
439 a9e3c075 Dimitris Routsis
                                    if (file!=null) getService().updateAccounting(owner, new Date(), contentLength);
440 14ad7326 pastith
                        } catch (ObjectNotFoundException e) {
441 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
442 14ad7326 pastith
                                return;
443 14ad7326 pastith
                        } catch (InsufficientPermissionsException e) {
444 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
445 14ad7326 pastith
                                return;
446 14ad7326 pastith
                        } catch (RpcException e) {
447 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
448 14ad7326 pastith
                                return;
449 14ad7326 pastith
                        }
450 14ad7326 pastith
                    }
451 14ad7326 pastith
            } else {
452 14ad7326 pastith
                    if (ranges == null || ranges.isEmpty())
453 14ad7326 pastith
                            return;
454 14ad7326 pastith
                    // Partial content response.
455 14ad7326 pastith
                    resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
456 14ad7326 pastith
457 14ad7326 pastith
                    if (ranges.size() == 1) {
458 14ad7326 pastith
                            Range range = (Range) ranges.get(0);
459 14ad7326 pastith
                            resp.addHeader("Content-Range", "bytes "
460 14ad7326 pastith
                                                    + range.start
461 14ad7326 pastith
                                                    + "-" + range.end + "/"
462 14ad7326 pastith
                                                    + range.length);
463 14ad7326 pastith
                            long length = range.end - range.start + 1;
464 14ad7326 pastith
                            if (length < Integer.MAX_VALUE)
465 14ad7326 pastith
                                        resp.setContentLength((int) length);
466 14ad7326 pastith
                                else
467 14ad7326 pastith
                                        // Set the content-length as String to be able to use a long
468 14ad7326 pastith
                                    resp.setHeader("content-length", "" + length);
469 14ad7326 pastith
470 14ad7326 pastith
                            if (contentType != null) {
471 14ad7326 pastith
                                    if (logger.isDebugEnabled())
472 14ad7326 pastith
                                            logger.debug("contentType='" + contentType + "'");
473 14ad7326 pastith
                                    resp.setContentType(contentType);
474 14ad7326 pastith
                            }
475 14ad7326 pastith
476 14ad7326 pastith
                            if (content) {
477 14ad7326 pastith
                                    try {
478 14ad7326 pastith
                                            resp.setBufferSize(output);
479 14ad7326 pastith
                                    } catch (IllegalStateException e) {
480 14ad7326 pastith
                                            // Silent catch
481 14ad7326 pastith
                                    }
482 14ad7326 pastith
                                    try {
483 14ad7326 pastith
                                            if (ostream != null)
484 14ad7326 pastith
                                                        copy(file, ostream, range, req, oldBody);
485 14ad7326 pastith
                                                else
486 14ad7326 pastith
                                                        copy(file, writer, range, req, oldBody);
487 a9e3c075 Dimitris Routsis
                                            getService().updateAccounting(owner, new Date(), contentLength);
488 14ad7326 pastith
                                } catch (ObjectNotFoundException e) {
489 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
490 14ad7326 pastith
                                        return;
491 14ad7326 pastith
                                } catch (InsufficientPermissionsException e) {
492 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
493 14ad7326 pastith
                                        return;
494 14ad7326 pastith
                                } catch (RpcException e) {
495 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
496 14ad7326 pastith
                                        return;
497 14ad7326 pastith
                                }
498 14ad7326 pastith
                            }
499 14ad7326 pastith
                    } else {
500 14ad7326 pastith
                            resp.setContentType("multipart/byteranges; boundary=" + mimeSeparation);
501 14ad7326 pastith
                            if (content) {
502 14ad7326 pastith
                                    try {
503 14ad7326 pastith
                                            resp.setBufferSize(output);
504 14ad7326 pastith
                                    } catch (IllegalStateException e) {
505 14ad7326 pastith
                                            // Silent catch
506 14ad7326 pastith
                                    }
507 14ad7326 pastith
                                    try {
508 14ad7326 pastith
                                            if (ostream != null)
509 14ad7326 pastith
                                                        copy(file, ostream, ranges.iterator(), contentType, req, oldBody);
510 14ad7326 pastith
                                                else
511 14ad7326 pastith
                                                        copy(file, writer, ranges.iterator(), contentType, req, oldBody);
512 a9e3c075 Dimitris Routsis
                                            getService().updateAccounting(owner, new Date(), contentLength);
513 14ad7326 pastith
                                } catch (ObjectNotFoundException e) {
514 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
515 14ad7326 pastith
                                        return;
516 14ad7326 pastith
                                } catch (InsufficientPermissionsException e) {
517 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
518 14ad7326 pastith
                                        return;
519 14ad7326 pastith
                                } catch (RpcException e) {
520 14ad7326 pastith
                                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
521 14ad7326 pastith
                                        return;
522 14ad7326 pastith
                                }
523 14ad7326 pastith
                            }
524 14ad7326 pastith
                    }
525 14ad7326 pastith
            }
526 14ad7326 pastith
    }
527 14ad7326 pastith
528 14ad7326 pastith
        /**
529 5942d113 pastith
         * Determines whether the user agent needs the Content-Disposition
530 5942d113 pastith
         * header to be set, in order to properly download a file.
531 5942d113 pastith
         *
532 5942d113 pastith
         * @param req the HTTP request
533 5942d113 pastith
         * @return true if the Content-Disposition HTTP header must be set
534 5942d113 pastith
         */
535 5942d113 pastith
        private boolean needsContentDisposition(HttpServletRequest req) {
536 617fe906 Dimitris Routsis
                /*String agent = req.getHeader("user-agent");
537 50364cd8 pastith
                if (agent != null && agent.contains("MSIE"))
538 617fe906 Dimitris Routsis
                        return true;*/
539 617fe906 Dimitris Routsis
                String dl = req.getParameter("dl");
540 617fe906 Dimitris Routsis
                if ("1".equals(dl))
541 5942d113 pastith
                        return true;
542 5942d113 pastith
                return false;
543 5942d113 pastith
        }
544 5942d113 pastith
545 5942d113 pastith
        /**
546 f5903adf pastith
         * Sends a progress update on the amount of bytes received until now for
547 f5903adf pastith
         * a file that the current user is currently uploading.
548 f5903adf pastith
         *
549 f5903adf pastith
         * @param req the HTTP request
550 f5903adf pastith
         * @param resp the HTTP response
551 f5903adf pastith
         * @param parameter the value for the progress request parameter
552 f5903adf pastith
         * @param user the current user
553 f5903adf pastith
         * @param file the file being uploaded, or null if the request is about a new file
554 f5903adf pastith
         * @throws IOException if an I/O error occurs
555 f5903adf pastith
         */
556 f5903adf pastith
        private void serveProgress(HttpServletRequest req, HttpServletResponse resp,
557 f5903adf pastith
                                String parameter, User user, FileHeaderDTO file)        throws IOException {
558 f5903adf pastith
                String filename = file == null ? parameter : file.getName();
559 f5903adf pastith
                try {
560 f5903adf pastith
                        FileUploadStatus status = getService().getFileUploadStatus(user.getId(), filename);
561 f5903adf pastith
                        if (status == null) {
562 f5903adf pastith
                                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
563 f5903adf pastith
                                return;
564 f5903adf pastith
                        }
565 f5903adf pastith
                        JSONObject json = new JSONObject();
566 f5903adf pastith
                        json.put("bytesUploaded", status.getBytesUploaded()).
567 f5903adf pastith
                                put("bytesTotal", status.getFileSize());
568 f5903adf pastith
                        sendJson(req, resp, json.toString());
569 470a59a7 pastith
570 470a59a7 pastith
                        // Workaround for IE's broken caching behavior.
571 470a59a7 pastith
                    resp.setHeader("Expires", "-1");
572 f5903adf pastith
                        return;
573 f5903adf pastith
                } catch (RpcException e) {
574 f5903adf pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
575 f5903adf pastith
                        return;
576 f5903adf pastith
                } catch (JSONException e) {
577 f5903adf pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
578 f5903adf pastith
                        return;
579 f5903adf pastith
                }
580 f5903adf pastith
        }
581 f5903adf pastith
582 f5903adf pastith
        /**
583 14ad7326 pastith
         * Server a POST request to create/modify a file or folder.
584 14ad7326 pastith
         *
585 14ad7326 pastith
         * @param req the HTTP request
586 14ad7326 pastith
         * @param resp the HTTP response
587 14ad7326 pastith
     * @exception IOException if an input/output error occurs
588 14ad7326 pastith
         */
589 14ad7326 pastith
        void postResource(HttpServletRequest req, HttpServletResponse resp) throws IOException {
590 bda7d76d pastith
                boolean authDeferred = getAuthDeferred(req);
591 bda7d76d pastith
            if (!authDeferred && req.getParameterMap().size() > 1) {
592 14ad7326 pastith
                    resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
593 14ad7326 pastith
                    return;
594 14ad7326 pastith
            }
595 14ad7326 pastith
        String path = getInnerPath(req, PATH_FILES);
596 14ad7326 pastith
            path = path.endsWith("/")? path: path + '/';
597 e8b747c4 pastith
                try {
598 e8b747c4 pastith
                    path = URLDecoder.decode(path, "UTF-8");
599 e8b747c4 pastith
                } catch (IllegalArgumentException e) {
600 e8b747c4 pastith
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
601 e8b747c4 pastith
                        return;
602 e8b747c4 pastith
                }
603 bda7d76d pastith
            // We only defer authenticating multipart POST requests.
604 bda7d76d pastith
            if (authDeferred) {
605 bda7d76d pastith
                        if (!ServletFileUpload.isMultipartContent(req)) {
606 bda7d76d pastith
                            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
607 bda7d76d pastith
                            return;
608 bda7d76d pastith
                    }
609 bda7d76d pastith
                        handleMultipart(req, resp, path);
610 bda7d76d pastith
                        return;
611 bda7d76d pastith
                }
612 bda7d76d pastith
613 14ad7326 pastith
            String newName = req.getParameter(NEW_FOLDER_PARAMETER);
614 14ad7326 pastith
            boolean hasUpdateParam = req.getParameterMap().containsKey(RESOURCE_UPDATE_PARAMETER);
615 14ad7326 pastith
            boolean hasTrashParam = req.getParameterMap().containsKey(RESOURCE_TRASH_PARAMETER);
616 14ad7326 pastith
            boolean hasRestoreParam = req.getParameterMap().containsKey(RESOURCE_RESTORE_PARAMETER);
617 14ad7326 pastith
            String copyTo = req.getParameter(RESOURCE_COPY_PARAMETER);
618 14ad7326 pastith
            String moveTo = req.getParameter(RESOURCE_MOVE_PARAMETER);
619 39c34533 pastith
            String restoreVersion = req.getParameter(RESTORE_VERSION_PARAMETER);
620 14ad7326 pastith
621 a7bcd018 droutsis
            if (newName != null)
622 14ad7326 pastith
                        createFolder(req, resp, path, newName);
623 a7bcd018 droutsis
            else if (hasUpdateParam)
624 14ad7326 pastith
                        updateResource(req, resp, path);
625 14ad7326 pastith
                else if (hasTrashParam)
626 14ad7326 pastith
                        trashResource(req, resp, path);
627 14ad7326 pastith
                else if (hasRestoreParam)
628 14ad7326 pastith
                        restoreResource(req, resp, path);
629 14ad7326 pastith
                else if (copyTo != null)
630 14ad7326 pastith
                        copyResource(req, resp, path, copyTo);
631 14ad7326 pastith
                else if (moveTo != null)
632 14ad7326 pastith
                        moveResource(req, resp, path, moveTo);
633 39c34533 pastith
                else if (restoreVersion != null)
634 39c34533 pastith
                        restoreVersion(req, resp, path, restoreVersion);
635 14ad7326 pastith
                else
636 9fd42cf4 Panagiotis Astithas
                        // IE with Gears uses POST for multiple uploads.
637 9fd42cf4 Panagiotis Astithas
                        putResource(req, resp);
638 14ad7326 pastith
        }
639 14ad7326 pastith
640 14ad7326 pastith
        /**
641 39c34533 pastith
         * Restores a previous version for a file.
642 39c34533 pastith
         *
643 39c34533 pastith
         * @param req the HTTP request
644 39c34533 pastith
         * @param resp the HTTP response
645 39c34533 pastith
         * @param path the resource path
646 39c34533 pastith
         * @param version the version number to restore
647 39c34533 pastith
         * @throws IOException if an I/O error occurs
648 39c34533 pastith
         */
649 39c34533 pastith
        private void restoreVersion(HttpServletRequest req, HttpServletResponse resp, String path, String version) throws IOException {
650 39c34533 pastith
                User user = getUser(req);
651 39c34533 pastith
                User owner = getOwner(req);
652 39c34533 pastith
                Object resource = null;
653 39c34533 pastith
                try {
654 39c34533 pastith
                        resource = getService().getResourceAtPath(owner.getId(), path, true);
655 39c34533 pastith
                } catch (ObjectNotFoundException e) {
656 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
657 39c34533 pastith
                        return;
658 39c34533 pastith
                } catch (RpcException e) {
659 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
660 39c34533 pastith
                        return;
661 39c34533 pastith
                }
662 39c34533 pastith
                if (resource instanceof FolderDTO) {
663 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
664 39c34533 pastith
                        return;
665 39c34533 pastith
                }
666 39c34533 pastith
667 39c34533 pastith
                try {
668 39c34533 pastith
                        FileHeaderDTO file = (FileHeaderDTO) resource;
669 39c34533 pastith
                        int oldVersion = Integer.parseInt(version);
670 39c34533 pastith
                        getService().restoreVersion(user.getId(), file.getId(), oldVersion);
671 39c34533 pastith
                } catch (InsufficientPermissionsException e) {
672 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
673 39c34533 pastith
                } catch (ObjectNotFoundException e) {
674 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
675 39c34533 pastith
                } catch (RpcException e) {
676 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
677 39c34533 pastith
                } catch (GSSIOException e) {
678 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
679 39c34533 pastith
                } catch (QuotaExceededException e) {
680 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
681 39c34533 pastith
                } catch (NumberFormatException e) {
682 39c34533 pastith
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
683 39c34533 pastith
                }
684 39c34533 pastith
        }
685 39c34533 pastith
686 39c34533 pastith
        /**
687 e150a336 pastith
         * A method for handling multipart POST requests for uploading
688 e150a336 pastith
         * files from browser-based JavaScript clients.
689 e150a336 pastith
         *
690 e150a336 pastith
         * @param request the HTTP request
691 e150a336 pastith
         * @param response the HTTP response
692 e150a336 pastith
         * @param path the resource path
693 e150a336 pastith
         * @throws IOException in case an error occurs writing to the
694 e150a336 pastith
         *                 response stream
695 e150a336 pastith
         */
696 e150a336 pastith
        private void handleMultipart(HttpServletRequest request, HttpServletResponse response, String path) throws IOException {
697 e150a336 pastith
            if (logger.isDebugEnabled())
698 e150a336 pastith
                           logger.debug("Multipart POST for resource: " + path);
699 e150a336 pastith
700 e150a336 pastith
            User owner = getOwner(request);
701 e150a336 pastith
            boolean exists = true;
702 e150a336 pastith
        Object resource = null;
703 e150a336 pastith
        FileHeaderDTO file = null;
704 e150a336 pastith
        try {
705 e150a336 pastith
                resource = getService().getResourceAtPath(owner.getId(), path, false);
706 e150a336 pastith
        } catch (ObjectNotFoundException e) {
707 e150a336 pastith
            exists = false;
708 e150a336 pastith
        } catch (RpcException e) {
709 e150a336 pastith
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
710 e150a336 pastith
                        return;
711 e150a336 pastith
                }
712 e150a336 pastith
713 e150a336 pastith
        if (exists)
714 ebe40d2c pastith
                        if (resource instanceof FileHeaderDTO) {
715 e150a336 pastith
                            file = (FileHeaderDTO) resource;
716 ebe40d2c pastith
                            if (file.isDeleted()) {
717 ebe40d2c pastith
                                    response.sendError(HttpServletResponse.SC_CONFLICT, file.getName() + " is in the trash");
718 ebe40d2c pastith
                                return;
719 ebe40d2c pastith
                            }
720 ebe40d2c pastith
                        } else {
721 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_CONFLICT, path + " is a folder");
722 e150a336 pastith
                            return;
723 e150a336 pastith
                }
724 e150a336 pastith
725 e150a336 pastith
        FolderDTO folder = null;
726 e150a336 pastith
            Object parent;
727 e150a336 pastith
            String parentPath = null;
728 e150a336 pastith
                try {
729 e150a336 pastith
                        parentPath = getParentPath(path);
730 e150a336 pastith
                        parent = getService().getResourceAtPath(owner.getId(), parentPath, true);
731 e150a336 pastith
                } catch (ObjectNotFoundException e) {
732 e150a336 pastith
                    response.sendError(HttpServletResponse.SC_NOT_FOUND, parentPath);
733 e150a336 pastith
                    return;
734 e150a336 pastith
                } catch (RpcException e) {
735 e150a336 pastith
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
736 e150a336 pastith
                        return;
737 e150a336 pastith
                }
738 e150a336 pastith
            if (!(parent instanceof FolderDTO)) {
739 e150a336 pastith
                    response.sendError(HttpServletResponse.SC_CONFLICT);
740 e150a336 pastith
                    return;
741 e150a336 pastith
            }
742 e150a336 pastith
                   folder = (FolderDTO) parent;
743 e150a336 pastith
            String fileName = getLastElement(path);
744 e150a336 pastith
745 e150a336 pastith
                FileItemIterator iter;
746 e150a336 pastith
                File uploadedFile = null;
747 e150a336 pastith
                try {
748 e150a336 pastith
                        // Create a new file upload handler.
749 e150a336 pastith
                        ServletFileUpload upload = new ServletFileUpload();
750 e150a336 pastith
                        StatusProgressListener progressListener = new StatusProgressListener(getService());
751 e150a336 pastith
                        upload.setProgressListener(progressListener);
752 e150a336 pastith
                        iter = upload.getItemIterator(request);
753 bda7d76d pastith
                        String dateParam = null;
754 bda7d76d pastith
                        String auth = null;
755 e150a336 pastith
                        while (iter.hasNext()) {
756 e150a336 pastith
                                FileItemStream item = iter.next();
757 bda7d76d pastith
                                String name = item.getFieldName();
758 e150a336 pastith
                                InputStream stream = item.openStream();
759 bda7d76d pastith
                                if (item.isFormField()) {
760 bda7d76d pastith
                                        final String value = Streams.asString(stream);
761 bda7d76d pastith
                                        if (name.equals(DATE_PARAMETER))
762 bda7d76d pastith
                                                dateParam = value;
763 bda7d76d pastith
                                        else if (name.equals(AUTHORIZATION_PARAMETER))
764 bda7d76d pastith
                                                auth = value;
765 bda7d76d pastith
766 bda7d76d pastith
                                        if (logger.isDebugEnabled())
767 bda7d76d pastith
                                                logger.debug(name + ":" + value);
768 bda7d76d pastith
                                } else {
769 bda7d76d pastith
                                        // Fetch the timestamp used to guard against replay attacks.
770 bda7d76d pastith
                                    if (dateParam == null) {
771 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN, "No Date parameter");
772 bda7d76d pastith
                                            return;
773 bda7d76d pastith
                                    }
774 bda7d76d pastith
775 bda7d76d pastith
                                    long timestamp;
776 bda7d76d pastith
                                        try {
777 bda7d76d pastith
                                                timestamp = DateUtil.parseDate(dateParam).getTime();
778 bda7d76d pastith
                                        } catch (DateParseException e) {
779 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
780 bda7d76d pastith
                                            return;
781 bda7d76d pastith
                                        }
782 bda7d76d pastith
                                    if (!isTimeValid(timestamp)) {
783 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN);
784 bda7d76d pastith
                                            return;
785 bda7d76d pastith
                                    }
786 bda7d76d pastith
787 bda7d76d pastith
                                        // Fetch the Authorization parameter and find the user specified in it.
788 bda7d76d pastith
                                    if (auth == null) {
789 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN, "No Authorization parameter");
790 bda7d76d pastith
                                            return;
791 bda7d76d pastith
                                    }
792 bda7d76d pastith
                                        String[] authParts = auth.split(" ");
793 bda7d76d pastith
                                        if (authParts.length != 2) {
794 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN);
795 bda7d76d pastith
                                            return;
796 bda7d76d pastith
                                    }
797 bda7d76d pastith
                                        String username = authParts[0];
798 bda7d76d pastith
                                        String signature = authParts[1];
799 bda7d76d pastith
                                        User user = null;
800 bda7d76d pastith
                                        try {
801 bda7d76d pastith
                                                user = getService().findUser(username);
802 bda7d76d pastith
                                        } catch (RpcException e) {
803 bda7d76d pastith
                                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
804 bda7d76d pastith
                                                return;
805 bda7d76d pastith
                                        }
806 bda7d76d pastith
                                        if (user == null) {
807 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN);
808 bda7d76d pastith
                                            return;
809 bda7d76d pastith
                                    }
810 bda7d76d pastith
                                        request.setAttribute(USER_ATTRIBUTE, user);
811 bda7d76d pastith
812 c961594d pastith
                                        // Remove the servlet path from the request URI.
813 c961594d pastith
                                        String p = request.getRequestURI();
814 c961594d pastith
                                        String servletPath = request.getContextPath() + request.getServletPath();
815 c961594d pastith
                                        p = p.substring(servletPath.length());
816 bda7d76d pastith
                                        // Validate the signature in the Authorization parameter.
817 c961594d pastith
                                        String data = request.getMethod() + dateParam + p;
818 bda7d76d pastith
                                        if (!isSignatureValid(signature, user, data)) {
819 bda7d76d pastith
                                            response.sendError(HttpServletResponse.SC_FORBIDDEN);
820 bda7d76d pastith
                                            return;
821 bda7d76d pastith
                                    }
822 bda7d76d pastith
823 e150a336 pastith
                                        progressListener.setUserId(user.getId());
824 e150a336 pastith
                                        progressListener.setFilename(fileName);
825 e150a336 pastith
                                        String contentType = item.getContentType();
826 e150a336 pastith
827 e150a336 pastith
                                        try {
828 e150a336 pastith
                                                uploadedFile = getService().uploadFile(stream, user.getId());
829 e150a336 pastith
                                        } catch (IOException ex) {
830 e150a336 pastith
                                                throw new GSSIOException(ex, false);
831 e150a336 pastith
                                        }
832 8f128261 droutsis
                                        FileHeaderDTO fileDTO = null;
833 e150a336 pastith
                                        if (file == null)
834 4d737770 Fotis Stamatelopoulos
                                                fileDTO = getService().createFile(user.getId(), folder.getId(), fileName, contentType, uploadedFile.getCanonicalFile().length(), uploadedFile.getAbsolutePath());
835 e150a336 pastith
                                        else
836 4d737770 Fotis Stamatelopoulos
                                                fileDTO = getService().updateFileContents(user.getId(), file.getId(), contentType, uploadedFile.getCanonicalFile().length(), uploadedFile.getAbsolutePath());
837 a9e3c075 Dimitris Routsis
                                        getService().updateAccounting(owner, new Date(), fileDTO.getFileSize());
838 599c9fc4 pastith
                                        getService().removeFileUploadProgress(user.getId(), fileName);
839 e150a336 pastith
                                }
840 e150a336 pastith
                        }
841 2e7ca93c pastith
                        // We can't return 204 here since GWT's onSubmitComplete won't fire.
842 2e7ca93c pastith
                        response.setContentType("text/html");
843 2e7ca93c pastith
            response.getWriter().print("<pre></pre>");
844 e150a336 pastith
                } catch (FileUploadException e) {
845 e150a336 pastith
                        String error = "Error while uploading file";
846 e150a336 pastith
                        logger.error(error, e);
847 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
848 e150a336 pastith
                } catch (GSSIOException e) {
849 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
850 e150a336 pastith
                                uploadedFile.delete();
851 e150a336 pastith
                        String error = "Error while uploading file";
852 e150a336 pastith
                        if (e.logAsError())
853 e150a336 pastith
                                logger.error(error, e);
854 e150a336 pastith
                        else
855 e150a336 pastith
                                logger.debug(error, e);
856 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
857 e150a336 pastith
                } catch (DuplicateNameException e) {
858 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
859 e150a336 pastith
                                uploadedFile.delete();
860 e150a336 pastith
                        String error = "The specified file name already exists in this folder";
861 e150a336 pastith
                        logger.error(error, e);
862 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_CONFLICT, error);
863 e150a336 pastith
864 e150a336 pastith
                } catch (InsufficientPermissionsException e) {
865 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
866 e150a336 pastith
                                uploadedFile.delete();
867 e150a336 pastith
                        String error = "You don't have the necessary permissions";
868 e150a336 pastith
                        logger.error(error, e);
869 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, error);
870 e150a336 pastith
871 e150a336 pastith
                } catch (QuotaExceededException e) {
872 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
873 e150a336 pastith
                                uploadedFile.delete();
874 e150a336 pastith
                        String error = "Not enough free space available";
875 e150a336 pastith
                        if (logger.isDebugEnabled())
876 e150a336 pastith
                                logger.debug(error, e);
877 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, error);
878 e150a336 pastith
879 e150a336 pastith
                } catch (ObjectNotFoundException e) {
880 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
881 e150a336 pastith
                                uploadedFile.delete();
882 e150a336 pastith
                        String error = "A specified object was not found";
883 e150a336 pastith
                        logger.error(error, e);
884 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_NOT_FOUND, error);
885 e150a336 pastith
                } catch (RpcException e) {
886 e150a336 pastith
                        if (uploadedFile != null && uploadedFile.exists())
887 e150a336 pastith
                                uploadedFile.delete();
888 e150a336 pastith
                        String error = "An error occurred while communicating with the service";
889 e150a336 pastith
                        logger.error(error, e);
890 e150a336 pastith
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
891 e150a336 pastith
                }
892 e150a336 pastith
        }
893 e150a336 pastith
894 74113dc6 koutsoub
        private String getBackupFilename(FileHeaderDTO file, String filename){
895 74113dc6 koutsoub
                List<FileHeaderDTO> deletedFiles = new ArrayList<FileHeaderDTO>();
896 74113dc6 koutsoub
                try{
897 74113dc6 koutsoub
                        deletedFiles = getService().getDeletedFiles(file.getOwner().getId());
898 74113dc6 koutsoub
                }
899 74113dc6 koutsoub
                catch(ObjectNotFoundException e){
900 74113dc6 koutsoub
901 74113dc6 koutsoub
                } catch (RpcException e) {
902 74113dc6 koutsoub
903 74113dc6 koutsoub
                }
904 74113dc6 koutsoub
                List<FileHeaderDTO> filesInSameFolder = new ArrayList<FileHeaderDTO>();
905 74113dc6 koutsoub
                for(FileHeaderDTO deleted : deletedFiles)
906 74113dc6 koutsoub
                        if(deleted.getFolder().getId().equals(file.getFolder().getId()))
907 74113dc6 koutsoub
                                filesInSameFolder.add(deleted);
908 74113dc6 koutsoub
                int i=1;
909 74113dc6 koutsoub
                String filenameToCheck = filename;
910 74113dc6 koutsoub
                for(FileHeaderDTO same : filesInSameFolder)
911 74113dc6 koutsoub
                        if(same.getName().startsWith(filename)){
912 74113dc6 koutsoub
                                String toCheck=same.getName().substring(filename.length(),same.getName().length());
913 74113dc6 koutsoub
                                if(toCheck.startsWith(" ")){
914 74113dc6 koutsoub
                                        int test =-1;
915 74113dc6 koutsoub
                                        try{
916 74113dc6 koutsoub
                                                test = Integer.valueOf(toCheck.replace(" ",""));
917 74113dc6 koutsoub
                                        }
918 74113dc6 koutsoub
                                        catch(NumberFormatException e){
919 74113dc6 koutsoub
                                                //do nothing since string is not a number
920 74113dc6 koutsoub
                                        }
921 74113dc6 koutsoub
                                        if(test>=i)
922 74113dc6 koutsoub
                                                i = test+1;
923 74113dc6 koutsoub
                                }
924 74113dc6 koutsoub
                        }
925 74113dc6 koutsoub
926 74113dc6 koutsoub
                return filename+" "+i;
927 74113dc6 koutsoub
        }
928 74113dc6 koutsoub
929 e150a336 pastith
        /**
930 14ad7326 pastith
         * Move the resource in the specified path to the specified destination.
931 14ad7326 pastith
         *
932 14ad7326 pastith
         * @param req the HTTP request
933 14ad7326 pastith
         * @param resp the HTTP response
934 14ad7326 pastith
         * @param path the path of the resource
935 14ad7326 pastith
         * @param moveTo the destination of the move procedure
936 14ad7326 pastith
         * @throws IOException if an input/output error occurs
937 14ad7326 pastith
         */
938 14ad7326 pastith
        private void moveResource(HttpServletRequest req, HttpServletResponse resp, String path, String moveTo) throws IOException {
939 14ad7326 pastith
                User user = getUser(req);
940 14ad7326 pastith
                User owner = getOwner(req);
941 14ad7326 pastith
                Object resource = null;
942 14ad7326 pastith
                try {
943 68410d59 pastith
                        resource = getService().getResourceAtPath(owner.getId(), path, true);
944 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
945 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
946 14ad7326 pastith
                        return;
947 14ad7326 pastith
                } catch (RpcException e) {
948 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
949 14ad7326 pastith
                        return;
950 14ad7326 pastith
                }
951 14ad7326 pastith
952 14ad7326 pastith
        String destination = null;
953 14ad7326 pastith
        User destOwner = null;
954 14ad7326 pastith
                boolean exists = true;
955 14ad7326 pastith
                try {
956 5e2b8ec6 koutsoub
                        destination = getDestinationPath(req, encodePath(moveTo));
957 5e2b8ec6 koutsoub
                        destination = URLDecoder.decode(destination, "UTF-8");
958 14ad7326 pastith
                        destOwner = getDestinationOwner(req);
959 68410d59 pastith
                        getService().getResourceAtPath(destOwner.getId(), destination, true);
960 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
961 14ad7326 pastith
                        exists = false;
962 14ad7326 pastith
                } catch (URISyntaxException e) {
963 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
964 14ad7326 pastith
                        return;
965 14ad7326 pastith
                } catch (RpcException e) {
966 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
967 14ad7326 pastith
                        return;
968 14ad7326 pastith
                }
969 14ad7326 pastith
                if (exists) {
970 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, destination + " already exists");
971 14ad7326 pastith
                        return;
972 14ad7326 pastith
                }
973 14ad7326 pastith
974 14ad7326 pastith
                try {
975 14ad7326 pastith
                        if (resource instanceof FolderDTO) {
976 14ad7326 pastith
                                FolderDTO folder = (FolderDTO) resource;
977 14ad7326 pastith
                                getService().moveFolderToPath(user.getId(), destOwner.getId(), folder.getId(), destination);
978 14ad7326 pastith
                        } else {
979 14ad7326 pastith
                                FileHeaderDTO file = (FileHeaderDTO) resource;
980 14ad7326 pastith
                                getService().moveFileToPath(user.getId(), destOwner.getId(), file.getId(), destination);
981 14ad7326 pastith
                        }
982 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
983 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
984 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
985 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
986 14ad7326 pastith
                } catch (RpcException e) {
987 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
988 14ad7326 pastith
                } catch (DuplicateNameException e) {
989 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
990 14ad7326 pastith
                } catch (GSSIOException e) {
991 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
992 14ad7326 pastith
                } catch (QuotaExceededException e) {
993 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
994 14ad7326 pastith
                }
995 14ad7326 pastith
        }
996 14ad7326 pastith
997 14ad7326 pastith
        /**
998 14ad7326 pastith
         * Copy the resource in the specified path to the specified destination.
999 14ad7326 pastith
         *
1000 14ad7326 pastith
         * @param req the HTTP request
1001 14ad7326 pastith
         * @param resp the HTTP response
1002 14ad7326 pastith
         * @param path the path of the resource
1003 14ad7326 pastith
         * @param copyTo the destination of the copy procedure
1004 14ad7326 pastith
         * @throws IOException if an input/output error occurs
1005 14ad7326 pastith
         */
1006 14ad7326 pastith
        private void copyResource(HttpServletRequest req, HttpServletResponse resp, String path, String copyTo) throws IOException {
1007 14ad7326 pastith
                User user = getUser(req);
1008 14ad7326 pastith
                User owner = getOwner(req);
1009 14ad7326 pastith
                Object resource = null;
1010 14ad7326 pastith
                try {
1011 68410d59 pastith
                        resource = getService().getResourceAtPath(owner.getId(), path, true);
1012 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1013 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
1014 14ad7326 pastith
                        return;
1015 14ad7326 pastith
                } catch (RpcException e) {
1016 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1017 14ad7326 pastith
                        return;
1018 14ad7326 pastith
                }
1019 14ad7326 pastith
1020 14ad7326 pastith
        String destination = null;
1021 14ad7326 pastith
        User destOwner = null;
1022 14ad7326 pastith
                boolean exists = true;
1023 14ad7326 pastith
                try {
1024 4c44fdca Dimitris Routsis
                        String destinationEncoded = getDestinationPath(req, encodePath(copyTo));
1025 4c44fdca Dimitris Routsis
                        destination = URLDecoder.decode(destinationEncoded, "UTF-8");
1026 14ad7326 pastith
                        destOwner = getDestinationOwner(req);
1027 4c44fdca Dimitris Routsis
                        getService().getResourceAtPath(destOwner.getId(), destinationEncoded, true);
1028 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1029 14ad7326 pastith
                        exists = false;
1030 14ad7326 pastith
                } catch (URISyntaxException e) {
1031 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
1032 14ad7326 pastith
                        return;
1033 14ad7326 pastith
                } catch (RpcException e) {
1034 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
1035 14ad7326 pastith
                        return;
1036 14ad7326 pastith
                }
1037 14ad7326 pastith
                if (exists) {
1038 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, destination + " already exists");
1039 14ad7326 pastith
                        return;
1040 14ad7326 pastith
                }
1041 14ad7326 pastith
1042 14ad7326 pastith
                try {
1043 14ad7326 pastith
                        if (resource instanceof FolderDTO) {
1044 14ad7326 pastith
                                FolderDTO folder = (FolderDTO) resource;
1045 14ad7326 pastith
                                getService().copyFolderStructureToPath(user.getId(), destOwner.getId(), folder.getId(), destination);
1046 14ad7326 pastith
                        } else {
1047 14ad7326 pastith
                                FileHeaderDTO file = (FileHeaderDTO) resource;
1048 14ad7326 pastith
                                getService().copyFileToPath(user.getId(), destOwner.getId(), file.getId(), destination);
1049 14ad7326 pastith
                        }
1050 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1051 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1052 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1053 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
1054 14ad7326 pastith
                } catch (RpcException e) {
1055 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, destination);
1056 14ad7326 pastith
                } catch (DuplicateNameException e) {
1057 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
1058 14ad7326 pastith
                } catch (GSSIOException e) {
1059 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
1060 14ad7326 pastith
                } catch (QuotaExceededException e) {
1061 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
1062 14ad7326 pastith
                }
1063 14ad7326 pastith
        }
1064 14ad7326 pastith
1065 5e2b8ec6 koutsoub
        private String encodePath(String path) throws UnsupportedEncodingException{
1066 5e2b8ec6 koutsoub
                StringTokenizer str = new StringTokenizer(path, "/:", true);
1067 5e2b8ec6 koutsoub
                String result = new String();
1068 5e2b8ec6 koutsoub
                while(str.hasMoreTokens()){
1069 5e2b8ec6 koutsoub
                        String token = str.nextToken();
1070 5e2b8ec6 koutsoub
                        if(!token.equals("/") && !token.equals(":"))
1071 5e2b8ec6 koutsoub
                                token = URLEncoder.encode(token,"UTF-8");
1072 5e2b8ec6 koutsoub
                        result = result + token;
1073 5e2b8ec6 koutsoub
                }
1074 5e2b8ec6 koutsoub
                return result;
1075 5e2b8ec6 koutsoub
        }
1076 14ad7326 pastith
        /**
1077 14ad7326 pastith
         * A helper method that extracts the relative resource path,
1078 14ad7326 pastith
         * after removing the 'files' namespace.
1079 4c44fdca Dimitris Routsis
         * The path returned is <i>not</i> URL-decoded.
1080 14ad7326 pastith
         *
1081 14ad7326 pastith
         * @param req the HTTP request
1082 14ad7326 pastith
         * @param path the specified path
1083 14ad7326 pastith
         * @return the path relative to the root folder
1084 14ad7326 pastith
         * @throws URISyntaxException
1085 14ad7326 pastith
         * @throws RpcException in case an error occurs while communicating
1086 14ad7326 pastith
         *                                                 with the backend
1087 4c44fdca Dimitris Routsis
         * @throws UnsupportedEncodingException
1088 14ad7326 pastith
         */
1089 4c44fdca Dimitris Routsis
        private String getDestinationPath(HttpServletRequest req, String path) throws URISyntaxException, RpcException, UnsupportedEncodingException {
1090 14ad7326 pastith
                URI uri = new URI(path);
1091 4c44fdca Dimitris Routsis
                String dest = uri.getRawPath();
1092 14ad7326 pastith
                // Remove the context path from the destination URI.
1093 14ad7326 pastith
                String contextPath = req.getContextPath();
1094 14ad7326 pastith
                if (!dest.startsWith(contextPath))
1095 14ad7326 pastith
                        throw new URISyntaxException(dest, "Destination path does not start with " + contextPath);
1096 14ad7326 pastith
                dest = dest.substring(contextPath.length());
1097 14ad7326 pastith
                // Remove the servlet path from the destination URI.
1098 14ad7326 pastith
                String servletPath = req.getServletPath();
1099 14ad7326 pastith
                if (!dest.startsWith(servletPath))
1100 14ad7326 pastith
                        throw new URISyntaxException(dest, "Destination path does not start with " + servletPath);
1101 14ad7326 pastith
                dest = dest.substring(servletPath.length());
1102 14ad7326 pastith
            // Strip the username part
1103 14ad7326 pastith
                if (dest.length() < 2)
1104 14ad7326 pastith
                        throw new URISyntaxException(dest, "No username in the destination URI");
1105 14ad7326 pastith
                int slash = dest.substring(1).indexOf('/');
1106 14ad7326 pastith
                if (slash == -1)
1107 14ad7326 pastith
                        throw new URISyntaxException(dest, "No username in the destination URI");
1108 4c44fdca Dimitris Routsis
                // Decode the user to get the proper characters (mainly the @)
1109 4c44fdca Dimitris Routsis
                String owner = URLDecoder.decode(dest.substring(1, slash + 1), "UTF-8");
1110 14ad7326 pastith
                User o;
1111 14ad7326 pastith
                o = getService().findUser(owner);
1112 14ad7326 pastith
                if (o == null)
1113 14ad7326 pastith
                        throw new URISyntaxException(dest, "User " + owner + " not found");
1114 14ad7326 pastith
1115 14ad7326 pastith
                req.setAttribute(DESTINATION_OWNER_ATTRIBUTE, o);
1116 14ad7326 pastith
                dest = dest.substring(slash + 1);
1117 14ad7326 pastith
1118 14ad7326 pastith
                // Chop the resource namespace part
1119 14ad7326 pastith
                dest = dest.substring(RequestHandler.PATH_FILES.length());
1120 14ad7326 pastith
1121 14ad7326 pastith
            dest = dest.endsWith("/")? dest: dest + '/';
1122 14ad7326 pastith
                return dest;
1123 14ad7326 pastith
        }
1124 14ad7326 pastith
1125 14ad7326 pastith
        /**
1126 14ad7326 pastith
         * Move the resource in the specified path to the trash bin.
1127 14ad7326 pastith
         *
1128 14ad7326 pastith
         * @param req the HTTP request
1129 14ad7326 pastith
         * @param resp the HTTP response
1130 14ad7326 pastith
         * @param path the path of the resource
1131 14ad7326 pastith
         * @throws IOException if an input/output error occurs
1132 14ad7326 pastith
         */
1133 14ad7326 pastith
        private void trashResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
1134 14ad7326 pastith
                User user = getUser(req);
1135 14ad7326 pastith
                User owner = getOwner(req);
1136 14ad7326 pastith
                Object resource = null;
1137 14ad7326 pastith
                try {
1138 68410d59 pastith
                        resource = getService().getResourceAtPath(owner.getId(), path, true);
1139 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1140 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
1141 14ad7326 pastith
                        return;
1142 14ad7326 pastith
                } catch (RpcException e) {
1143 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1144 14ad7326 pastith
                        return;
1145 14ad7326 pastith
                }
1146 14ad7326 pastith
1147 14ad7326 pastith
                try {
1148 14ad7326 pastith
                        if (resource instanceof FolderDTO) {
1149 14ad7326 pastith
                                FolderDTO folder = (FolderDTO) resource;
1150 14ad7326 pastith
                                getService().moveFolderToTrash(user.getId(), folder.getId());
1151 14ad7326 pastith
                        } else {
1152 14ad7326 pastith
                                FileHeaderDTO file = (FileHeaderDTO) resource;
1153 14ad7326 pastith
                                getService().moveFileToTrash(user.getId(), file.getId());
1154 14ad7326 pastith
                        }
1155 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1156 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1157 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1158 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
1159 14ad7326 pastith
                } catch (RpcException e) {
1160 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1161 14ad7326 pastith
                }
1162 14ad7326 pastith
        }
1163 14ad7326 pastith
1164 14ad7326 pastith
        /**
1165 14ad7326 pastith
         * Restore the resource in the specified path from the trash bin.
1166 14ad7326 pastith
         *
1167 14ad7326 pastith
         * @param req the HTTP request
1168 14ad7326 pastith
         * @param resp the HTTP response
1169 14ad7326 pastith
         * @param path the path of the resource
1170 14ad7326 pastith
         * @throws IOException if an input/output error occurs
1171 14ad7326 pastith
         */
1172 14ad7326 pastith
        private void restoreResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
1173 14ad7326 pastith
                User user = getUser(req);
1174 14ad7326 pastith
                User owner = getOwner(req);
1175 14ad7326 pastith
                Object resource = null;
1176 14ad7326 pastith
                try {
1177 e150a336 pastith
                        resource = getService().getResourceAtPath(owner.getId(), path, false);
1178 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1179 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
1180 14ad7326 pastith
                        return;
1181 14ad7326 pastith
                } catch (RpcException e) {
1182 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1183 14ad7326 pastith
                        return;
1184 14ad7326 pastith
                }
1185 14ad7326 pastith
1186 14ad7326 pastith
                try {
1187 14ad7326 pastith
                        if (resource instanceof FolderDTO) {
1188 14ad7326 pastith
                                FolderDTO folder = (FolderDTO) resource;
1189 14ad7326 pastith
                                getService().removeFolderFromTrash(user.getId(), folder.getId());
1190 14ad7326 pastith
                        } else {
1191 14ad7326 pastith
                                FileHeaderDTO file = (FileHeaderDTO) resource;
1192 14ad7326 pastith
                                getService().removeFileFromTrash(user.getId(), file.getId());
1193 14ad7326 pastith
                        }
1194 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1195 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1196 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1197 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
1198 14ad7326 pastith
                } catch (RpcException e) {
1199 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1200 14ad7326 pastith
                }
1201 14ad7326 pastith
        }
1202 14ad7326 pastith
1203 14ad7326 pastith
        /**
1204 14ad7326 pastith
         * Update the resource in the specified path.
1205 14ad7326 pastith
         *
1206 14ad7326 pastith
         * @param req the HTTP request
1207 14ad7326 pastith
         * @param resp the HTTP response
1208 14ad7326 pastith
         * @param path the path of the resource
1209 14ad7326 pastith
         * @throws IOException if an input/output error occurs
1210 14ad7326 pastith
         */
1211 14ad7326 pastith
        private void updateResource(HttpServletRequest req, HttpServletResponse resp, String path) throws IOException {
1212 77dcb3f1 Panagiotis Astithas
                final User user = getUser(req);
1213 14ad7326 pastith
                User owner = getOwner(req);
1214 14ad7326 pastith
                Object resource = null;
1215 14ad7326 pastith
                try {
1216 3d1b9329 koutsoub
                        resource = getService().getResourceAtPath(owner.getId(), path, false);
1217 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1218 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
1219 14ad7326 pastith
                        return;
1220 14ad7326 pastith
                } catch (RpcException e) {
1221 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1222 14ad7326 pastith
                        return;
1223 14ad7326 pastith
                }
1224 95da8819 koutsoub
                //use utf-8 encoding for reading request
1225 95da8819 koutsoub
                BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream(),"UTF-8"));
1226 14ad7326 pastith
                StringBuffer input = new StringBuffer();
1227 14ad7326 pastith
                String line = null;
1228 14ad7326 pastith
                JSONObject json = null;
1229 14ad7326 pastith
                while ((line = reader.readLine()) != null)
1230 14ad7326 pastith
                        input.append(line);
1231 14ad7326 pastith
                reader.close();
1232 14ad7326 pastith
                try {
1233 14ad7326 pastith
                        json = new JSONObject(input.toString());
1234 14ad7326 pastith
                        if (logger.isDebugEnabled())
1235 14ad7326 pastith
                                logger.debug("JSON update: " + json);
1236 14ad7326 pastith
                        if (resource instanceof FolderDTO) {
1237 77dcb3f1 Panagiotis Astithas
                                final FolderDTO folder = (FolderDTO) resource;
1238 14ad7326 pastith
                                String name = json.optString("name");
1239 5e2b8ec6 koutsoub
                                if (!name.isEmpty()){
1240 8fa7f8ff pastith
                                        try {
1241 8fa7f8ff pastith
                                                name = URLDecoder.decode(name, "UTF-8");
1242 8fa7f8ff pastith
                                        } catch (IllegalArgumentException e) {
1243 8fa7f8ff pastith
                                                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
1244 8fa7f8ff pastith
                                                return;
1245 8fa7f8ff pastith
                                        }
1246 77dcb3f1 Panagiotis Astithas
                                        final String fName = name;
1247 77dcb3f1 Panagiotis Astithas
                                        FolderDTO folderUpdated = new TransactionHelper<FolderDTO>().tryExecute(new Callable<FolderDTO>() {
1248 77dcb3f1 Panagiotis Astithas
                                                @Override
1249 77dcb3f1 Panagiotis Astithas
                                                public FolderDTO call() throws Exception {
1250 77dcb3f1 Panagiotis Astithas
                                                        return getService().modifyFolder(user.getId(), folder.getId(), fName);
1251 77dcb3f1 Panagiotis Astithas
                                                }
1252 77dcb3f1 Panagiotis Astithas
1253 77dcb3f1 Panagiotis Astithas
                                        });
1254 5e2b8ec6 koutsoub
                                        String parentUrl =URLDecoder.decode(getContextPath(req, true),"UTF-8");
1255 5e2b8ec6 koutsoub
                                        String fpath = URLDecoder.decode(req.getPathInfo(), "UTF-8");
1256 5e2b8ec6 koutsoub
                                        parentUrl = parentUrl.replaceAll(fpath, "");
1257 5e2b8ec6 koutsoub
                                        if(!parentUrl.endsWith("/"))
1258 5e2b8ec6 koutsoub
                                                parentUrl = parentUrl+"/";
1259 5e2b8ec6 koutsoub
                                        parentUrl = parentUrl+folderUpdated.getOwner().getUsername()+PATH_FILES+folderUpdated.getPath();
1260 5e2b8ec6 koutsoub
                                        resp.getWriter().println(parentUrl);
1261 5e2b8ec6 koutsoub
                                }
1262 14ad7326 pastith
1263 14ad7326 pastith
                                JSONArray permissions = json.optJSONArray("permissions");
1264 14ad7326 pastith
                                if (permissions != null) {
1265 77dcb3f1 Panagiotis Astithas
                                        final Set<PermissionDTO> perms = parsePermissions(user, permissions);
1266 77dcb3f1 Panagiotis Astithas
                                        new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
1267 77dcb3f1 Panagiotis Astithas
                                                @Override
1268 77dcb3f1 Panagiotis Astithas
                                                public Object call() throws Exception {
1269 77dcb3f1 Panagiotis Astithas
                                                        getService().setFolderPermissions(user.getId(), folder.getId(), perms);
1270 77dcb3f1 Panagiotis Astithas
                                                        return null;
1271 77dcb3f1 Panagiotis Astithas
                                                }
1272 77dcb3f1 Panagiotis Astithas
1273 77dcb3f1 Panagiotis Astithas
                                        });
1274 14ad7326 pastith
                                }
1275 14ad7326 pastith
                        } else {
1276 77dcb3f1 Panagiotis Astithas
                                final FileHeaderDTO file = (FileHeaderDTO) resource;
1277 14ad7326 pastith
                                String name = null;
1278 14ad7326 pastith
                                if (json.opt("name") != null)
1279 14ad7326 pastith
                                        name = json.optString("name");
1280 14ad7326 pastith
                                JSONArray tagset = json.optJSONArray("tags");
1281 77dcb3f1 Panagiotis Astithas
                                String tags= null;
1282 14ad7326 pastith
                                StringBuffer t = new StringBuffer();
1283 14ad7326 pastith
                                if (tagset != null) {
1284 14ad7326 pastith
                                        for (int i = 0; i < tagset.length(); i++)
1285 14ad7326 pastith
                                                t.append(tagset.getString(i) + ',');
1286 14ad7326 pastith
                                        tags = t.toString();
1287 14ad7326 pastith
                                }
1288 77dcb3f1 Panagiotis Astithas
                                if (name != null || tags != null) {
1289 77dcb3f1 Panagiotis Astithas
                                        final String fName = name;
1290 77dcb3f1 Panagiotis Astithas
                                        final String fTags = tags;
1291 77dcb3f1 Panagiotis Astithas
                                        new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
1292 77dcb3f1 Panagiotis Astithas
                                                @Override
1293 77dcb3f1 Panagiotis Astithas
                                                public Object call() throws Exception {
1294 77dcb3f1 Panagiotis Astithas
                                                        getService().updateFile(user.getId(), file.getId(), fName, fTags);
1295 77dcb3f1 Panagiotis Astithas
                                                        return null;
1296 77dcb3f1 Panagiotis Astithas
                                                }
1297 77dcb3f1 Panagiotis Astithas
1298 77dcb3f1 Panagiotis Astithas
                                        });
1299 77dcb3f1 Panagiotis Astithas
                                }
1300 14ad7326 pastith
1301 14ad7326 pastith
                                JSONArray permissions = json.optJSONArray("permissions");
1302 14ad7326 pastith
                                Set<PermissionDTO> perms = null;
1303 14ad7326 pastith
                                if (permissions != null)
1304 14ad7326 pastith
                                        perms = parsePermissions(user, permissions);
1305 14ad7326 pastith
                                Boolean readForAll = null;
1306 14ad7326 pastith
                                if (json.opt("readForAll") != null)
1307 14ad7326 pastith
                                        readForAll = json.optBoolean("readForAll");
1308 77dcb3f1 Panagiotis Astithas
                                if (perms != null || readForAll != null) {
1309 77dcb3f1 Panagiotis Astithas
                                        final Boolean fReadForAll = readForAll;
1310 77dcb3f1 Panagiotis Astithas
                                        final Set<PermissionDTO> fPerms = perms;
1311 77dcb3f1 Panagiotis Astithas
                                        new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
1312 77dcb3f1 Panagiotis Astithas
                                                @Override
1313 77dcb3f1 Panagiotis Astithas
                                                public Object call() throws Exception {
1314 77dcb3f1 Panagiotis Astithas
                                                        getService().setFilePermissions(user.getId(), file.getId(), fReadForAll, fPerms);
1315 77dcb3f1 Panagiotis Astithas
                                                        return null;
1316 77dcb3f1 Panagiotis Astithas
                                                }
1317 77dcb3f1 Panagiotis Astithas
1318 77dcb3f1 Panagiotis Astithas
                                        });
1319 77dcb3f1 Panagiotis Astithas
                                }
1320 14ad7326 pastith
1321 14ad7326 pastith
                                if (json.opt("versioned") != null) {
1322 77dcb3f1 Panagiotis Astithas
                                        final boolean versioned = json.getBoolean("versioned");
1323 77dcb3f1 Panagiotis Astithas
                                        new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
1324 77dcb3f1 Panagiotis Astithas
                                                @Override
1325 77dcb3f1 Panagiotis Astithas
                                                public Object call() throws Exception {
1326 77dcb3f1 Panagiotis Astithas
                                                        getService().toggleFileVersioning(user.getId(), file.getId(), versioned);
1327 77dcb3f1 Panagiotis Astithas
                                                        return null;
1328 77dcb3f1 Panagiotis Astithas
                                                }
1329 77dcb3f1 Panagiotis Astithas
1330 77dcb3f1 Panagiotis Astithas
                                        });
1331 14ad7326 pastith
                                }
1332 14ad7326 pastith
                        }
1333 14ad7326 pastith
                } catch (JSONException e) {
1334 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
1335 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1336 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1337 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1338 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
1339 14ad7326 pastith
                } catch (DuplicateNameException e) {
1340 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
1341 14ad7326 pastith
                } catch (RpcException e) {
1342 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1343 77dcb3f1 Panagiotis Astithas
                } catch (Exception e) {
1344 77dcb3f1 Panagiotis Astithas
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1345 77dcb3f1 Panagiotis Astithas
                        return;
1346 14ad7326 pastith
                }
1347 14ad7326 pastith
        }
1348 14ad7326 pastith
1349 14ad7326 pastith
        /**
1350 14ad7326 pastith
         * Helper method to convert a JSON array of permissions into a set of
1351 14ad7326 pastith
         * PermissionDTO objects.
1352 14ad7326 pastith
         *
1353 14ad7326 pastith
         * @param user the current user
1354 14ad7326 pastith
         * @param permissions the JSON array to parse
1355 14ad7326 pastith
         * @return the parsed set of permissions
1356 14ad7326 pastith
         * @throws JSONException if there was an error parsing the JSON object
1357 14ad7326 pastith
         * @throws RpcException if there was an error communicating with the EJB
1358 14ad7326 pastith
         * @throws ObjectNotFoundException if the user could not be found
1359 14ad7326 pastith
         */
1360 14ad7326 pastith
        private Set<PermissionDTO> parsePermissions(User user, JSONArray permissions)
1361 14ad7326 pastith
                        throws JSONException, RpcException, ObjectNotFoundException {
1362 14ad7326 pastith
                if (permissions == null)
1363 14ad7326 pastith
                        return null;
1364 14ad7326 pastith
                Set<PermissionDTO> perms = new HashSet<PermissionDTO>();
1365 14ad7326 pastith
                for (int i = 0; i < permissions.length(); i++) {
1366 14ad7326 pastith
                        JSONObject j = permissions.getJSONObject(i);
1367 14ad7326 pastith
                        PermissionDTO perm = new PermissionDTO();
1368 14ad7326 pastith
                        perm.setModifyACL(j.optBoolean("modifyACL"));
1369 14ad7326 pastith
                        perm.setRead(j.optBoolean("read"));
1370 14ad7326 pastith
                        perm.setWrite(j.optBoolean("write"));
1371 14ad7326 pastith
                        String permUser = j.optString("user");
1372 14ad7326 pastith
                        if (!permUser.isEmpty()) {
1373 14ad7326 pastith
                                User u = getService().findUser(permUser);
1374 14ad7326 pastith
                                if (u == null)
1375 14ad7326 pastith
                                        throw new ObjectNotFoundException("User " + permUser + " not found");
1376 14ad7326 pastith
                                perm.setUser(u.getDTO());
1377 14ad7326 pastith
                        }
1378 14ad7326 pastith
                        String permGroup = j.optString("group");
1379 14ad7326 pastith
                        if (!permGroup.isEmpty()) {
1380 14ad7326 pastith
                                GroupDTO g = getService().getGroup(user.getId(), permGroup);
1381 14ad7326 pastith
                                perm.setGroup(g);
1382 14ad7326 pastith
                        }
1383 14ad7326 pastith
                        if (permUser.isEmpty() && permGroup.isEmpty() ||
1384 14ad7326 pastith
                                                permUser.isEmpty() && permGroup.isEmpty())
1385 14ad7326 pastith
                                throw new JSONException("A permission must correspond to either a user or a group");
1386 14ad7326 pastith
                        perms.add(perm);
1387 14ad7326 pastith
                }
1388 14ad7326 pastith
                return perms;
1389 14ad7326 pastith
        }
1390 14ad7326 pastith
1391 14ad7326 pastith
        /**
1392 14ad7326 pastith
         * Creates a new folder with the specified name under the folder in the provided path.
1393 14ad7326 pastith
         *
1394 14ad7326 pastith
         * @param req the HTTP request
1395 14ad7326 pastith
         * @param resp the HTTP response
1396 14ad7326 pastith
         * @param path the parent folder path
1397 14ad7326 pastith
         * @param folderName the name of the new folder
1398 14ad7326 pastith
         * @throws IOException if an input/output error occurs
1399 14ad7326 pastith
         */
1400 77dcb3f1 Panagiotis Astithas
        private void createFolder(HttpServletRequest req, HttpServletResponse resp, String path, final String folderName) throws IOException {
1401 14ad7326 pastith
                if (logger.isDebugEnabled())
1402 14ad7326 pastith
                           logger.debug("Creating folder " + folderName + " in '" + path);
1403 14ad7326 pastith
1404 77dcb3f1 Panagiotis Astithas
            final User user = getUser(req);
1405 14ad7326 pastith
            User owner = getOwner(req);
1406 14ad7326 pastith
        boolean exists = true;
1407 14ad7326 pastith
        try {
1408 e150a336 pastith
                getService().getResourceAtPath(owner.getId(), path + folderName, false);
1409 14ad7326 pastith
        } catch (ObjectNotFoundException e) {
1410 14ad7326 pastith
            exists = false;
1411 14ad7326 pastith
        } catch (RpcException e) {
1412 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path + folderName);
1413 14ad7326 pastith
                        return;
1414 14ad7326 pastith
                }
1415 14ad7326 pastith
1416 14ad7326 pastith
        if (exists) {
1417 14ad7326 pastith
            resp.addHeader("Allow", METHOD_GET + ", " + METHOD_DELETE +
1418 14ad7326 pastith
                                    ", " + METHOD_HEAD);
1419 14ad7326 pastith
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1420 14ad7326 pastith
            return;
1421 14ad7326 pastith
        }
1422 14ad7326 pastith
1423 14ad7326 pastith
                Object parent;
1424 14ad7326 pastith
                try {
1425 68410d59 pastith
                        parent = getService().getResourceAtPath(owner.getId(), path, true);
1426 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1427 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1428 14ad7326 pastith
                        return;
1429 14ad7326 pastith
                } catch (RpcException e) {
1430 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path + folderName);
1431 14ad7326 pastith
                        return;
1432 14ad7326 pastith
                }
1433 14ad7326 pastith
                try {
1434 14ad7326 pastith
                        if (parent instanceof FolderDTO) {
1435 77dcb3f1 Panagiotis Astithas
                                final FolderDTO folder = (FolderDTO) parent;
1436 77dcb3f1 Panagiotis Astithas
                                new TransactionHelper<Object>().tryExecute(new Callable<Object>() {
1437 77dcb3f1 Panagiotis Astithas
                                        @Override
1438 77dcb3f1 Panagiotis Astithas
                                        public Object call() throws Exception {
1439 77dcb3f1 Panagiotis Astithas
                                                getService().createFolder(user.getId(), folder.getId(), folderName);
1440 77dcb3f1 Panagiotis Astithas
                                                return null;
1441 77dcb3f1 Panagiotis Astithas
                                        }
1442 77dcb3f1 Panagiotis Astithas
1443 77dcb3f1 Panagiotis Astithas
                                });
1444 14ad7326 pastith
                        String newResource = getContextPath(req, true) + folderName;
1445 14ad7326 pastith
                        resp.setHeader("Location", newResource);
1446 14ad7326 pastith
                        resp.setContentType("text/plain");
1447 14ad7326 pastith
                        PrintWriter out = resp.getWriter();
1448 14ad7326 pastith
                        out.println(newResource);
1449 14ad7326 pastith
                        } else {
1450 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1451 14ad7326 pastith
                            return;
1452 14ad7326 pastith
                        }
1453 14ad7326 pastith
                } catch (DuplicateNameException e) {
1454 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1455 14ad7326 pastith
                    return;
1456 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1457 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1458 14ad7326 pastith
                    return;
1459 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1460 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1461 14ad7326 pastith
                        return;
1462 14ad7326 pastith
                } catch (RpcException e) {
1463 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path + folderName);
1464 14ad7326 pastith
                        return;
1465 77dcb3f1 Panagiotis Astithas
                } catch (Exception e) {
1466 77dcb3f1 Panagiotis Astithas
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1467 77dcb3f1 Panagiotis Astithas
                        return;
1468 14ad7326 pastith
                }
1469 14ad7326 pastith
            resp.setStatus(HttpServletResponse.SC_CREATED);
1470 14ad7326 pastith
        }
1471 14ad7326 pastith
1472 14ad7326 pastith
        /**
1473 14ad7326 pastith
         * @param req
1474 14ad7326 pastith
         * @param resp
1475 14ad7326 pastith
         * @throws IOException
1476 14ad7326 pastith
         * @throws FileNotFoundException
1477 14ad7326 pastith
         */
1478 14ad7326 pastith
        void putResource(HttpServletRequest req, HttpServletResponse resp) throws IOException, FileNotFoundException {
1479 14ad7326 pastith
        String path = getInnerPath(req, PATH_FILES);
1480 f0c744b4 Panagiotis Astithas
                try {
1481 f0c744b4 Panagiotis Astithas
                    path = URLDecoder.decode(path, "UTF-8");
1482 f0c744b4 Panagiotis Astithas
                } catch (IllegalArgumentException e) {
1483 f0c744b4 Panagiotis Astithas
                        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
1484 f0c744b4 Panagiotis Astithas
                        return;
1485 f0c744b4 Panagiotis Astithas
                }
1486 14ad7326 pastith
            if (logger.isDebugEnabled())
1487 14ad7326 pastith
                           logger.debug("Updating resource: " + path);
1488 14ad7326 pastith
1489 204107fb Panagiotis Astithas
            final User user = getUser(req);
1490 14ad7326 pastith
            User owner = getOwner(req);
1491 14ad7326 pastith
            boolean exists = true;
1492 14ad7326 pastith
        Object resource = null;
1493 14ad7326 pastith
        FileHeaderDTO file = null;
1494 14ad7326 pastith
        try {
1495 e150a336 pastith
                resource = getService().getResourceAtPath(owner.getId(), path, false);
1496 14ad7326 pastith
        } catch (ObjectNotFoundException e) {
1497 14ad7326 pastith
            exists = false;
1498 14ad7326 pastith
        } catch (RpcException e) {
1499 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1500 14ad7326 pastith
                        return;
1501 14ad7326 pastith
                }
1502 14ad7326 pastith
1503 14ad7326 pastith
        if (exists)
1504 14ad7326 pastith
                        if (resource instanceof FileHeaderDTO)
1505 14ad7326 pastith
                            file = (FileHeaderDTO) resource;
1506 14ad7326 pastith
                        else {
1507 e150a336 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT, path + " is a folder");
1508 14ad7326 pastith
                            return;
1509 14ad7326 pastith
                }
1510 14ad7326 pastith
        boolean result = true;
1511 14ad7326 pastith
1512 14ad7326 pastith
        // Temporary content file used to support partial PUT.
1513 14ad7326 pastith
        File contentFile = null;
1514 14ad7326 pastith
1515 14ad7326 pastith
        Range range = parseContentRange(req, resp);
1516 14ad7326 pastith
1517 14ad7326 pastith
        InputStream resourceInputStream = null;
1518 14ad7326 pastith
1519 14ad7326 pastith
        // Append data specified in ranges to existing content for this
1520 14ad7326 pastith
        // resource - create a temporary file on the local filesystem to
1521 14ad7326 pastith
        // perform this operation.
1522 14ad7326 pastith
        // Assume just one range is specified for now
1523 14ad7326 pastith
        if (range != null) {
1524 14ad7326 pastith
            try {
1525 14ad7326 pastith
                                contentFile = executePartialPut(req, range, path);
1526 14ad7326 pastith
                        } catch (RpcException e) {
1527 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1528 14ad7326 pastith
                                return;
1529 14ad7326 pastith
                        } catch (ObjectNotFoundException e) {
1530 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_CONFLICT);
1531 14ad7326 pastith
                        return;
1532 14ad7326 pastith
                        } catch (InsufficientPermissionsException e) {
1533 14ad7326 pastith
                                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1534 14ad7326 pastith
                        return;
1535 14ad7326 pastith
                        }
1536 14ad7326 pastith
            resourceInputStream = new FileInputStream(contentFile);
1537 14ad7326 pastith
        } else
1538 14ad7326 pastith
                        resourceInputStream = req.getInputStream();
1539 14ad7326 pastith
1540 14ad7326 pastith
        try {
1541 14ad7326 pastith
                FolderDTO folder = null;
1542 68410d59 pastith
                Object parent = getService().getResourceAtPath(owner.getId(), getParentPath(path), true);
1543 14ad7326 pastith
                if (!(parent instanceof FolderDTO)) {
1544 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1545 14ad7326 pastith
                        return;
1546 14ad7326 pastith
                }
1547 14ad7326 pastith
                       folder = (FolderDTO) parent;
1548 204107fb Panagiotis Astithas
                final String name = getLastElement(path);
1549 204107fb Panagiotis Astithas
                final String mimeType = context.getMimeType(name);
1550 b13aae04 pastith
                File uploadedFile = null;
1551 b13aae04 pastith
                try {
1552 b13aae04 pastith
                                uploadedFile = getService().uploadFile(resourceInputStream, user.getId());
1553 b13aae04 pastith
                        } catch (IOException ex) {
1554 b13aae04 pastith
                                throw new GSSIOException(ex, false);
1555 b13aae04 pastith
                        }
1556 8f128261 droutsis
                FileHeaderDTO fileDTO = null;
1557 14ad7326 pastith
            if (exists)
1558 4d737770 Fotis Stamatelopoulos
                    fileDTO = getService().updateFileContents(user.getId(), file.getId(), mimeType, uploadedFile.getCanonicalFile().length(), uploadedFile.getAbsolutePath());
1559 204107fb Panagiotis Astithas
                        else {
1560 204107fb Panagiotis Astithas
                                final File uploadedf = uploadedFile;
1561 204107fb Panagiotis Astithas
                                final FolderDTO parentf = folder;
1562 204107fb Panagiotis Astithas
                                fileDTO = new TransactionHelper<FileHeaderDTO>().tryExecute(new Callable<FileHeaderDTO>() {
1563 204107fb Panagiotis Astithas
                                        @Override
1564 204107fb Panagiotis Astithas
                                        public FileHeaderDTO call() throws Exception {
1565 4d737770 Fotis Stamatelopoulos
                                                return getService().createFile(user.getId(), parentf.getId(), name, mimeType, uploadedf.getCanonicalFile().length(), uploadedf.getAbsolutePath());
1566 204107fb Panagiotis Astithas
                                        }
1567 204107fb Panagiotis Astithas
1568 204107fb Panagiotis Astithas
                                });
1569 204107fb Panagiotis Astithas
                        }
1570 a9e3c075 Dimitris Routsis
            getService().updateAccounting(owner, new Date(), fileDTO.getFileSize());
1571 a1d5e983 pastith
                        getService().removeFileUploadProgress(user.getId(), fileDTO.getName());
1572 14ad7326 pastith
        } catch(ObjectNotFoundException e) {
1573 14ad7326 pastith
            result = false;
1574 14ad7326 pastith
        } catch (RpcException e) {
1575 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1576 14ad7326 pastith
                        return;
1577 14ad7326 pastith
        } catch (IOException e) {
1578 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1579 14ad7326 pastith
                        return;
1580 14ad7326 pastith
                } catch (GSSIOException e) {
1581 14ad7326 pastith
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1582 14ad7326 pastith
                        return;
1583 14ad7326 pastith
                } catch (DuplicateNameException e) {
1584 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1585 14ad7326 pastith
                    return;
1586 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1587 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1588 14ad7326 pastith
                    return;
1589 14ad7326 pastith
                } catch (QuotaExceededException e) {
1590 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, e.getMessage());
1591 14ad7326 pastith
                    return;
1592 204107fb Panagiotis Astithas
                } catch (Exception e) {
1593 204107fb Panagiotis Astithas
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
1594 204107fb Panagiotis Astithas
                        return;
1595 14ad7326 pastith
                }
1596 14ad7326 pastith
1597 14ad7326 pastith
        if (result) {
1598 14ad7326 pastith
            if (exists)
1599 14ad7326 pastith
                                resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
1600 14ad7326 pastith
                        else
1601 14ad7326 pastith
                                resp.setStatus(HttpServletResponse.SC_CREATED);
1602 14ad7326 pastith
        } else
1603 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_CONFLICT);
1604 14ad7326 pastith
        }
1605 14ad7326 pastith
1606 14ad7326 pastith
    /**
1607 14ad7326 pastith
     * Delete a resource.
1608 14ad7326 pastith
     *
1609 14ad7326 pastith
     * @param req The servlet request we are processing
1610 14ad7326 pastith
     * @param resp The servlet response we are processing
1611 14ad7326 pastith
         * @throws IOException if the response cannot be sent
1612 14ad7326 pastith
     */
1613 14ad7326 pastith
    void deleteResource(HttpServletRequest req, HttpServletResponse resp) throws IOException {
1614 14ad7326 pastith
        String path = getInnerPath(req, PATH_FILES);
1615 14ad7326 pastith
            if (logger.isDebugEnabled())
1616 14ad7326 pastith
                           logger.debug("Deleting resource '" + path);
1617 5e2b8ec6 koutsoub
            path = URLDecoder.decode(path, "UTF-8");
1618 14ad7326 pastith
            User user = getUser(req);
1619 14ad7326 pastith
            User owner = getOwner(req);
1620 14ad7326 pastith
            boolean exists = true;
1621 14ad7326 pastith
            Object object = null;
1622 14ad7326 pastith
            try {
1623 e150a336 pastith
                    object = getService().getResourceAtPath(owner.getId(), path, false);
1624 14ad7326 pastith
            } catch (ObjectNotFoundException e) {
1625 14ad7326 pastith
                    exists = false;
1626 14ad7326 pastith
            } catch (RpcException e) {
1627 14ad7326 pastith
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1628 14ad7326 pastith
                        return;
1629 14ad7326 pastith
                }
1630 14ad7326 pastith
1631 14ad7326 pastith
            if (!exists) {
1632 14ad7326 pastith
                    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
1633 14ad7326 pastith
                    return;
1634 14ad7326 pastith
            }
1635 14ad7326 pastith
1636 14ad7326 pastith
            FolderDTO folder = null;
1637 14ad7326 pastith
            FileHeaderDTO file = null;
1638 14ad7326 pastith
            if (object instanceof FolderDTO)
1639 14ad7326 pastith
                    folder = (FolderDTO) object;
1640 14ad7326 pastith
            else
1641 14ad7326 pastith
                    file = (FileHeaderDTO) object;
1642 14ad7326 pastith
1643 14ad7326 pastith
            if (file != null)
1644 14ad7326 pastith
                        try {
1645 14ad7326 pastith
                                getService().deleteFile(user.getId(), file.getId());
1646 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1647 14ad7326 pastith
                        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1648 14ad7326 pastith
                                return;
1649 14ad7326 pastith
                    } catch (ObjectNotFoundException e) {
1650 14ad7326 pastith
                            // Although we had already found the object, it was
1651 14ad7326 pastith
                            // probably deleted from another thread.
1652 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
1653 14ad7326 pastith
                            return;
1654 14ad7326 pastith
                    } catch (RpcException e) {
1655 14ad7326 pastith
                            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1656 14ad7326 pastith
                            return;
1657 14ad7326 pastith
                    }
1658 14ad7326 pastith
                else if (folder != null)
1659 14ad7326 pastith
                        try {
1660 14ad7326 pastith
                            getService().deleteFolder(user.getId(), folder.getId());
1661 14ad7326 pastith
                } catch (InsufficientPermissionsException e) {
1662 14ad7326 pastith
                        resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
1663 14ad7326 pastith
                        return;
1664 14ad7326 pastith
                    } catch (ObjectNotFoundException e) {
1665 14ad7326 pastith
                        resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
1666 14ad7326 pastith
                        return;
1667 14ad7326 pastith
                    } catch (RpcException e) {
1668 14ad7326 pastith
                        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1669 14ad7326 pastith
                        return;
1670 14ad7326 pastith
                    }
1671 14ad7326 pastith
                resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
1672 14ad7326 pastith
            return;
1673 14ad7326 pastith
    }
1674 14ad7326 pastith
1675 14ad7326 pastith
        /**
1676 14ad7326 pastith
     * Return an InputStream to a JSON representation of the contents
1677 14ad7326 pastith
     * of this directory.
1678 14ad7326 pastith
     *
1679 14ad7326 pastith
         * @param user the user that made the request
1680 14ad7326 pastith
     * @param folder the specified directory
1681 14ad7326 pastith
     * @return an input stream with the rendered contents
1682 14ad7326 pastith
         * @throws IOException if the response cannot be sent
1683 14ad7326 pastith
     * @throws ServletException
1684 14ad7326 pastith
         * @throws InsufficientPermissionsException if the user does not have
1685 14ad7326 pastith
         *                         the necessary privileges to read the directory
1686 14ad7326 pastith
     */
1687 2b90ab8a pastith
    private InputStream renderJson(User user, FolderDTO folder) throws IOException,
1688 14ad7326 pastith
                    ServletException, InsufficientPermissionsException {
1689 14ad7326 pastith
            JSONObject json = new JSONObject();
1690 14ad7326 pastith
            try {
1691 08c62ec7 pastith
                        json.put("name", folder.getName()).
1692 47d800f9 pastith
                                        put("owner", folder.getOwner().getUsername()).
1693 14ad7326 pastith
                                        put("createdBy", folder.getAuditInfo().getCreatedBy().getUsername()).
1694 14ad7326 pastith
                                        put("creationDate", folder.getAuditInfo().getCreationDate().getTime()).
1695 14ad7326 pastith
                                        put("deleted", folder.isDeleted());
1696 77f75ac4 pastith
                        if (folder.getAuditInfo().getModifiedBy() != null)
1697 77f75ac4 pastith
                                json.put("modifiedBy", folder.getAuditInfo().getModifiedBy().getUsername()).
1698 77f75ac4 pastith
                                                put("modificationDate", folder.getAuditInfo().getModificationDate().getTime());
1699 8cc77d04 pastith
                        if (folder.getParent() != null) {
1700 8cc77d04 pastith
                                JSONObject j = new JSONObject();
1701 865f1d02 pastith
                                j.put("uri", getApiRoot() + folder.getParent().getURI());
1702 8cc77d04 pastith
                                j.put("name", folder.getParent().getName());
1703 8cc77d04 pastith
                                json.put("parent", j);
1704 d6ba3052 koutsoub
                        }
1705 f7abcd5a pastith
                    List<JSONObject> subfolders = new ArrayList<JSONObject>();
1706 14ad7326 pastith
                    for (FolderDTO f: folder.getSubfolders())
1707 f7abcd5a pastith
                                if (!f.isDeleted()) {
1708 f7abcd5a pastith
                                        JSONObject j = new JSONObject();
1709 f7abcd5a pastith
                                        j.put("name", f.getName()).
1710 2b90ab8a pastith
                                                put("uri", getApiRoot() + f.getURI());
1711 f7abcd5a pastith
                                        subfolders.add(j);
1712 f7abcd5a pastith
                                }
1713 f7abcd5a pastith
                    json.put("folders", subfolders);
1714 f7abcd5a pastith
                    List<JSONObject> files = new ArrayList<JSONObject>();
1715 3d1b9329 koutsoub
                    List<FileHeaderDTO> fileHeaders = getService().getFiles(user.getId(), folder.getId(), false);
1716 f7abcd5a pastith
                    for (FileHeaderDTO f: fileHeaders) {
1717 f7abcd5a pastith
                            JSONObject j = new JSONObject();
1718 f7abcd5a pastith
                                j.put("name", f.getName()).
1719 3f2e14a0 pastith
                                        put("owner", f.getOwner().getUsername()).
1720 f7abcd5a pastith
                                        put("deleted", f.isDeleted()).
1721 f7abcd5a pastith
                                        put("version", f.getVersion()).
1722 0e4865ee pastith
                                        put("content", f.getMimeType()).
1723 f7abcd5a pastith
                                        put("size", f.getFileSize()).
1724 f7abcd5a pastith
                                        put("creationDate", f.getAuditInfo().getCreationDate().getTime()).
1725 d6ba3052 koutsoub
                                        put("path", f.getFolder().getPath()).
1726 2b90ab8a pastith
                                        put("uri", getApiRoot() + f.getURI());
1727 eee18108 pastith
                                if (f.getAuditInfo().getModificationDate() != null)
1728 eee18108 pastith
                                        j.put("modificationDate", f.getAuditInfo().getModificationDate().getTime());
1729 f7abcd5a pastith
                                files.add(j);
1730 f7abcd5a pastith
                    }
1731 14ad7326 pastith
                    json.put("files", files);
1732 14ad7326 pastith
                    Set<PermissionDTO> perms = getService().getFolderPermissions(user.getId(), folder.getId());
1733 14ad7326 pastith
                    json.put("permissions", renderJson(perms));
1734 14ad7326 pastith
                } catch (JSONException e) {
1735 14ad7326 pastith
                        throw new ServletException(e);
1736 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1737 14ad7326 pastith
                        throw new ServletException(e);
1738 14ad7326 pastith
                } catch (RpcException e) {
1739 14ad7326 pastith
                        throw new ServletException(e);
1740 14ad7326 pastith
                }
1741 14ad7326 pastith
1742 14ad7326 pastith
            // Prepare a writer to a buffered area
1743 14ad7326 pastith
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
1744 14ad7326 pastith
            OutputStreamWriter osWriter = new OutputStreamWriter(stream, "UTF8");
1745 14ad7326 pastith
            PrintWriter writer = new PrintWriter(osWriter);
1746 14ad7326 pastith
1747 14ad7326 pastith
            // Return an input stream to the underlying bytes
1748 14ad7326 pastith
            writer.write(json.toString());
1749 14ad7326 pastith
            writer.flush();
1750 14ad7326 pastith
            return new ByteArrayInputStream(stream.toByteArray());
1751 14ad7326 pastith
    }
1752 14ad7326 pastith
1753 14ad7326 pastith
        /**
1754 14ad7326 pastith
     * Return a String with a JSON representation of the metadata
1755 77f75ac4 pastith
     * of the specified folder.
1756 77f75ac4 pastith
         * @throws RpcException
1757 77f75ac4 pastith
         * @throws InsufficientPermissionsException
1758 77f75ac4 pastith
         * @throws ObjectNotFoundException
1759 77f75ac4 pastith
     */
1760 77f75ac4 pastith
    private String renderJsonMetadata(User user, FolderDTO folder)
1761 77f75ac4 pastith
                    throws ServletException, InsufficientPermissionsException {
1762 77f75ac4 pastith
            // Check if the user has read permission.
1763 77f75ac4 pastith
                try {
1764 77f75ac4 pastith
                        if (!getService().canReadFolder(user.getId(), folder.getId()))
1765 77f75ac4 pastith
                                throw new InsufficientPermissionsException();
1766 77f75ac4 pastith
                } catch (ObjectNotFoundException e) {
1767 77f75ac4 pastith
                        throw new ServletException(e);
1768 77f75ac4 pastith
                } catch (RpcException e) {
1769 77f75ac4 pastith
                        throw new ServletException(e);
1770 77f75ac4 pastith
                }
1771 77f75ac4 pastith
1772 77f75ac4 pastith
            JSONObject json = new JSONObject();
1773 77f75ac4 pastith
            try {
1774 77f75ac4 pastith
                        json.put("name", folder.getName()).
1775 77f75ac4 pastith
                        put("owner", folder.getOwner().getUsername()).
1776 77f75ac4 pastith
                        put("createdBy", folder.getAuditInfo().getCreatedBy().getUsername()).
1777 77f75ac4 pastith
                        put("creationDate", folder.getAuditInfo().getCreationDate().getTime()).
1778 77f75ac4 pastith
                        put("deleted", folder.isDeleted());
1779 77f75ac4 pastith
                        if (folder.getAuditInfo().getModifiedBy() != null)
1780 77f75ac4 pastith
                                json.put("modifiedBy", folder.getAuditInfo().getModifiedBy().getUsername()).
1781 77f75ac4 pastith
                                                put("modificationDate", folder.getAuditInfo().getModificationDate().getTime());
1782 77f75ac4 pastith
                } catch (JSONException e) {
1783 77f75ac4 pastith
                        throw new ServletException(e);
1784 77f75ac4 pastith
                }
1785 77f75ac4 pastith
            return json.toString();
1786 77f75ac4 pastith
    }
1787 77f75ac4 pastith
1788 77f75ac4 pastith
        /**
1789 77f75ac4 pastith
     * Return a String with a JSON representation of the metadata
1790 14ad7326 pastith
     * of the specified file. If an old file body is provided, then
1791 14ad7326 pastith
     * the metadata of that particular version will be returned.
1792 14ad7326 pastith
     *
1793 14ad7326 pastith
         * @param user the user that made the request
1794 14ad7326 pastith
     * @param file the specified file header
1795 14ad7326 pastith
     * @param oldBody the version number
1796 14ad7326 pastith
     * @return the JSON-encoded file
1797 14ad7326 pastith
     * @throws ServletException
1798 14ad7326 pastith
         * @throws InsufficientPermissionsException if the user does not have
1799 14ad7326 pastith
         *                         the necessary privileges to read the directory
1800 14ad7326 pastith
     */
1801 14ad7326 pastith
    private String renderJson(User user, FileHeaderDTO file, FileBodyDTO oldBody)
1802 3a90e4f3 pastith
                    throws ServletException, InsufficientPermissionsException {
1803 14ad7326 pastith
            JSONObject json = new JSONObject();
1804 14ad7326 pastith
            try {
1805 8cc77d04 pastith
                    // Need to encode file name in order to properly display it in the web client.
1806 5e2b8ec6 koutsoub
                        json.put("name", URLEncoder.encode(file.getName(),"UTF-8")).
1807 47d800f9 pastith
                                        put("owner", file.getOwner().getUsername()).
1808 47d800f9 pastith
                                        put("versioned", file.isVersioned()).
1809 47d800f9 pastith
                                        put("version", oldBody != null ? oldBody.getVersion() : file.getVersion()).
1810 47d800f9 pastith
                                        put("readForAll", file.isReadForAll()).
1811 fc5ef2cc droutsis
                                        put("tags", renderJson(file.getTags())).
1812 2b90ab8a pastith
                                        put("path", file.getFolder().getPath()).
1813 865f1d02 pastith
                                    put("uri", getApiRoot() + file.getURI()).
1814 14ad7326 pastith
                                        put("deleted", file.isDeleted());
1815 8cc77d04 pastith
                        JSONObject j = new JSONObject();
1816 865f1d02 pastith
                        j.put("uri", getApiRoot() + file.getFolder().getURI()).
1817 8cc77d04 pastith
                                        put("name", URLEncoder.encode(file.getFolder().getName(),"UTF-8"));
1818 8cc77d04 pastith
                        json.put("folder", j);
1819 14ad7326 pastith
                        if (oldBody != null)
1820 14ad7326 pastith
                                json.put("createdBy", oldBody.getAuditInfo().getCreatedBy().getUsername()).
1821 14ad7326 pastith
                                                put("creationDate", oldBody.getAuditInfo().getCreationDate().getTime()).
1822 14ad7326 pastith
                                                put("modifiedBy", oldBody.getAuditInfo().getModifiedBy().getUsername()).
1823 2d40bbc6 pastith
                                                put("modificationDate", oldBody.getAuditInfo().getModificationDate().getTime()).
1824 0e4865ee pastith
                                                put("content", oldBody.getMimeType()).
1825 2d40bbc6 pastith
                                                put("size", oldBody.getFileSize());
1826 14ad7326 pastith
                        else
1827 14ad7326 pastith
                                json.put("createdBy", file.getAuditInfo().getCreatedBy().getUsername()).
1828 14ad7326 pastith
                                                put("creationDate", file.getAuditInfo().getCreationDate().getTime()).
1829 14ad7326 pastith
                                                put("modifiedBy", file.getAuditInfo().getModifiedBy().getUsername()).
1830 2d40bbc6 pastith
                                                put("modificationDate", file.getAuditInfo().getModificationDate().getTime()).
1831 0e4865ee pastith
                                                put("content", file.getMimeType()).
1832 2d40bbc6 pastith
                                                put("size", file.getFileSize());
1833 14ad7326 pastith
                    Set<PermissionDTO> perms = getService().getFilePermissions(user.getId(), file.getId());
1834 14ad7326 pastith
                    json.put("permissions", renderJson(perms));
1835 14ad7326 pastith
                } catch (JSONException e) {
1836 14ad7326 pastith
                        throw new ServletException(e);
1837 14ad7326 pastith
                } catch (ObjectNotFoundException e) {
1838 14ad7326 pastith
                        throw new ServletException(e);
1839 14ad7326 pastith
                } catch (RpcException e) {
1840 14ad7326 pastith
                        throw new ServletException(e);
1841 3a90e4f3 pastith
                } catch (UnsupportedEncodingException e) {
1842 3a90e4f3 pastith
                        throw new ServletException(e);
1843 14ad7326 pastith
                }
1844 14ad7326 pastith
1845 14ad7326 pastith
            return json.toString();
1846 14ad7326 pastith
    }
1847 14ad7326 pastith
1848 14ad7326 pastith
        /**
1849 14ad7326 pastith
         * Return a String with a JSON representation of the
1850 14ad7326 pastith
         * specified set of permissions.
1851 14ad7326 pastith
     *
1852 14ad7326 pastith
         * @param permissions the set of permissions
1853 14ad7326 pastith
         * @return the JSON-encoded object
1854 14ad7326 pastith
         * @throws JSONException
1855 fc5ef2cc droutsis
         * @throws UnsupportedEncodingException
1856 14ad7326 pastith
         */
1857 fc5ef2cc droutsis
        private JSONArray renderJson(Set<PermissionDTO> permissions) throws JSONException, UnsupportedEncodingException {
1858 14ad7326 pastith
                JSONArray perms = new JSONArray();
1859 14ad7326 pastith
                for (PermissionDTO p: permissions) {
1860 14ad7326 pastith
                        JSONObject permission = new JSONObject();
1861 14ad7326 pastith
                        permission.put("read", p.hasRead()).put("write", p.hasWrite()).put("modifyACL", p.hasModifyACL());
1862 14ad7326 pastith
                        if (p.getUser() != null)
1863 14ad7326 pastith
                                permission.put("user", p.getUser().getUsername());
1864 14ad7326 pastith
                        if (p.getGroup() != null)
1865 fc5ef2cc droutsis
                                permission.put("group", URLEncoder.encode(p.getGroup().getName(),"UTF-8"));
1866 14ad7326 pastith
                        perms.put(permission);
1867 14ad7326 pastith
                }
1868 14ad7326 pastith
                return perms;
1869 14ad7326 pastith
        }
1870 14ad7326 pastith
1871 14ad7326 pastith
        /**
1872 fc5ef2cc droutsis
         * Return a String with a JSON representation of the
1873 fc5ef2cc droutsis
         * specified collection of tags.
1874 fc5ef2cc droutsis
     *
1875 fc5ef2cc droutsis
         * @param tags the collection of tags
1876 fc5ef2cc droutsis
         * @return the JSON-encoded object
1877 fc5ef2cc droutsis
         * @throws JSONException
1878 fc5ef2cc droutsis
         * @throws UnsupportedEncodingException
1879 fc5ef2cc droutsis
         */
1880 fc5ef2cc droutsis
        private JSONArray renderJson(Collection<String> tags) throws JSONException, UnsupportedEncodingException {
1881 fc5ef2cc droutsis
                JSONArray tagArray = new JSONArray();
1882 fc5ef2cc droutsis
                for (String t: tags)
1883 fc5ef2cc droutsis
                        tagArray.put(URLEncoder.encode(t,"UTF-8"));
1884 fc5ef2cc droutsis
                return tagArray;
1885 fc5ef2cc droutsis
        }
1886 fc5ef2cc droutsis
1887 fc5ef2cc droutsis
        /**
1888 14ad7326 pastith
         * Retrieves the user who owns the destination namespace, for a
1889 14ad7326 pastith
         * copy or move request.
1890 14ad7326 pastith
         *
1891 14ad7326 pastith
         * @param req the HTTP request
1892 14ad7326 pastith
         * @return the owner of the namespace
1893 14ad7326 pastith
         */
1894 14ad7326 pastith
        protected User getDestinationOwner(HttpServletRequest req) {
1895 14ad7326 pastith
                return (User) req.getAttribute(DESTINATION_OWNER_ATTRIBUTE);
1896 14ad7326 pastith
        }
1897 e150a336 pastith
1898 e150a336 pastith
        /**
1899 e150a336 pastith
         * A helper inner class for updating the progress status of a file upload.
1900 e150a336 pastith
         *
1901 e150a336 pastith
         * @author kman
1902 e150a336 pastith
         */
1903 e150a336 pastith
        public static class StatusProgressListener implements ProgressListener {
1904 e150a336 pastith
                private int percentLogged = 0;
1905 e150a336 pastith
                private long bytesTransferred = 0;
1906 e150a336 pastith
1907 e150a336 pastith
                private long fileSize = -100;
1908 e150a336 pastith
1909 e150a336 pastith
                private long tenKBRead = -1;
1910 e150a336 pastith
1911 e150a336 pastith
                private Long userId;
1912 e150a336 pastith
1913 e150a336 pastith
                private String filename;
1914 e150a336 pastith
1915 e150a336 pastith
                private ExternalAPI service;
1916 e150a336 pastith
1917 e150a336 pastith
                public StatusProgressListener(ExternalAPI aService) {
1918 e150a336 pastith
                        service = aService;
1919 e150a336 pastith
                }
1920 e150a336 pastith
1921 e150a336 pastith
                /**
1922 e150a336 pastith
                 * Modify the userId.
1923 e150a336 pastith
                 *
1924 e150a336 pastith
                 * @param aUserId the userId to set
1925 e150a336 pastith
                 */
1926 e150a336 pastith
                public void setUserId(Long aUserId) {
1927 e150a336 pastith
                        userId = aUserId;
1928 e150a336 pastith
                }
1929 e150a336 pastith
1930 e150a336 pastith
                /**
1931 e150a336 pastith
                 * Modify the filename.
1932 e150a336 pastith
                 *
1933 e150a336 pastith
                 * @param aFilename the filename to set
1934 e150a336 pastith
                 */
1935 e150a336 pastith
                public void setFilename(String aFilename) {
1936 e150a336 pastith
                        filename = aFilename;
1937 e150a336 pastith
                }
1938 e150a336 pastith
1939 e150a336 pastith
                public void update(long bytesRead, long contentLength, int items) {
1940 e150a336 pastith
                        //monitoring per percent of bytes uploaded
1941 e150a336 pastith
                        bytesTransferred = bytesRead;
1942 e150a336 pastith
                        if (fileSize != contentLength)
1943 e150a336 pastith
                                fileSize = contentLength;
1944 e150a336 pastith
                        int percent = new Long(bytesTransferred * 100 / fileSize).intValue();
1945 e150a336 pastith
1946 e150a336 pastith
                        if (percent < 5 || percent % TRACK_PROGRESS_PERCENT == 0 )
1947 e150a336 pastith
                                if (percent != percentLogged){
1948 e150a336 pastith
                                        percentLogged = percent;
1949 e150a336 pastith
                                        try {
1950 e150a336 pastith
                                                if (userId != null && filename != null)
1951 e150a336 pastith
                                                        service.createFileUploadProgress(userId, filename, bytesTransferred, fileSize);
1952 e150a336 pastith
                                        } catch (ObjectNotFoundException e) {
1953 e150a336 pastith
                                                // Swallow the exception since it is going to be caught
1954 e150a336 pastith
                                                // by previously called methods
1955 e150a336 pastith
                                        }
1956 e150a336 pastith
                                }
1957 e150a336 pastith
                }
1958 e150a336 pastith
        }
1959 14ad7326 pastith
}