##### Coverage Report - org.apache.turbine.services.assemblerbroker.TurbineAssemblerBrokerService

Classes in this File | Line Coverage | Branch Coverage | Complexity
TurbineAssemblerBrokerService |
81% | 60/74
75% | 27/36
| 5.666666666666667;5,667

1 |  |
     package org.apache.turbine.services.assemblerbroker;
2 |  |
3 |  |
4 |  |
     /*
5 |  |
      * Licensed to the Apache Software Foundation (ASF) under one
6 |  |
      * or more contributor license agreements.  See the NOTICE file
7 |  |
      * distributed with this work for additional information
8 |  |
      * regarding copyright ownership.  The ASF licenses this file
9 |  |
      * to you under the Apache License, Version 2.0 (the
10 |  |
      * "License"); you may not use this file except in compliance
11 |  |
      * with the License.  You may obtain a copy of the License at
12 |  |
      *
13 |  |
      *   http://www.apache.org/licenses/LICENSE-2.0
14 |  |
      *
15 |  |
      * Unless required by applicable law or agreed to in writing,
16 |  |
      * software distributed under the License is distributed on an
17 |  |
      * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 |  |
      * KIND, either express or implied.  See the License for the
19 |  |
      * specific language governing permissions and limitations
20 |  |
      * under the License.
21 |  |
      */
22 |  |
23 |  |
24 |  |
     import java.util.HashMap;
25 |  |
     import java.util.Iterator;
26 |  |
     import java.util.List;
27 |  |
     import java.util.Map;
28 |  |
     import java.util.Vector;
29 |  |
30 |  |
     import org.apache.commons.collections.map.LRUMap;
31 |  |
     import org.apache.commons.configuration.Configuration;
32 |  |
     import org.apache.commons.logging.Log;
33 |  |
     import org.apache.commons.logging.LogFactory;
34 |  |
     import org.apache.turbine.Turbine;
35 |  |
     import org.apache.turbine.TurbineConstants;
36 |  |
     import org.apache.turbine.modules.Assembler;
37 |  |
     import org.apache.turbine.modules.Loader;
38 |  |
     import org.apache.turbine.services.InitializationException;
39 |  |
     import org.apache.turbine.services.TurbineBaseService;
40 |  |
     import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
41 |  |
     import org.apache.turbine.util.TurbineException;
42 |  |
43 |  |
     /**
44 |  |
      * TurbineAssemblerBrokerService allows assemblers (like screens,
45 |  |
      * actions and layouts) to be loaded from one or more AssemblerFactory
46 |  |
      * classes.  AssemblerFactory classes are registered with this broker
47 |  |
      * by adding them to the TurbineResources.properties file.
48 |  |
      *
49 |  |
      * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
50 |  |
      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
51 |  |
      * @version $Id: TurbineAssemblerBrokerService.java 1078552 2011-03-06 19:58:46Z tv $
52 |  |
      */
53 | 58 |
     public class TurbineAssemblerBrokerService
54 |  |
             extends TurbineBaseService
55 |  |
             implements AssemblerBrokerService
56 |  |
     {
57 |  |
         /** Logging */
58 | 58 |
         private static Log log
59 |  |
                 = LogFactory.getLog(TurbineAssemblerBrokerService.class);
60 |  |
61 |  |
         /** A structure that holds the registered AssemblerFactories */
62 | 58 |
         private Map<String, List<AssemblerFactory>> factories = null;
63 |  |
64 |  |
         /** A cache that holds the generated Assemblers */
65 | 58 |
         private Map<String, Assembler> assemblerCache = null;
66 |  |
67 |  |
         /** A cache that holds the Loaders */
68 | 58 |
         private Map<String, Loader> loaderCache = null;
69 |  |
70 |  |
         /** Caching on/off */
71 |  |
         private boolean isCaching;
72 |  |
73 |  |
         /**
74 |  |
          * Get a list of AssemblerFactories of a certain type
75 |  |
          *
76 |  |
          * @param type type of Assembler
77 |  |
          * @return list of AssemblerFactories
78 |  |
          */
79 |  |
         private List<AssemblerFactory> getFactoryGroup(String type)
80 |  |
         {
81 | 1672 |
             if (!factories.containsKey(type))
82 |  |
             {
83 | 564 |
                 factories.put(type, new Vector<AssemblerFactory>());
84 |  |
             }
85 | 1672 |
             return factories.get(type);
86 |  |
         }
87 |  |
88 |  |
         /**
89 |  |
          * Utiltiy method to register all factories for a given type.
90 |  |
          *
91 |  |
          * @param type type of Assembler
92 |  |
          * @throws TurbineException
93 |  |
          */
94 |  |
         private void registerFactories(String type)
95 |  |
             throws TurbineException
96 |  |
         {
97 | 564 |
             List names = getConfiguration().getList(type);
98 |  |
99 | 564 |
             log.info("Registering " + names.size() + " " + type + " factories.");
100 |  |
101 | 564 |
             for (Iterator it = names.iterator(); it.hasNext(); )
102 |  |
             {
103 | 564 |
                 String factory = (String) it.next();
104 |  |
                 try
105 |  |
                 {
106 | 564 |
                     Object o = Class.forName(factory).newInstance();
107 | 564 |
                     registerFactory(type, (AssemblerFactory) o);
108 |  |
                 }
109 |  |
                 // these must be passed to the VM
110 | 0 |
                 catch (ThreadDeath e)
111 |  |
                 {
112 | 0 |
                     throw e;
113 |  |
                 }
114 | 0 |
                 catch (OutOfMemoryError e)
115 |  |
                 {
116 | 0 |
                     throw e;
117 |  |
                 }
118 |  |
                 // when using Class.forName(), NoClassDefFoundErrors are likely
119 |  |
                 // to happen (missing jar files)
120 | 0 |
                 catch (Throwable t)
121 |  |
                 {
122 | 0 |
                     throw new TurbineException("Failed registering " + type
123 |  |
                             + " factory: " + factory, t);
124 | 564 |
                 }
125 | 564 |
             }
126 | 564 |
         }
127 |  |
128 |  |
         /**
129 |  |
          * Initializes the AssemblerBroker and loads the AssemblerFactory
130 |  |
          * classes registered in TurbineResources.Properties.
131 |  |
          *
132 |  |
          * @throws InitializationException
133 |  |
          */
134 |  |
         @SuppressWarnings("unchecked") // as long as commons-collections does not use generics
135 |  |
         @Override
136 |  |
         public void init()
137 |  |
             throws InitializationException
138 |  |
         {
139 | 94 |
             factories = new HashMap<String, List<AssemblerFactory>>();
140 |  |
141 |  |
             try
142 |  |
             {
143 | 94 |
                 Configuration conf = getConfiguration();
144 |  |
145 | 94 |
                 for (Iterator i = conf.getKeys(); i.hasNext();)
146 |  |
                 {
147 | 658 |
                     String type = (String)i.next();
148 |  |
149 | 658 |
                     if (!"classname".equalsIgnoreCase(type))
150 |  |
                     {
151 | 564 |
                         registerFactories(type);
152 |  |
                     }
153 | 658 |
                 }
154 |  |
             }
155 | 0 |
             catch (TurbineException e)
156 |  |
             {
157 | 0 |
                 throw new InitializationException(
158 |  |
                         "AssemblerBrokerService failed to initialize", e);
159 | 94 |
             }
160 |  |
161 | 94 |
             isCaching = Turbine.getConfiguration()
162 |  |
                 .getBoolean(TurbineConstants.MODULE_CACHE_KEY,
163 |  |
                             TurbineConstants.MODULE_CACHE_DEFAULT);
164 |  |
165 | 94 |
             if (isCaching)
166 |  |
             {
167 | 34 |
                 int cacheSize = Turbine.getConfiguration()
168 |  |
                     .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,
169 |  |
                             TurbineConstants.MODULE_CACHE_SIZE_DEFAULT);
170 |  |
171 | 34 |
                 assemblerCache = new LRUMap(cacheSize);
172 | 34 |
                 loaderCache = new LRUMap(cacheSize);
173 |  |
             }
174 |  |
175 | 94 |
             setInit(true);
176 | 94 |
         }
177 |  |
178 |  |
         /**
179 |  |
          * Register a new AssemblerFactory under a certain type
180 |  |
          *
181 |  |
          * @param type type of Assembler
182 |  |
          * @param factory factory to register
183 |  |
          */
184 |  |
         public void registerFactory(String type, AssemblerFactory factory)
185 |  |
         {
186 | 564 |
             getFactoryGroup(type).add(factory);
187 | 564 |
         }
188 |  |
189 |  |
         /**
190 |  |
          * Attempt to retrieve an Assembler of a given type with
191 |  |
          * a name.  Cycle through all the registered AssemblerFactory
192 |  |
          * classes of type and return the first non-null assembly
193 |  |
          * found.  If an assembly was not found return null.
194 |  |
          *
195 |  |
          * @param type type of Assembler
196 |  |
          * @param name name of the requested Assembler
197 |  |
          * @return an Assembler or null
198 |  |
          * @throws TurbineException
199 |  |
          */
200 |  |
         public Assembler getAssembler(String type, String name)
201 |  |
             throws TurbineException
202 |  |
         {
203 | 212 |
             String key = type + ":" + name;
204 | 212 |
             Assembler assembler = null;
205 |  |
206 | 212 |
             if (isCaching && assemblerCache.containsKey(key))
207 |  |
             {
208 | 0 |
                 assembler = assemblerCache.get(key);
209 | 0 |
                 log.debug("Found " + key + " in the cache!");
210 |  |
             }
211 |  |
             else
212 |  |
             {
213 | 212 |
                 log.debug("Loading " + key);
214 | 212 |
                 List<AssemblerFactory> facs = getFactoryGroup(type);
215 |  |
216 | 212 |
                 for (Iterator<AssemblerFactory> it = facs.iterator(); (assembler == null) && it.hasNext();)
217 |  |
                 {
218 | 212 |
                     AssemblerFactory fac = it.next();
219 |  |
220 |  |
                     try
221 |  |
                     {
222 | 212 |
                         assembler = fac.getAssembler(name);
223 |  |
                     }
224 | 0 |
                     catch (Exception e)
225 |  |
                     {
226 | 0 |
                         throw new TurbineException("Failed to load an assembler for "
227 |  |
                                                    + name + " from the "
228 |  |
                                                    + type + " factory "
229 |  |
                                                    + fac.getClass().getName(), e);
230 | 212 |
                     }
231 |  |
232 | 212 |
                     if (isCaching && assembler != null)
233 |  |
                     {
234 | 0 |
                         assemblerCache.put(key, assembler);
235 |  |
                     }
236 | 212 |
                 }
237 |  |
             }
238 |  |
239 | 212 |
             return assembler;
240 |  |
         }
241 |  |
242 |  |
         /**
243 |  |
          * Get a Loader for the given assembler type
244 |  |
          *
245 |  |
          * @param type The Type of the Assembler
246 |  |
          * @return A Loader instance for the requested type
247 |  |
          */
248 |  |
         public Loader getLoader(String type)
249 |  |
         {
250 | 1100 |
             Loader loader = null;
251 |  |
252 | 1100 |
             if (isCaching && loaderCache.containsKey(type))
253 |  |
             {
254 | 204 |
                 loader = loaderCache.get(type);
255 | 204 |
                 log.debug("Found " + type + " loader in the cache!");
256 |  |
             }
257 |  |
             else
258 |  |
             {
259 | 896 |
                 log.debug("Getting Loader for " + type);
260 | 896 |
                 List facs = getFactoryGroup(type);
261 |  |
262 | 896 |
                 for (Iterator it = facs.iterator(); (loader == null) && it.hasNext();)
263 |  |
                 {
264 | 896 |
                     AssemblerFactory fac = (AssemblerFactory) it.next();
265 |  |
266 | 896 |
                     loader = fac.getLoader();
267 | 896 |
                 }
268 |  |
269 | 896 |
                 if (isCaching && loader != null)
270 |  |
                 {
271 | 170 |
                     loaderCache.put(type, loader);
272 |  |
                 }
273 |  |
             }
274 |  |
275 | 1100 |
             if (loader == null)
276 |  |
             {
277 | 0 |
                 log.warn("Loader for " + type + " is null.");
278 |  |
             }
279 |  |
280 | 1100 |
             return loader;
281 |  |
         }
282 |  |
     }