View Javadoc
1   /*
2    * Copyright 2011 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.fatwire.gst.foundation.controller.annotation;
18  
19  import static COM.FutureTense.Interfaces.Utilities.goodString;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  
24  import COM.FutureTense.Interfaces.ICS;
25  import COM.FutureTense.Util.ftErrors;
26  import COM.FutureTense.Util.ftMessage;
27  
28  import com.fatwire.gst.foundation.CSRuntimeException;
29  import com.fatwire.gst.foundation.controller.AbstractController;
30  import com.fatwire.gst.foundation.facade.RenderUtils;
31  import com.fatwire.gst.foundation.facade.runtag.render.LogDep;
32  
33  /**
34   * The Controller delegates the business logic to an annotated method. In this
35   * method the special logic for the request is executed. Method selection is
36   * done via the {@literal @}IcsVariable annotation. This works of the premise that a special
37   * name/value pair on the ics scope set before this controller is executed, is
38   * enough to determine the selection for the business logic method.
39   * 
40   * @author Dolf Dijkstra
41   * @since Apr 15, 2011
42   * @see IcsVariable
43   */
44  public abstract class AnnotationController extends AbstractController {
45  
46      public AnnotationController(ICS ics) {
47          super(ics);
48      }
49  
50      /*
51       * (non-Javadoc)
52       * 
53       * @see com.fatwire.gst.foundation.controller.AbstractController#doExecute()
54       */
55      @Override
56      protected void doExecute() {
57  
58          // record seid and eid and any other deps required
59          RenderUtils.recordBaseCompositionalDependencies(ics);
60          final ControllerMappingResolver resolver = new ControllerMappingResolver();
61          final Object target = getTarget();
62          final Method m = resolver.findControllerMethod(ics, target);
63          if (m == null) {
64              executeDefault();
65          } else {
66              invokeControllerMethod(m, target);
67          }
68      }
69  
70      /**
71       * @param m
72       * @param target
73       */
74      protected void invokeControllerMethod(final Method m, final Object target) {
75          try {
76              m.invoke(target, new Object[] { ics });
77          } catch (final IllegalArgumentException e) {
78              handleException(e);
79          } catch (final IllegalAccessException e) {
80              handleException(e);
81          } catch (final InvocationTargetException e) {
82              handleException(e);
83          }
84  
85      }
86  
87      /**
88       * @return this
89       */
90      protected Object getTarget() {
91          return this;
92      }
93  
94      /**
95       * Default operation to execute if no matching annotated method can be
96       * found.
97       */
98      abstract void executeDefault();
99  
100     @Override
101     protected void handleException(final Exception e) {
102         if (e instanceof CSRuntimeException) {
103             handleCSRuntimeException((CSRuntimeException) e);
104         } else {
105             sendError(500, e);
106         }
107     }
108 
109     /**
110      * This method transforms errno values into http status codes and sets them
111      * using the X-Fatwire-Status header.
112      * <p/>
113      * Only some errnos are handled by this base class.
114      * <p/>
115      * More info coming soon
116      * 
117      * @param e exception
118      */
119     protected void handleCSRuntimeException(final CSRuntimeException e) {
120         switch (e.getErrno()) {
121             case 400:
122             case ftErrors.badparams:
123                 sendError(400, e);
124                 break;
125             case 404:
126             case ftErrors.pagenotfound:
127                 sendError(404, e);
128                 break;
129             case 403:
130             case ftErrors.noprivs:
131                 sendError(403, e);
132                 break;
133             default:
134                 sendError(500, e);
135                 break;
136         }
137     }
138 
139     /**
140      * Record compositional dependencies that are required for the controller
141      */
142     protected void recordCompositionalDependencies() {
143         if (ics.isCacheable(ics.GetVar(ftMessage.PageName))) {
144             if (goodString(ics.GetVar("seid"))) {
145                 LogDep.logDep(ics, "SiteEntry", ics.GetVar("seid"));
146             }
147             if (goodString(ics.GetVar("eid"))) {
148                 LogDep.logDep(ics, "CSElement", ics.GetVar("eid"));
149             }
150         }
151     }
152 
153 }