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.Util.ftErrors;
25  import COM.FutureTense.Util.ftMessage;
26  
27  import com.fatwire.gst.foundation.CSRuntimeException;
28  import com.fatwire.gst.foundation.controller.AbstractController;
29  import com.fatwire.gst.foundation.facade.RenderUtils;
30  import com.fatwire.gst.foundation.facade.runtag.render.LogDep;
31  
32  /**
33   * The Controller delegates the business logic to an annotated method. In this
34   * method the special logic for the request is executed. Method selection is
35   * done via the {@literal @}IcsVariable annotation. This works of the premise that a special
36   * name/value pair on the ics scope set before this controller is executed, is
37   * enough to determine the selection for the business logic method.
38   * 
39   * @author Dolf Dijkstra
40   * @since Apr 15, 2011
41   * @see IcsVariable
42   */
43  public abstract class AnnotationController extends AbstractController {
44  
45      /*
46       * (non-Javadoc)
47       * 
48       * @see com.fatwire.gst.foundation.controller.AbstractController#doExecute()
49       */
50      @Override
51      protected void doExecute() {
52  
53          // record seid and eid and any other deps required
54          RenderUtils.recordBaseCompositionalDependencies(ics);
55          final ControllerMappingResolver resolver = new ControllerMappingResolver();
56          final Object target = getTarget();
57          final Method m = resolver.findControllerMethod(ics, target);
58          if (m == null) {
59              executeDefault();
60          } else {
61              invokeControllerMethod(m, target);
62          }
63      }
64  
65      /**
66       * @param m
67       * @param target
68       */
69      protected void invokeControllerMethod(final Method m, final Object target) {
70          try {
71              m.invoke(target, new Object[] { ics });
72          } catch (final IllegalArgumentException e) {
73              handleException(e);
74          } catch (final IllegalAccessException e) {
75              handleException(e);
76          } catch (final InvocationTargetException e) {
77              handleException(e);
78          }
79  
80      }
81  
82      /**
83       * @return this
84       */
85      protected Object getTarget() {
86          return this;
87      }
88  
89      /**
90       * Default operation to execute if no matching annotated method can be
91       * found.
92       */
93      abstract void executeDefault();
94  
95      @Override
96      protected void handleException(final Exception e) {
97          if (e instanceof CSRuntimeException) {
98              handleCSRuntimeException((CSRuntimeException) e);
99          } else {
100             sendError(500, e);
101         }
102     }
103 
104     /**
105      * This method transforms errno values into http status codes and sets them
106      * using the X-Fatwire-Status header.
107      * <p/>
108      * Only some errnos are handled by this base class.
109      * <p/>
110      * More info coming soon
111      * 
112      * @param e exception
113      */
114     protected void handleCSRuntimeException(final CSRuntimeException e) {
115         switch (e.getErrno()) {
116             case 400:
117             case ftErrors.badparams:
118                 sendError(400, e);
119                 break;
120             case 404:
121             case ftErrors.pagenotfound:
122                 sendError(404, e);
123                 break;
124             case 403:
125             case ftErrors.noprivs:
126                 sendError(403, e);
127                 break;
128             default:
129                 sendError(500, e);
130                 break;
131         }
132     }
133 
134     /**
135      * Record compositional dependencies that are required for the controller
136      */
137     protected void recordCompositionalDependencies() {
138         if (ics.isCacheable(ics.GetVar(ftMessage.PageName))) {
139             if (goodString(ics.GetVar("seid"))) {
140                 LogDep.logDep(ics, "SiteEntry", ics.GetVar("seid"));
141             }
142             if (goodString(ics.GetVar("eid"))) {
143                 LogDep.logDep(ics, "CSElement", ics.GetVar("eid"));
144             }
145         }
146     }
147 
148 }