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.shared;
20  
21  import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
22  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
23  import org.apache.chemistry.opencmis.commons.server.CallContext;
24  import org.apache.chemistry.opencmis.commons.server.CmisService;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import java.io.Serializable;
30  
31  import java.lang.reflect.InvocationTargetException;
32  import java.lang.reflect.Method;
33  
34  import java.util.HashMap;
35  import java.util.Map;
36  
37  import javax.servlet.http.HttpServletRequest;
38  import javax.servlet.http.HttpServletResponse;
39  
40  
41  /**
42   * Dispatcher for the AtomPub and Browser binding servlet.
43   */
44  public class Dispatcher implements Serializable
45  {
46      private static final long serialVersionUID = 1L;
47      public static final String METHOD_GET = "GET";
48      public static final String METHOD_POST = "POST";
49      public static final String METHOD_PUT = "PUT";
50      public static final String METHOD_DELETE = "DELETE";
51      private static final Log LOG = LogFactory.getLog( Dispatcher.class.getName(  ) );
52      private final boolean caseSensitive;
53      private Map<String, Method> methodMap = new HashMap<String, Method>(  );
54  
55      public Dispatcher(  )
56      {
57          this( true );
58      }
59  
60      public Dispatcher( boolean caseSensitive )
61      {
62          this.caseSensitive = caseSensitive;
63      }
64  
65      /**
66       * Connects a resource and HTTP method with a class and a class method.
67       */
68      public synchronized void addResource( String resource, String httpMethod, Class<?> clazz, String classmethod )
69          throws NoSuchMethodException
70      {
71          Method m = clazz.getMethod( classmethod, CallContext.class, CmisService.class, String.class,
72                  HttpServletRequest.class, HttpServletResponse.class );
73  
74          methodMap.put( getKey( resource, httpMethod ), m );
75      }
76  
77      /**
78       * Find the appropriate method an call it.
79       *
80       * @return
81       * <code>true</code> if the method was found,
82       * <code>false</code> otherwise.
83       */
84      public boolean dispatch( String resource, String httpMethod, CallContext context, CmisService service,
85          String repositoryId, HttpServletRequest request, HttpServletResponse response )
86      {
87          Method m = methodMap.get( getKey( resource, httpMethod ) );
88  
89          if ( m == null )
90          {
91              return false;
92          }
93  
94          if ( LOG.isDebugEnabled(  ) )
95          {
96              LOG.debug( repositoryId + " / " + resource + ", " + httpMethod + " -> " + m.getName(  ) );
97          }
98  
99          try
100         {
101             m.invoke( null, context, service, repositoryId, request, response );
102         }
103         catch ( IllegalAccessException e )
104         {
105             throw new CmisRuntimeException( "Internal error!", e );
106         }
107         catch ( InvocationTargetException e )
108         {
109             if ( e.getCause(  ) instanceof CmisBaseException )
110             {
111                 throw (CmisBaseException) e.getCause(  );
112             }
113             else
114             {
115                 throw new CmisRuntimeException( e.getMessage(  ), e );
116             }
117         }
118 
119         return true;
120     }
121 
122     /**
123      * Generates a map key from a resource and an HTTP method.
124      */
125     private String getKey( String resource, String httpMethod )
126     {
127         String s = resource + "/" + httpMethod;
128 
129         return ( caseSensitive ? s : s.toUpperCase(  ) );
130     }
131 }