This project has retired. For details please refer to its
Attic page.
CmisBrowserBindingServlet xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.server.impl.browser;
20
21 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_ADD_OBJECT_TO_FOLDER;
22 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_APPEND_CONTENT;
23 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_APPLY_ACL;
24 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_APPLY_POLICY;
25 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_BULK_UPDATE;
26 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CANCEL_CHECK_OUT;
27 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CHECK_IN;
28 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CHECK_OUT;
29 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_DOCUMENT;
30 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_DOCUMENT_FROM_SOURCE;
31 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_FOLDER;
32 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_ITEM;
33 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_POLICY;
34 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_RELATIONSHIP;
35 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_TYPE;
36 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE;
37 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE_CONTENT;
38 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE_TREE;
39 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE_TYPE;
40 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_MOVE;
41 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_QUERY;
42 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_REMOVE_OBJECT_FROM_FOLDER;
43 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_REMOVE_POLICY;
44 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_SET_CONTENT;
45 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_UPDATE_PROPERTIES;
46 import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_UPDATE_TYPE;
47 import static org.apache.chemistry.opencmis.commons.impl.Constants.PARAM_OBJECT_ID;
48 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_ACL;
49 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_ALLOWABLEACTIONS;
50 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CHECKEDOUT;
51 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CHILDREN;
52 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CONTENT;
53 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CONTENT_CHANGES;
54 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_DESCENDANTS;
55 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_FOLDER_TREE;
56 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_LAST_RESULT;
57 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_OBJECT;
58 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PARENT;
59 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PARENTS;
60 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_POLICIES;
61 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PROPERTIES;
62 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_QUERY;
63 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_RELATIONSHIPS;
64 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_RENDITIONS;
65 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_REPOSITORY_INFO;
66 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_CHILDREN;
67 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_DEFINITION;
68 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_DESCENDANTS;
69 import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_VERSIONS;
70 import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_EXCEPTION;
71 import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_MESSAGE;
72 import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_STACKTRACE;
73 import static org.apache.chemistry.opencmis.server.shared.Dispatcher.METHOD_GET;
74 import static org.apache.chemistry.opencmis.server.shared.Dispatcher.METHOD_HEAD;
75 import static org.apache.chemistry.opencmis.server.shared.Dispatcher.METHOD_POST;
76
77 import java.io.IOException;
78 import java.io.InputStream;
79 import java.io.PrintWriter;
80 import java.util.Map;
81
82 import javax.servlet.ServletConfig;
83 import javax.servlet.ServletException;
84 import javax.servlet.http.HttpServletRequest;
85 import javax.servlet.http.HttpServletResponse;
86
87 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
88 import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
89 import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
90 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
91 import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
92 import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException;
93 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
94 import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
95 import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
96 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
97 import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
98 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
99 import org.apache.chemistry.opencmis.commons.exceptions.CmisServiceUnavailableException;
100 import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
101 import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException;
102 import org.apache.chemistry.opencmis.commons.exceptions.CmisTooManyRequestsException;
103 import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
104 import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
105 import org.apache.chemistry.opencmis.commons.exceptions.CmisVersioningException;
106 import org.apache.chemistry.opencmis.commons.impl.Constants;
107 import org.apache.chemistry.opencmis.commons.impl.IOUtils;
108 import org.apache.chemistry.opencmis.commons.impl.json.JSONObject;
109 import org.apache.chemistry.opencmis.commons.server.CallContext;
110 import org.apache.chemistry.opencmis.commons.server.CmisService;
111 import org.apache.chemistry.opencmis.server.impl.ServerVersion;
112 import org.apache.chemistry.opencmis.server.impl.browser.token.TokenHandler;
113 import org.apache.chemistry.opencmis.server.shared.AbstractCmisHttpServlet;
114 import org.apache.chemistry.opencmis.server.shared.Dispatcher;
115 import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
116 import org.apache.chemistry.opencmis.server.shared.HEADHttpServletRequestWrapper;
117 import org.apache.chemistry.opencmis.server.shared.HttpUtils;
118 import org.apache.chemistry.opencmis.server.shared.NoBodyHttpServletResponseWrapper;
119 import org.apache.chemistry.opencmis.server.shared.QueryStringHttpServletRequestWrapper;
120 import org.apache.chemistry.opencmis.server.shared.ServiceCall;
121 import org.apache.chemistry.opencmis.server.shared.TempStoreOutputStreamFactory;
122 import org.slf4j.Logger;
123 import org.slf4j.LoggerFactory;
124
125
126
127
128 public class CmisBrowserBindingServlet extends AbstractCmisHttpServlet {
129
130 private static final long serialVersionUID = 1L;
131
132 private static final Logger LOG = LoggerFactory.getLogger(CmisBrowserBindingServlet.class);
133
134 private final Dispatcher repositoryDispatcher = new Dispatcher(false);
135 private final Dispatcher rootDispatcher = new Dispatcher(false);
136 private static final ErrorServiceCall ERROR_SERTVICE_CALL = new ErrorServiceCall();
137
138 public enum CallUrl {
139 SERVICE, REPOSITORY, ROOT
140 }
141
142 @Override
143 public void init(ServletConfig config) throws ServletException {
144 super.init(config);
145
146
147 setBinding(CallContext.BINDING_BROWSER);
148
149
150 setCmisVersion(CmisVersion.CMIS_1_1);
151
152
153 addRepositoryResource("", METHOD_GET, new RepositoryService.GetRepositories());
154 addRepositoryResource(SELECTOR_REPOSITORY_INFO, METHOD_GET, new RepositoryService.GetRepositoryInfo());
155 addRepositoryResource(SELECTOR_LAST_RESULT, METHOD_GET, new RepositoryService.GetLastResult());
156 addRepositoryResource(SELECTOR_TYPE_CHILDREN, METHOD_GET, new RepositoryService.GetTypeChildren());
157 addRepositoryResource(SELECTOR_TYPE_DESCENDANTS, METHOD_GET, new RepositoryService.GetTypeDescendants());
158 addRepositoryResource(SELECTOR_TYPE_DEFINITION, METHOD_GET, new RepositoryService.GetTypeDefinition());
159 addRepositoryResource(CMISACTION_CREATE_TYPE, METHOD_POST, new RepositoryService.CreateType());
160 addRepositoryResource(CMISACTION_UPDATE_TYPE, METHOD_POST, new RepositoryService.UpdateType());
161 addRepositoryResource(CMISACTION_DELETE_TYPE, METHOD_POST, new RepositoryService.DeleteType());
162 addRepositoryResource(SELECTOR_QUERY, METHOD_GET, new DiscoveryService.Query());
163 addRepositoryResource(SELECTOR_CHECKEDOUT, METHOD_GET, new NavigationService.GetCheckedOutDocs());
164 addRepositoryResource(SELECTOR_CONTENT_CHANGES, METHOD_GET, new DiscoveryService.GetContentChanges());
165
166 addRepositoryResource(CMISACTION_QUERY, METHOD_POST, new DiscoveryService.Query());
167 addRepositoryResource(CMISACTION_CREATE_DOCUMENT, METHOD_POST, new ObjectService.CreateDocument());
168 addRepositoryResource(CMISACTION_CREATE_DOCUMENT_FROM_SOURCE, METHOD_POST,
169 new ObjectService.CreateDocumentFromSource());
170 addRepositoryResource(CMISACTION_CREATE_POLICY, METHOD_POST, new ObjectService.CreatePolicy());
171 addRepositoryResource(CMISACTION_CREATE_ITEM, METHOD_POST, new ObjectService.CreateItem());
172 addRepositoryResource(CMISACTION_CREATE_RELATIONSHIP, METHOD_POST, new ObjectService.CreateRelationship());
173 addRepositoryResource(CMISACTION_BULK_UPDATE, METHOD_POST, new ObjectService.BulkUpdateProperties());
174
175
176 addRootResource(SELECTOR_OBJECT, METHOD_GET, new ObjectService.GetObject());
177 addRootResource(SELECTOR_PROPERTIES, METHOD_GET, new ObjectService.GetProperties());
178 addRootResource(SELECTOR_ALLOWABLEACTIONS, METHOD_GET, new ObjectService.GetAllowableActions());
179 addRootResource(SELECTOR_RENDITIONS, METHOD_GET, new ObjectService.GetRenditions());
180 addRootResource(SELECTOR_CONTENT, METHOD_GET, new ObjectService.GetContentStream());
181 addRootResource(SELECTOR_CHILDREN, METHOD_GET, new NavigationService.GetChildren());
182 addRootResource(SELECTOR_DESCENDANTS, METHOD_GET, new NavigationService.GetDescendants());
183 addRootResource(SELECTOR_FOLDER_TREE, METHOD_GET, new NavigationService.GetFolderTree());
184 addRootResource(SELECTOR_PARENT, METHOD_GET, new NavigationService.GetFolderParent());
185 addRootResource(SELECTOR_PARENTS, METHOD_GET, new NavigationService.GetObjectParents());
186 addRootResource(SELECTOR_VERSIONS, METHOD_GET, new VersioningService.GetAllVersions());
187 addRootResource(SELECTOR_RELATIONSHIPS, METHOD_GET, new RelationshipService.GetObjectRelationships());
188 addRootResource(SELECTOR_CHECKEDOUT, METHOD_GET, new NavigationService.GetCheckedOutDocs());
189 addRootResource(SELECTOR_POLICIES, METHOD_GET, new PolicyService.GetAppliedPolicies());
190 addRootResource(SELECTOR_ACL, METHOD_GET, new AclService.GetACL());
191
192 addRootResource(CMISACTION_CREATE_DOCUMENT, METHOD_POST, new ObjectService.CreateDocument());
193 addRootResource(CMISACTION_CREATE_DOCUMENT_FROM_SOURCE, METHOD_POST,
194 new ObjectService.CreateDocumentFromSource());
195 addRootResource(CMISACTION_CREATE_FOLDER, METHOD_POST, new ObjectService.CreateFolder());
196 addRootResource(CMISACTION_CREATE_POLICY, METHOD_POST, new ObjectService.CreatePolicy());
197 addRootResource(CMISACTION_CREATE_ITEM, METHOD_POST, new ObjectService.CreateItem());
198 addRootResource(CMISACTION_UPDATE_PROPERTIES, METHOD_POST, new ObjectService.UpdateProperties());
199 addRootResource(CMISACTION_SET_CONTENT, METHOD_POST, new ObjectService.SetContentStream());
200 addRootResource(CMISACTION_APPEND_CONTENT, METHOD_POST, new ObjectService.AppendContentStream());
201 addRootResource(CMISACTION_DELETE_CONTENT, METHOD_POST, new ObjectService.DeleteContentStream());
202 addRootResource(CMISACTION_DELETE, METHOD_POST, new ObjectService.DeleteObject());
203 addRootResource(CMISACTION_DELETE_TREE, METHOD_POST, new ObjectService.DeleteTree());
204 addRootResource(CMISACTION_MOVE, METHOD_POST, new ObjectService.MoveObject());
205 addRootResource(CMISACTION_ADD_OBJECT_TO_FOLDER, METHOD_POST, new MultiFilingService.AddObjectToFolder());
206 addRootResource(CMISACTION_REMOVE_OBJECT_FROM_FOLDER, METHOD_POST,
207 new MultiFilingService.RemoveObjectFromFolder());
208 addRootResource(CMISACTION_CHECK_OUT, METHOD_POST, new VersioningService.CheckOut());
209 addRootResource(CMISACTION_CANCEL_CHECK_OUT, METHOD_POST, new VersioningService.CancelCheckOut());
210 addRootResource(CMISACTION_CHECK_IN, METHOD_POST, new VersioningService.CheckIn());
211 addRootResource(CMISACTION_APPLY_POLICY, METHOD_POST, new PolicyService.ApplyPolicy());
212 addRootResource(CMISACTION_REMOVE_POLICY, METHOD_POST, new PolicyService.RemovePolicy());
213 addRootResource(CMISACTION_APPLY_ACL, METHOD_POST, new AclService.ApplyACL());
214
215
216 addRootResource("folder", METHOD_GET, new NavigationService.GetFolderTree());
217 }
218
219 @Override
220 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
221 IOException {
222 CallContext context = null;
223
224 boolean flush = true;
225 try {
226
227 String method = request.getMethod();
228 if (!METHOD_GET.equals(method) && !METHOD_HEAD.equals(method)) {
229 checkCsrfToken(request, response, false, false);
230 }
231
232
233 response.addHeader("Cache-Control", "private, max-age=0");
234 response.addHeader("Server", ServerVersion.OPENCMIS_SERVER);
235
236
237 String[] pathFragments = HttpUtils.splitPath(request);
238
239
240 TempStoreOutputStreamFactory streamFactoy = TempStoreOutputStreamFactory.newInstance(getServiceFactory(),
241 pathFragments.length > 0 ? pathFragments[0] : null, request);
242
243
244 if (METHOD_GET.equals(method)) {
245 request = new QueryStringHttpServletRequestWrapper(request);
246 } else if (METHOD_POST.equals(method)) {
247 request = new POSTHttpServletRequestWrapper(request, streamFactoy);
248 } else if (METHOD_HEAD.equals(method)) {
249 request = new HEADHttpServletRequestWrapper(request);
250 response = new NoBodyHttpServletResponseWrapper(response);
251 } else {
252 throw new CmisNotSupportedException("Unsupported method");
253 }
254
255
256 if (request.getParameter("login") != null && getCallContextHandler() instanceof TokenHandler) {
257 ((TokenHandler) getCallContextHandler()).service(getServletContext(), request, response);
258 return;
259 }
260
261 context = createContext(getServletContext(), request, response, streamFactoy);
262 dispatch(context, request, response, pathFragments);
263 } catch (Exception e) {
264 if (e instanceof CmisUnauthorizedException) {
265 response.setHeader("WWW-Authenticate", "Basic realm=\"CMIS\", charset=\"UTF-8\"");
266 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization Required");
267 } else if (e instanceof CmisPermissionDeniedException) {
268 if (context == null || context.getUsername() == null) {
269 response.setHeader("WWW-Authenticate", "Basic realm=\"CMIS\", charset=\"UTF-8\"");
270 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization Required");
271 } else {
272 printError(context, e, request, response);
273 }
274 } else {
275
276
277
278
279 flush = !(e instanceof IOException);
280
281 printError(context, e, request, response);
282 }
283 } catch (Throwable t) {
284 LOG.error(createLogMessage(t, request), t);
285
286 try {
287 response.resetBuffer();
288 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
289 response.setContentType(AbstractBrowserServiceCall.JSON_MIME_TYPE);
290 response.setCharacterEncoding(IOUtils.UTF8);
291
292 PrintWriter pw = response.getWriter();
293 pw.print("{\"exception\":\"runtime\",\"message\": \"An error occurred!\"}");
294 pw.flush();
295 } catch (Exception te) {
296
297
298 flush = false;
299 }
300
301 throw t;
302 } finally {
303
304 if (request instanceof POSTHttpServletRequestWrapper) {
305 InputStream stream = ((POSTHttpServletRequestWrapper) request).getStream();
306 if (stream != null) {
307 try {
308 stream.close();
309 } catch (IOException e) {
310 LOG.error("Could not close POST stream: {}", e.toString(), e);
311 }
312 }
313 }
314
315
316 if (flush) {
317 try {
318 response.flushBuffer();
319 } catch (IOException ioe) {
320 LOG.error("Could not flush resposne: {}", ioe.toString(), ioe);
321 }
322 }
323 }
324 }
325
326
327
328
329
330
331 protected void addRepositoryResource(String resource, String httpMethod, ServiceCall serviceCall) {
332 repositoryDispatcher.addResource(resource, httpMethod, serviceCall);
333 }
334
335
336
337
338 protected void addRootResource(String resource, String httpMethod, ServiceCall serviceCall) {
339 rootDispatcher.addResource(resource, httpMethod, serviceCall);
340 }
341
342 private void dispatch(CallContext context, HttpServletRequest request, HttpServletResponse response,
343 String[] pathFragments) throws Exception {
344 BrowserCallContextImpl browserContext = (BrowserCallContextImpl) context;
345 CmisService service = null;
346 try {
347
348 service = getServiceFactory().getService(context);
349
350
351 if (pathFragments.length < 1) {
352
353 checkCsrfToken(request, response, true, false);
354
355
356 repositoryDispatcher.dispatch("", METHOD_GET, context, service, null, request, response);
357 return;
358 }
359
360
361 CallUrl callUrl = null;
362 if (pathFragments.length == 1) {
363 callUrl = CallUrl.REPOSITORY;
364 } else if (AbstractBrowserServiceCall.ROOT_PATH_FRAGMENT.equals(pathFragments[1])) {
365 callUrl = CallUrl.ROOT;
366 }
367
368 if (callUrl == null) {
369 throw new CmisNotSupportedException("Unknown operation");
370 }
371
372 String method = request.getMethod();
373 String repositoryId = pathFragments[0];
374 boolean callServiceFound = false;
375
376 if (METHOD_GET.equals(method)) {
377 String selector = HttpUtils.getStringParameter(request, Constants.PARAM_SELECTOR);
378 String objectId = HttpUtils.getStringParameter(request, PARAM_OBJECT_ID);
379
380
381 if (callUrl == CallUrl.REPOSITORY) {
382 if (selector == null || selector.length() == 0) {
383 throw new CmisNotSupportedException("No selector");
384 }
385
386
387 checkCsrfToken(request, response, SELECTOR_REPOSITORY_INFO.equalsIgnoreCase(selector), false);
388
389
390 browserContext.setCallDetails(service, objectId, null, null);
391 callServiceFound = repositoryDispatcher.dispatch(selector, method, browserContext, service,
392 repositoryId, request, response);
393 } else if (callUrl == CallUrl.ROOT) {
394 browserContext.setCallDetails(service, objectId, pathFragments, null);
395
396
397 if (selector == null) {
398 try {
399 BaseTypeId basetype = browserContext.getBaseTypeId();
400 switch (basetype) {
401 case CMIS_DOCUMENT:
402 selector = SELECTOR_CONTENT;
403 break;
404 case CMIS_FOLDER:
405 selector = SELECTOR_CHILDREN;
406 break;
407 default:
408 selector = SELECTOR_OBJECT;
409 break;
410 }
411 } catch (Exception e) {
412 selector = SELECTOR_OBJECT;
413 }
414 }
415
416
417 checkCsrfToken(request, response, false, SELECTOR_CONTENT.equalsIgnoreCase(selector));
418
419
420 callServiceFound = rootDispatcher.dispatch(selector, method, browserContext, service, repositoryId,
421 request, response);
422 }
423 } else if (METHOD_POST.equals(method)) {
424 String cmisaction = HttpUtils.getStringParameter(request, Constants.CONTROL_CMISACTION);
425 String objectId = HttpUtils.getStringParameter(request, Constants.CONTROL_OBJECT_ID);
426 String token = HttpUtils.getStringParameter(request, Constants.CONTROL_TOKEN);
427
428 if (cmisaction == null || cmisaction.length() == 0) {
429 throw new CmisNotSupportedException("Unknown action");
430 }
431
432
433 if (callUrl == CallUrl.REPOSITORY) {
434 browserContext.setCallDetails(service, objectId, null, token);
435 callServiceFound = repositoryDispatcher.dispatch(cmisaction, method, browserContext, service,
436 repositoryId, request, response);
437 } else if (callUrl == CallUrl.ROOT) {
438 browserContext.setCallDetails(service, objectId, pathFragments, token);
439 callServiceFound = rootDispatcher.dispatch(cmisaction, method, browserContext, service,
440 repositoryId, request, response);
441 }
442 }
443
444
445
446 if (!callServiceFound) {
447 throw new CmisNotSupportedException("Unknown operation");
448 }
449 } finally {
450 if (service != null) {
451 service.close();
452 }
453 }
454 }
455
456
457
458
459 protected int getErrorCode(CmisBaseException ex) {
460 return ERROR_SERTVICE_CALL.getErrorCode(ex);
461 }
462
463
464
465
466 protected void printError(CallContext context, Exception ex, HttpServletRequest request,
467 HttpServletResponse response) {
468 ERROR_SERTVICE_CALL.printError(context, ex, request, response);
469 }
470
471 static class ErrorServiceCall extends AbstractBrowserServiceCall {
472
473 @Override
474 public void serve(CallContext context, CmisService service, String repositoryId, HttpServletRequest request,
475 HttpServletResponse response) throws Exception {
476
477 }
478
479 public int getErrorCode(CmisBaseException ex) {
480 if (ex instanceof CmisConstraintException) {
481 return 409;
482 } else if (ex instanceof CmisContentAlreadyExistsException) {
483 return 409;
484 } else if (ex instanceof CmisFilterNotValidException) {
485 return 400;
486 } else if (ex instanceof CmisInvalidArgumentException) {
487 return 400;
488 } else if (ex instanceof CmisNameConstraintViolationException) {
489 return 409;
490 } else if (ex instanceof CmisNotSupportedException) {
491 return 405;
492 } else if (ex instanceof CmisObjectNotFoundException) {
493 return 404;
494 } else if (ex instanceof CmisPermissionDeniedException) {
495 return 403;
496 } else if (ex instanceof CmisStorageException) {
497 return 500;
498 } else if (ex instanceof CmisStreamNotSupportedException) {
499 return 403;
500 } else if (ex instanceof CmisUpdateConflictException) {
501 return 409;
502 } else if (ex instanceof CmisVersioningException) {
503 return 409;
504 } else if (ex instanceof CmisTooManyRequestsException) {
505 return 429;
506 } else if (ex instanceof CmisServiceUnavailableException) {
507 return 503;
508 }
509
510 return 500;
511 }
512
513 public void printError(CallContext context, Exception ex, HttpServletRequest request,
514 HttpServletResponse response) {
515 int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
516 String exceptionName = CmisRuntimeException.EXCEPTION_NAME;
517
518 if (ex instanceof CmisRuntimeException) {
519 LOG.error(createLogMessage(ex, request), ex);
520 statusCode = getErrorCode((CmisRuntimeException) ex);
521 } else if (ex instanceof CmisStorageException) {
522 LOG.error(createLogMessage(ex, request), ex);
523 statusCode = getErrorCode((CmisStorageException) ex);
524 exceptionName = ((CmisStorageException) ex).getExceptionName();
525 } else if (ex instanceof CmisBaseException) {
526 statusCode = getErrorCode((CmisBaseException) ex);
527 exceptionName = ((CmisBaseException) ex).getExceptionName();
528
529 if (statusCode == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) {
530 LOG.error(createLogMessage(ex, request), ex);
531 }
532 } else if (ex instanceof IOException) {
533 LOG.warn(createLogMessage(ex, request), ex);
534 } else {
535 LOG.error(createLogMessage(ex, request), ex);
536 }
537
538 if (response.isCommitted()) {
539 LOG.warn("Failed to send error message to client. Response is already committed.", ex);
540 return;
541 }
542
543 String token = (context instanceof BrowserCallContextImpl ? ((BrowserCallContextImpl) context).getToken()
544 : null);
545
546 String message = ex.getMessage();
547 if (!(ex instanceof CmisBaseException)) {
548 message = "An error occurred!";
549 }
550
551 if (token == null) {
552 response.resetBuffer();
553 setStatus(request, response, statusCode);
554
555 JSONObject jsonResponse = new JSONObject();
556
557 jsonResponse.put(ERROR_EXCEPTION, exceptionName);
558 jsonResponse.put(ERROR_MESSAGE, message);
559
560 String st = ExceptionHelper.getStacktraceAsString(ex);
561 if (st != null) {
562 jsonResponse.put(ERROR_STACKTRACE, st);
563 }
564
565 if (ex instanceof CmisBaseException) {
566 Map<String, String> additionalData = ((CmisBaseException) ex).getAdditionalData();
567 if (additionalData != null && !additionalData.isEmpty()) {
568 for (Map.Entry<String, String> e : additionalData.entrySet()) {
569 if (ERROR_EXCEPTION.equalsIgnoreCase(e.getKey())
570 || ERROR_MESSAGE.equalsIgnoreCase(e.getKey())) {
571 continue;
572 }
573 jsonResponse.put(e.getKey(), e.getValue());
574 }
575 }
576 }
577
578 try {
579 writeJSON(jsonResponse, request, response);
580 } catch (Exception e) {
581 LOG.error(createLogMessage(ex, request), e);
582 try {
583 response.sendError(statusCode, message);
584 } catch (Exception en) {
585
586 }
587 }
588 } else {
589 setStatus(request, response, HttpServletResponse.SC_OK);
590 response.setContentType(HTML_MIME_TYPE);
591 response.setContentLength(0);
592
593 if (context != null) {
594 setCookie(request, response, context.getRepositoryId(), token,
595 createCookieValue(statusCode, null, exceptionName, message));
596 }
597 }
598 }
599 }
600 }