View Javadoc
1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.chain.commands.servlet;
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.struts.action.Action;
27  import org.apache.struts.action.ActionServlet;
28  import org.apache.struts.chain.Constants;
29  import org.apache.struts.chain.commands.util.ClassUtils;
30  import org.apache.struts.chain.contexts.ActionContext;
31  import org.apache.struts.chain.contexts.ServletActionContext;
32  import org.apache.struts.config.ActionConfig;
33  import org.apache.struts.config.ModuleConfig;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * <p>Concrete implementation of <code>AbstractCreateAction</code> for use in
39   * a Servlet API chain.  Expects that the ActionContext passed into it can
40   * safely be cast to <code>ServletActionContext</code>.</p>
41   */
42  public class CreateAction
43      extends org.apache.struts.chain.commands.AbstractCreateAction {
44      // ------------------------------------------------------ Instance Variables
45  
46      /**
47       * The {@code Log} instance for this class.
48       */
49      private final Logger log =
50          LoggerFactory.getLogger(CreateAction.class);
51  
52      /* :TODO The Action class' dependency on having its "servlet" property set
53       * requires this API-dependent subclass of AbstractCreateAction.
54       */
55      protected synchronized Action getAction(ActionContext context, String type,
56          ActionConfig actionConfig)
57          throws Exception {
58  
59          ServletActionContext saContext = (ServletActionContext) context;
60          ActionServlet actionServlet = saContext.getActionServlet();
61  
62          ModuleConfig moduleConfig = actionConfig.getModuleConfig();
63          String actionsKey = Constants.ACTIONS_KEY + moduleConfig.getPrefix();
64          @SuppressWarnings("unchecked")
65          Map<String, Action> actions = (Map<String, Action>) context.getApplicationScope().get(actionsKey);
66  
67          if (actions == null) {
68              actions = new HashMap<>();
69              context.getApplicationScope().put(actionsKey, actions);
70          }
71  
72          Action action = null;
73  
74          try {
75              if (actionConfig.isSingleton()) {
76                  synchronized (actions) {
77                      action = actions.get(type);
78                      if (action == null) {
79                          action = createAction(context, type);
80                          actions.put(type, action);
81                      }
82                  }
83              } else {
84                  action = createAction(context, type);
85              }
86          } catch (Exception e) {
87              log.atError()
88                  .setMessage(() -> actionServlet.getInternal().getMessage(
89                      "actionCreate", actionConfig.getPath(),
90                      actionConfig.toString()))
91                  .setCause(e).log();
92              throw e;
93          }
94  
95          if (action.getServlet() == null) {
96              action.setServlet(actionServlet);
97          }
98  
99          return (action);
100     }
101 
102     /**
103      * <p>Invoked by <code>getAction</code> when the <code>Action</code>
104      * actually has to be created. If the instance is already created and
105      * cached, this method will not be called. </p>
106      *
107      * @param context      The <code>Context</code> for this request
108      * @param type         Name of class to instantiate
109      * @return Instantiated Action class
110      * @throws Exception if there are any problems instantiating the Action
111      *                   class.
112      * @since Struts 1.3.7
113      */
114     protected Action createAction(ActionContext context, String type) throws Exception {
115         log.info("Initialize action of type: {}", type);
116         return (Action) ClassUtils.getApplicationInstance(type);
117     }
118 }