View Javadoc

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