View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.server.impl.browser;
20  
21  import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
22  import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
23  import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
24  import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
25  import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException;
26  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
27  import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
28  import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
29  import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
30  import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
31  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
32  import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
33  import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException;
34  import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
35  import org.apache.chemistry.opencmis.commons.exceptions.CmisVersioningException;
36  import org.apache.chemistry.opencmis.commons.impl.Constants;
37  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_ADD_OBJECT_TO_FOLDER;
38  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_APPLY_ACL;
39  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_APPLY_POLICY;
40  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CANCEL_CHECK_OUT;
41  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CHECK_IN;
42  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CHECK_OUT;
43  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_DOCUMENT;
44  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_DOCUMENT_FROM_SOURCE;
45  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_FOLDER;
46  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_POLICY;
47  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_CREATE_RELATIONSHIP;
48  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE;
49  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE_CONTENT;
50  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_DELETE_TREE;
51  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_MOVE;
52  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_QUERY;
53  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_REMOVE_OBJECT_FROM_FOLDER;
54  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_REMOVE_POLICY;
55  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_SET_CONTENT;
56  import static org.apache.chemistry.opencmis.commons.impl.Constants.CMISACTION_UPDATE_PROPERTIES;
57  import static org.apache.chemistry.opencmis.commons.impl.Constants.PARAM_OBJECT_ID;
58  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_ACL;
59  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_ALLOWABLEACTIONS;
60  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CHECKEDOUT;
61  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CHILDREN;
62  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CONTENT;
63  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_CONTENT_CHANGES;
64  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_DESCENDANTS;
65  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_FOLDER_TREE;
66  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_LAST_RESULT;
67  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_OBJECT;
68  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PARENT;
69  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PARENTS;
70  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_POLICIES;
71  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_PROPERTIES;
72  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_QUERY;
73  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_RELATIONSHIPS;
74  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_RENDITIONS;
75  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_REPOSITORY_INFO;
76  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_CHILDREN;
77  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_DEFINITION;
78  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_TYPE_DESCENDANTS;
79  import static org.apache.chemistry.opencmis.commons.impl.Constants.SELECTOR_VERSIONS;
80  import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_EXCEPTION;
81  import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_MESSAGE;
82  import static org.apache.chemistry.opencmis.commons.impl.JSONConstants.ERROR_STACKTRACE;
83  import org.apache.chemistry.opencmis.commons.impl.json.JSONObject;
84  import org.apache.chemistry.opencmis.commons.server.CallContext;
85  import org.apache.chemistry.opencmis.commons.server.CmisService;
86  import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
87  import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
88  import org.apache.chemistry.opencmis.server.impl.ServerVersion;
89  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.CONTEXT_BASETYPE_ID;
90  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.CONTEXT_TRANSACTION;
91  import org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.CallUrl;
92  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.HTML_MIME_TYPE;
93  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.JSON_MIME_TYPE;
94  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.createCookieValue;
95  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.prepareContext;
96  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.setCookie;
97  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.setStatus;
98  import static org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.writeJSON;
99  import org.apache.chemistry.opencmis.server.shared.CallContextHandler;
100 import org.apache.chemistry.opencmis.server.shared.Dispatcher;
101 import static org.apache.chemistry.opencmis.server.shared.Dispatcher.METHOD_GET;
102 import static org.apache.chemistry.opencmis.server.shared.Dispatcher.METHOD_POST;
103 import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
104 import org.apache.chemistry.opencmis.server.shared.HttpUtils;
105 import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
106 
107 import org.apache.commons.logging.Log;
108 import org.apache.commons.logging.LogFactory;
109 
110 import java.io.File;
111 import java.io.IOException;
112 
113 import javax.servlet.ServletConfig;
114 import javax.servlet.ServletException;
115 import javax.servlet.http.HttpServlet;
116 import javax.servlet.http.HttpServletRequest;
117 import javax.servlet.http.HttpServletResponse;
118 
119 
120 public class CmisBrowserBindingServlet extends HttpServlet
121 {
122     private static final long serialVersionUID = 1L;
123     public static final String PARAM_CALL_CONTEXT_HANDLER = "callContextHandler";
124     private static final Log LOG = LogFactory.getLog( CmisBrowserBindingServlet.class.getName(  ) );
125     private File tempDir;
126     private int memoryThreshold;
127     private Dispatcher repositoryDispatcher;
128     private Dispatcher rootDispatcher;
129     private CallContextHandler callContextHandler;
130 
131     @Override
132     public void init( ServletConfig config ) throws ServletException
133     {
134         super.init( config );
135 
136         // initialize the call context handler
137         callContextHandler = null;
138 
139         String callContextHandlerClass = config.getInitParameter( PARAM_CALL_CONTEXT_HANDLER );
140 
141         if ( callContextHandlerClass != null )
142         {
143             try
144             {
145                 callContextHandler = (CallContextHandler) Class.forName( callContextHandlerClass ).newInstance(  );
146             }
147             catch ( Exception e )
148             {
149                 throw new ServletException( "Could not load call context handler: " + e, e );
150             }
151         }
152 
153         // get memory threshold and temp directory
154         CmisServiceFactory factory = (CmisServiceFactory) config.getServletContext(  )
155                                                                 .getAttribute( CmisRepositoryContextListener.SERVICES_FACTORY );
156 
157         tempDir = factory.getTempDirectory(  );
158         memoryThreshold = factory.getMemoryThreshold(  );
159 
160         // initialize the dispatchers
161         repositoryDispatcher = new Dispatcher( false );
162         rootDispatcher = new Dispatcher( false );
163 
164         try
165         {
166             repositoryDispatcher.addResource( SELECTOR_REPOSITORY_INFO, METHOD_GET, RepositoryService.class,
167                 "getRepositoryInfo" );
168             repositoryDispatcher.addResource( SELECTOR_LAST_RESULT, METHOD_GET, RepositoryService.class, "getLastResult" );
169             repositoryDispatcher.addResource( SELECTOR_TYPE_CHILDREN, METHOD_GET, RepositoryService.class,
170                 "getTypeChildren" );
171             repositoryDispatcher.addResource( SELECTOR_TYPE_DESCENDANTS, METHOD_GET, RepositoryService.class,
172                 "getTypeDescendants" );
173             repositoryDispatcher.addResource( SELECTOR_TYPE_DEFINITION, METHOD_GET, RepositoryService.class,
174                 "getTypeDefinition" );
175             repositoryDispatcher.addResource( SELECTOR_QUERY, METHOD_GET, DiscoveryService.class, "query" );
176             repositoryDispatcher.addResource( SELECTOR_CHECKEDOUT, METHOD_GET, NavigationService.class,
177                 "getCheckedOutDocs" );
178             repositoryDispatcher.addResource( SELECTOR_CONTENT_CHANGES, METHOD_GET, DiscoveryService.class,
179                 "getContentChanges" );
180 
181             repositoryDispatcher.addResource( CMISACTION_QUERY, METHOD_POST, DiscoveryService.class, "query" );
182             repositoryDispatcher.addResource( CMISACTION_CREATE_DOCUMENT, METHOD_POST, ObjectService.class,
183                 "createDocument" );
184             repositoryDispatcher.addResource( CMISACTION_CREATE_DOCUMENT_FROM_SOURCE, METHOD_POST, ObjectService.class,
185                 "createDocumentFromSource" );
186             repositoryDispatcher.addResource( CMISACTION_CREATE_POLICY, METHOD_POST, ObjectService.class, "createPolicy" );
187             repositoryDispatcher.addResource( CMISACTION_CREATE_RELATIONSHIP, METHOD_POST, ObjectService.class,
188                 "createRelationship" );
189 
190             rootDispatcher.addResource( SELECTOR_OBJECT, METHOD_GET, ObjectService.class, "getObject" );
191             rootDispatcher.addResource( SELECTOR_PROPERTIES, METHOD_GET, ObjectService.class, "getProperties" );
192             rootDispatcher.addResource( SELECTOR_ALLOWABLEACTIONS, METHOD_GET, ObjectService.class,
193                 "getAllowableActions" );
194             rootDispatcher.addResource( SELECTOR_RENDITIONS, METHOD_GET, ObjectService.class, "getRenditions" );
195             rootDispatcher.addResource( SELECTOR_CONTENT, METHOD_GET, ObjectService.class, "getContentStream" );
196             rootDispatcher.addResource( SELECTOR_CHILDREN, METHOD_GET, NavigationService.class, "getChildren" );
197             rootDispatcher.addResource( SELECTOR_DESCENDANTS, METHOD_GET, NavigationService.class, "getDescendants" );
198             rootDispatcher.addResource( SELECTOR_FOLDER_TREE, METHOD_GET, NavigationService.class, "getFolderTree" );
199             rootDispatcher.addResource( SELECTOR_PARENT, METHOD_GET, NavigationService.class, "getFolderParent" );
200             rootDispatcher.addResource( SELECTOR_PARENTS, METHOD_GET, NavigationService.class, "getObjectParents" );
201             rootDispatcher.addResource( SELECTOR_VERSIONS, METHOD_GET, VersioningService.class, "getAllVersions" );
202             rootDispatcher.addResource( SELECTOR_RELATIONSHIPS, METHOD_GET, RelationshipService.class,
203                 "getObjectRelationships" );
204             rootDispatcher.addResource( SELECTOR_CHECKEDOUT, METHOD_GET, NavigationService.class, "getCheckedOutDocs" );
205             rootDispatcher.addResource( SELECTOR_POLICIES, METHOD_GET, PolicyService.class, "getAppliedPolicies" );
206             rootDispatcher.addResource( SELECTOR_ACL, METHOD_GET, AclService.class, "getACL" );
207 
208             rootDispatcher.addResource( CMISACTION_CREATE_DOCUMENT, METHOD_POST, ObjectService.class, "createDocument" );
209             rootDispatcher.addResource( CMISACTION_CREATE_DOCUMENT_FROM_SOURCE, METHOD_POST, ObjectService.class,
210                 "createDocumentFromSource" );
211             rootDispatcher.addResource( CMISACTION_CREATE_FOLDER, METHOD_POST, ObjectService.class, "createFolder" );
212             rootDispatcher.addResource( CMISACTION_CREATE_POLICY, METHOD_POST, ObjectService.class, "createPolicy" );
213             rootDispatcher.addResource( CMISACTION_UPDATE_PROPERTIES, METHOD_POST, ObjectService.class,
214                 "updateProperties" );
215             rootDispatcher.addResource( CMISACTION_SET_CONTENT, METHOD_POST, ObjectService.class, "setContentStream" );
216             rootDispatcher.addResource( CMISACTION_DELETE_CONTENT, METHOD_POST, ObjectService.class,
217                 "deleteContentStream" );
218             rootDispatcher.addResource( CMISACTION_DELETE, METHOD_POST, ObjectService.class, "deleteObject" );
219             rootDispatcher.addResource( CMISACTION_DELETE_TREE, METHOD_POST, ObjectService.class, "deleteTree" );
220             rootDispatcher.addResource( CMISACTION_MOVE, METHOD_POST, ObjectService.class, "moveObject" );
221             rootDispatcher.addResource( CMISACTION_ADD_OBJECT_TO_FOLDER, METHOD_POST, MultiFilingService.class,
222                 "addObjectToFolder" );
223             rootDispatcher.addResource( CMISACTION_REMOVE_OBJECT_FROM_FOLDER, METHOD_POST, MultiFilingService.class,
224                 "removeObjectFromFolder" );
225             rootDispatcher.addResource( CMISACTION_CHECK_OUT, METHOD_POST, VersioningService.class, "checkOut" );
226             rootDispatcher.addResource( CMISACTION_CANCEL_CHECK_OUT, METHOD_POST, VersioningService.class,
227                 "cancelCheckOut" );
228             rootDispatcher.addResource( CMISACTION_CHECK_IN, METHOD_POST, VersioningService.class, "checkIn" );
229             rootDispatcher.addResource( CMISACTION_APPLY_POLICY, METHOD_POST, PolicyService.class, "applyPolicy" );
230             rootDispatcher.addResource( CMISACTION_REMOVE_POLICY, METHOD_POST, PolicyService.class, "removePolicy" );
231             rootDispatcher.addResource( CMISACTION_APPLY_ACL, METHOD_POST, AclService.class, "applyACL" );
232         }
233         catch ( NoSuchMethodException e )
234         {
235             LOG.error( "Cannot initialize dispatcher!", e );
236         }
237     }
238 
239     @Override
240     protected void service( HttpServletRequest request, HttpServletResponse response )
241         throws ServletException, IOException
242     {
243         // set default headers
244         response.addHeader( "Cache-Control", "private, max-age=0" );
245         response.addHeader( "Server", ServerVersion.OPENCMIS_SERVER );
246 
247         // create a context object, dispatch and handle exceptions
248         CallContext context = null;
249 
250         try
251         {
252             context = HttpUtils.createContext( request, response, getServletContext(  ), CallContext.BINDING_BROWSER,
253                     callContextHandler, tempDir, memoryThreshold );
254             dispatch( context, request, response );
255         }
256         catch ( Exception e )
257         {
258             if ( e instanceof CmisPermissionDeniedException )
259             {
260                 if ( ( context == null ) || ( context.getUsername(  ) == null ) )
261                 {
262                     response.setHeader( "WWW-Authenticate", "Basic realm=\"CMIS\"" );
263                     response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Authorization Required" );
264                 }
265                 else
266                 {
267                     printError( e, request, response, context );
268                 }
269             }
270             else
271             {
272                 printError( e, request, response, context );
273             }
274         }
275 
276         // we are done.
277         response.flushBuffer(  );
278     }
279 
280     // --------------------------------------------------------
281     private void dispatch( CallContext context, HttpServletRequest request, HttpServletResponse response )
282         throws Exception
283     {
284         CmisService service = null;
285 
286         try
287         {
288             // get services factory
289             CmisServiceFactory factory = (CmisServiceFactory) getServletContext(  )
290                                                                   .getAttribute( CmisRepositoryContextListener.SERVICES_FACTORY );
291 
292             if ( factory == null )
293             {
294                 throw new CmisRuntimeException( "Service factory not available! Configuration problem?" );
295             }
296 
297             // get the service
298             service = factory.getService( context );
299 
300             // analyze the path
301             String[] pathFragments = HttpUtils.splitPath( request );
302 
303             if ( pathFragments.length < 4 )
304             {
305                 // root -> repository infos
306                 RepositoryService.getRepositories( context, service, request, response );
307 
308                 return;
309             }
310 
311             // select dispatcher
312             System.out.println( "pathFragments.length=" + pathFragments.length );
313 
314             CallUrl callUrl = null;
315 
316             if ( pathFragments.length == 4 )
317             {
318                 callUrl = CallUrl.REPOSITORY;
319             }
320             else if ( BrowserBindingUtils.ROOT_PATH_FRAGMENT.equals( pathFragments[4] ) )
321             {
322                 callUrl = CallUrl.ROOT;
323             }
324 
325             if ( callUrl == null )
326             {
327                 throw new CmisNotSupportedException( "Unknown operation" );
328             }
329 
330             String method = request.getMethod(  );
331             String repositoryId = pathFragments[3];
332             boolean methodFound = false;
333 
334             if ( METHOD_GET.equals( method ) )
335             {
336                 String selector = getStringParameter( request, Constants.PARAM_SELECTOR );
337                 String objectId = getStringParameter( request, PARAM_OBJECT_ID );
338 
339                 // add object id and object base type id to context
340                 prepareContext( context, callUrl, service, repositoryId, objectId, null, request );
341 
342                 // dispatch
343                 if ( callUrl == CallUrl.REPOSITORY )
344                 {
345                     if ( selector == null )
346                     {
347                         selector = "";
348                     }
349 
350                     methodFound = repositoryDispatcher.dispatch( selector, method, context, service, repositoryId,
351                             request, response );
352                 }
353                 else if ( callUrl == CallUrl.ROOT )
354                 {
355                     // set default method if necessary
356                     if ( selector == null )
357                     {
358                         try
359                         {
360                             BaseTypeId basetype = BaseTypeId.fromValue( (String) context.get( CONTEXT_BASETYPE_ID ) );
361 
362                             switch ( basetype )
363                             {
364                                 case CMIS_DOCUMENT:
365                                     selector = SELECTOR_CONTENT;
366 
367                                     break;
368 
369                                 case CMIS_FOLDER:
370                                     selector = SELECTOR_CHILDREN;
371 
372                                     break;
373 
374                                 default:
375                                     selector = SELECTOR_OBJECT;
376 
377                                     break;
378                             }
379                         }
380                         catch ( Exception e )
381                         {
382                             selector = SELECTOR_OBJECT;
383                         }
384                     }
385 
386                     methodFound = rootDispatcher.dispatch( selector, method, context, service, repositoryId, request,
387                             response );
388                 }
389             }
390             else if ( METHOD_POST.equals( method ) )
391             {
392                 POSTHttpServletRequestWrapper postRequest = new POSTHttpServletRequestWrapper( request, tempDir,
393                         memoryThreshold );
394 
395                 String cmisaction = getStringParameter( postRequest, Constants.CONTROL_CMISACTION );
396                 String objectId = getStringParameter( postRequest, Constants.CONTROL_OBJECT_ID );
397                 String transaction = getStringParameter( postRequest, Constants.CONTROL_TRANSACTION );
398 
399                 if ( ( cmisaction == null ) || ( cmisaction.length(  ) == 0 ) )
400                 {
401                     throw new CmisNotSupportedException( "Unknown action" );
402                 }
403 
404                 // add object id and object base type id to context
405                 prepareContext( context, callUrl, service, repositoryId, objectId, transaction, postRequest );
406 
407                 // dispatch
408                 if ( callUrl == CallUrl.REPOSITORY )
409                 {
410                     methodFound = repositoryDispatcher.dispatch( cmisaction, method, context, service, repositoryId,
411                             postRequest, response );
412                 }
413                 else if ( callUrl == CallUrl.ROOT )
414                 {
415                     methodFound = rootDispatcher.dispatch( cmisaction, method, context, service, repositoryId,
416                             postRequest, response );
417                 }
418             }
419 
420             // if the dispatcher couldn't find a matching method, return an
421             // error message
422             if ( !methodFound )
423             {
424                 throw new CmisNotSupportedException( "Unknown operation" );
425             }
426         }
427         finally
428         {
429             if ( service != null )
430             {
431                 service.close(  );
432             }
433         }
434     }
435 
436     /**
437      * Translates an exception in an appropriate HTTP error code.
438      */
439     private static int getErrorCode( CmisBaseException ex )
440     {
441         if ( ex instanceof CmisConstraintException )
442         {
443             return 409;
444         }
445         else if ( ex instanceof CmisContentAlreadyExistsException )
446         {
447             return 409;
448         }
449         else if ( ex instanceof CmisFilterNotValidException )
450         {
451             return 400;
452         }
453         else if ( ex instanceof CmisInvalidArgumentException )
454         {
455             return 400;
456         }
457         else if ( ex instanceof CmisNameConstraintViolationException )
458         {
459             return 409;
460         }
461         else if ( ex instanceof CmisNotSupportedException )
462         {
463             return 405;
464         }
465         else if ( ex instanceof CmisObjectNotFoundException )
466         {
467             return 404;
468         }
469         else if ( ex instanceof CmisPermissionDeniedException )
470         {
471             return 403;
472         }
473         else if ( ex instanceof CmisStorageException )
474         {
475             return 500;
476         }
477         else if ( ex instanceof CmisStreamNotSupportedException )
478         {
479             return 403;
480         }
481         else if ( ex instanceof CmisUpdateConflictException )
482         {
483             return 409;
484         }
485         else if ( ex instanceof CmisVersioningException )
486         {
487             return 409;
488         }
489 
490         return 500;
491     }
492 
493     /**
494      * Prints the error as JSON.
495      */
496     private static void printError( Exception ex, HttpServletRequest request, HttpServletResponse response,
497         CallContext context )
498     {
499         int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
500         String exceptionName = "runtime";
501 
502         if ( ex instanceof CmisRuntimeException )
503         {
504             LOG.error( ex.getMessage(  ), ex );
505         }
506         else if ( ex instanceof CmisBaseException )
507         {
508             statusCode = getErrorCode( (CmisBaseException) ex );
509             exceptionName = ( (CmisBaseException) ex ).getExceptionName(  );
510         }
511         else
512         {
513             LOG.error( ex.getMessage(  ), ex );
514         }
515 
516         String transaction = ( ( context == null ) ? null : (String) context.get( CONTEXT_TRANSACTION ) );
517 
518         if ( transaction == null )
519         {
520             setStatus( request, response, statusCode );
521             response.setContentType( JSON_MIME_TYPE );
522 
523             JSONObject jsonResponse = new JSONObject(  );
524             jsonResponse.put( ERROR_EXCEPTION, exceptionName );
525             jsonResponse.put( ERROR_MESSAGE, ex.getMessage(  ) );
526 
527             String st = ExceptionHelper.getStacktraceAsString( ex );
528 
529             if ( st != null )
530             {
531                 jsonResponse.put( ERROR_STACKTRACE, st );
532             }
533 
534             try
535             {
536                 writeJSON( jsonResponse, request, response );
537             }
538             catch ( Exception e )
539             {
540                 LOG.error( e.getMessage(  ), e );
541             }
542         }
543         else
544         {
545             setStatus( request, response, HttpServletResponse.SC_OK );
546             response.setContentType( HTML_MIME_TYPE );
547             response.setContentLength( 0 );
548 
549             if ( context != null )
550             {
551                 setCookie( request, response, context.getRepositoryId(  ), transaction,
552                     createCookieValue( statusCode, null, exceptionName, ex.getMessage(  ) ) );
553             }
554         }
555     }
556 }