View Javadoc

1   /**
2    * - Digitalis Internal Framework v2.0 - (C) 2007, Digitalis Informatica. Distribuicao e Gestao de Informatica, Lda.
3    * Estrada de Paco de Arcos num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999
4    * http://www.digitalis.pt
5    */
6   package pt.digitalis.dif.controller;
7   
8   import pt.digitalis.dif.controller.interfaces.IChAL;
9   import pt.digitalis.dif.controller.interfaces.IDIFDispatcher;
10  import pt.digitalis.dif.controller.interfaces.IDIFRequest;
11  import pt.digitalis.dif.controller.interfaces.IDIFResponse;
12  import pt.digitalis.dif.controller.interfaces.IDispatcherErrorHandler;
13  import pt.digitalis.dif.controller.objects.ClientDescriptor;
14  import pt.digitalis.dif.controller.objects.RESTAction;
15  import pt.digitalis.dif.dem.annotations.controller.Channel;
16  import pt.digitalis.dif.dem.managers.IMessageManager;
17  import pt.digitalis.dif.exception.controller.BusinessFlowException;
18  import pt.digitalis.dif.exception.controller.ControllerException;
19  import pt.digitalis.dif.ioc.DIFIoCRegistry;
20  
21  import com.newrelic.api.agent.Trace;
22  
23  /**
24   * Base implementation for all ChALs The API exposed to the Listener entities is the <code>serve()</code> method. All
25   * the communication between AbstractChAL and Listener is done through this API.
26   * 
27   * @param <RequestType>
28   *            type original request type
29   * @param <ResponseType>
30   *            the original response type
31   * @author Rodrigo Gonçalves <a href="mailto:rgoncalves@digitalis.pt">rgoncalves@digitalis.pt</a>
32   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a>
33   * @created 2007/03/27
34   */
35  abstract public class AbstractChAL<RequestType, ResponseType> implements IChAL<RequestType, ResponseType> {
36  
37      /** The channel ID */
38      private String channelID = null;
39  
40      /** The message manager. */
41      protected IMessageManager messageManager = DIFIoCRegistry.getRegistry().getImplementation(IMessageManager.class);
42  
43      /**
44       * Get the id of the channel associated to the ChAL. If the id is unset the method reads the channel id from the
45       * annotation.
46       * 
47       * @return the channel ID read from the {@link Channel} annotation
48       */
49      public String getChannelID()
50      {
51          if (channelID == null)
52              channelID = this.getClass().getAnnotation(Channel.class).value();
53  
54          return channelID;
55      }
56  
57      /**
58       * Creates a client descriptor object identifying the client agent who issued the request
59       * 
60       * @param originalRequest
61       *            the original request object
62       * @return the client descriptor for the current request
63       * @throws ControllerException
64       *             when any runtime exception is thrown
65       */
66      abstract protected ClientDescriptor getClientDescriptor(RequestType originalRequest) throws ControllerException;
67  
68      /**
69       * Inspector of the dispatcher assigned to this channel.
70       * 
71       * @return theDispatcher attribute
72       */
73      protected IDIFDispatcher getDispatcher()
74      {
75          return DIFIoCRegistry.getRegistry().getImplementation(IDIFDispatcher.class, getChannelID());
76      }
77  
78      /**
79       * Inspector of the dispatcher assigned to this channel.
80       * 
81       * @return theDispatcher attribute
82       */
83      protected IDispatcherErrorHandler getErrorHandler()
84      {
85          return DIFIoCRegistry.getRegistry().getImplementation(IDispatcherErrorHandler.class, getChannelID());
86      }
87  
88      /**
89       * @see pt.digitalis.dif.controller.interfaces.IChAL#serve(java.lang.Object, java.lang.Object,
90       *      pt.digitalis.dif.controller.objects.RESTAction)
91       * @param originalRequest
92       *            the original request object
93       * @param finalResponse
94       *            the final response object
95       * @param restAction
96       *            the REST action, if specified
97       * @return the processed DIFResponse
98       */
99      @Trace(metricName = "DIF:ChAL:Serve", dispatcher = true)
100     public IDIFResponse serve(RequestType originalRequest, ResponseType finalResponse, RESTAction restAction)
101     {
102 
103         IDIFResponse difResponse = null;
104         IDIFRequest difRequest = null;
105 
106         try
107         {
108             difRequest = translateRequest(originalRequest);
109             difRequest.setRestAction(restAction);
110 
111             // Initializes the client descriptor if ins't filled. The translateRequest is responsible for filling it.
112             if (difRequest.getClient() == null)
113                 difRequest.setClient(getClientDescriptor(originalRequest));
114 
115             if (validateRequest(originalRequest))
116             {
117 
118                 difResponse = getDispatcher().dispatch(difRequest);
119 
120                 // Fail-over. Should never return null.
121                 if (difResponse == null)
122                     difResponse = getErrorHandler().getDefaultErrorResponse(difRequest, null);
123 
124             }
125             else
126                 difResponse = getErrorHandler().getDefaultErrorResponse(difRequest, null);
127 
128         }
129         catch (BusinessFlowException exception)
130         {
131             difResponse = getErrorHandler().processException(difRequest, exception);
132         }
133         catch (RuntimeException exception)
134         {
135             difResponse = getErrorHandler().processException(difRequest, exception);
136         }
137         catch (ControllerException exception)
138         {
139             difResponse = getErrorHandler().processException(difRequest, exception);
140         }
141 
142         this.publish(difResponse, originalRequest, finalResponse);
143 
144         return difResponse;
145     }
146 
147     /**
148      * Validates the original request. It can be used to check if a particular request is valid for the channel. It may
149      * also perform other validations, as the request parameters integrity.
150      * 
151      * @param originalRequest
152      *            The original request received from the client.
153      * @return T case the request is well formed, F otherwise
154      * @throws ControllerException
155      *             when any runtime exception is thrown
156      */
157     abstract protected boolean validateRequest(RequestType originalRequest) throws ControllerException;
158 }