View Javadoc

1   package org.apache.turbine.modules;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * 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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.util.List;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  import org.apache.ecs.ConcreteElement;
25  
26  import org.apache.turbine.Turbine;
27  import org.apache.turbine.TurbineConstants;
28  import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
29  import org.apache.turbine.services.assemblerbroker.TurbineAssemblerBroker;
30  import org.apache.turbine.util.ObjectUtils;
31  import org.apache.turbine.util.RunData;
32  
33  /***
34   * The purpose of this class is to allow one to load and execute
35   * Screen modules.
36   *
37   * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
38   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
39   * @version $Id: ScreenLoader.java 264148 2005-08-29 14:21:04Z henning $
40   */
41  public class ScreenLoader
42      extends GenericLoader
43      implements Loader
44  {
45      /*** Serial Version UID */
46      private static final long serialVersionUID = -4825216334500657398L;
47  
48      /*** Logging */
49      private static Log log = LogFactory.getLog(ScreenLoader.class);
50  
51      /*** The single instance of this class. */
52      private static ScreenLoader instance =
53          new ScreenLoader(Turbine.getConfiguration()
54                           .getInt(TurbineConstants.SCREEN_CACHE_SIZE_KEY,
55                                   TurbineConstants.SCREEN_CACHE_SIZE_DEFAULT));
56  
57      /*** The Assembler Broker Service */
58      private static AssemblerBrokerService ab = TurbineAssemblerBroker.getService();
59  
60      /***
61       * These ctor's are private to force clients to use getInstance()
62       * to access this class.
63       */
64      private ScreenLoader()
65      {
66          super();
67      }
68  
69      /***
70       * These ctor's are private to force clients to use getInstance()
71       * to access this class.
72       */
73      private ScreenLoader(int i)
74      {
75          super(i);
76      }
77  
78      /***
79       * Adds an instance of an object into the hashtable.
80       *
81       * @param name Name of object.
82       * @param screen Screen to be associated with name.
83       */
84      private void addInstance(String name, Screen screen)
85      {
86          if (cache())
87          {
88              this.put(name, (Screen) screen);
89          }
90      }
91  
92      /***
93       * Attempts to load and execute the external Screen. This is used
94       * when you want to execute a Screen which returns its output via
95       * a MultiPartElement instead of out the data.getPage() value.
96       * This allows you to easily chain the execution of Screen modules
97       * together.
98       *
99       * @param data Turbine information.
100      * @param name Name of object that will execute the screen.
101      * @exception Exception a generic exception.
102      */
103     public ConcreteElement eval(RunData data, String name)
104             throws Exception
105     {
106         // Execute screen
107         return getInstance(name).build(data);
108     }
109 
110     /***
111      * Attempts to load and execute the Screen. This is used when you
112      * want to execute a Screen which returns its output via the
113      * data.getPage() object.
114      *
115      * @param data Turbine information.
116      * @param name Name of object that will execute the screen.
117      * @exception Exception a generic exception.
118      */
119     public void exec(RunData data, String name)
120             throws Exception
121     {
122         this.eval(data, name);
123     }
124 
125     /***
126      * Pulls out an instance of the object by name.  Name is just the
127      * single name of the object. This is equal to getInstance but
128      * returns an Assembler object and is needed to fulfil the Loader
129      * interface.
130      *
131      * @param name Name of object instance.
132      * @return A Screen with the specified name, or null.
133      * @exception Exception a generic exception.
134      */
135     public Assembler getAssembler(String name)
136         throws Exception
137     {
138         return getInstance(name);
139     }
140 
141     /***
142      * Pulls out an instance of the Screen by name.  Name is just the
143      * single name of the Screen.
144      *
145      * @param name Name of requested Screen.
146      * @return A Screen with the specified name, or null.
147      * @exception Exception a generic exception.
148      */
149     public Screen getInstance(String name)
150             throws Exception
151     {
152         Screen screen = null;
153 
154         // Check if the screen is already in the cache
155         if (cache() && this.containsKey(name))
156         {
157             screen = (Screen) this.get(name);
158             log.debug("Found Screen " + name + " in the cache!");
159         }
160         else
161         {
162             log.debug("Loading Screen " + name + " from the Assembler Broker");
163 
164             try
165             {
166                 if (ab != null)
167                 {
168                     // Attempt to load the screen
169                     screen = (Screen) ab.getAssembler(
170                         AssemblerBrokerService.SCREEN_TYPE, name);
171                 }
172             }
173             catch (ClassCastException cce)
174             {
175                 // This can alternatively let this exception be thrown
176                 // So that the ClassCastException is shown in the
177                 // browser window.  Like this it shows "Screen not Found"
178                 screen = null;
179             }
180 
181             if (screen == null)
182             {
183                 // If we did not find a screen we should try and give
184                 // the user a reason for that...
185                 // FIX ME: The AssemblerFactories should each add it's
186                 // own string here...
187                 List packages = Turbine.getConfiguration()
188                     .getList(TurbineConstants.MODULE_PACKAGES);
189 
190                 ObjectUtils.addOnce(packages,
191                         GenericLoader.getBasePackage());
192 
193                 throw new ClassNotFoundException(
194                         "\n\n\tRequested Screen not found: " + name +
195                         "\n\tTurbine looked in the following " +
196                         "modules.packages path: \n\t" + packages.toString() + "\n");
197             }
198             else if (cache())
199             {
200                 // The new instance is added to the cache
201                 addInstance(name, screen);
202             }
203         }
204         return screen;
205     }
206 
207     /***
208      * The method through which this class is accessed.
209      *
210      * @return The single instance of this class.
211      */
212     public static ScreenLoader getInstance()
213     {
214         return instance;
215     }
216 }