1 package org.apache.turbine.services.assemblerbroker.util.java;
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 import java.util.List;
24 import java.util.concurrent.ConcurrentHashMap;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.turbine.modules.Assembler;
30 import org.apache.turbine.modules.GenericLoader;
31 import org.apache.turbine.modules.Loader;
32 import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
33
34 /**
35 * A screen factory that attempts to load a java class from
36 * the module packages defined in the TurbineResource.properties.
37 *
38 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
39 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
40 * @param <T> the specialized assembler type
41 */
42 public abstract class JavaBaseFactory<T extends Assembler>
43 implements AssemblerFactory<T>
44 {
45 /** A vector of packages. */
46 private static List<String> packages = GenericLoader.getPackages();
47
48 /** Logging */
49 protected Log log = LogFactory.getLog(this.getClass());
50
51 /**
52 * A cache for previously obtained Class instances, which we keep in order
53 * to reduce the Class.forName() overhead (which can be sizable).
54 */
55 private final ConcurrentHashMap<String, Class<T>> classCache = new ConcurrentHashMap<String, Class<T>>();
56
57 /**
58 * Get an Assembler.
59 *
60 * @param packageName java package name
61 * @param name name of the requested Assembler
62 * @return an Assembler
63 */
64 @SuppressWarnings("unchecked")
65 public T getAssembler(String packageName, String name)
66 {
67 T assembler = null;
68
69 if (log.isDebugEnabled())
70 {
71 log.debug("Class Fragment is " + name);
72 }
73
74 if (StringUtils.isNotEmpty(name))
75 {
76 for (String p : packages)
77 {
78 StringBuilder sb = new StringBuilder();
79
80 sb.append(p).append('.').append(packageName).append('.').append(name);
81 String className = sb.toString();
82
83 if (log.isDebugEnabled())
84 {
85 log.debug("Trying " + className);
86 }
87
88 try
89 {
90 Class<T> servClass = classCache.get(className);
91 if (servClass == null)
92 {
93 servClass = (Class<T>) Class.forName(className);
94 Class<T> _servClass = classCache.putIfAbsent(className, servClass);
95 if (_servClass != null)
96 {
97 servClass = _servClass;
98 }
99 }
100 assembler = servClass.newInstance();
101 break; // for()
102 }
103 catch (ClassNotFoundException cnfe)
104 {
105 // Do this so we loop through all the packages.
106 log.debug(className + ": Not found");
107 }
108 catch (NoClassDefFoundError ncdfe)
109 {
110 // Do this so we loop through all the packages.
111 log.debug(className + ": No Class Definition found");
112 }
113 catch (ClassCastException cce)
114 {
115 // This means trouble!
116 // Alternatively we can throw this exception so
117 // that it will appear on the client browser
118 log.error("Could not load "+className, cce);
119 break; // for()
120 }
121 catch (InstantiationException ine)
122 {
123 // This means trouble!
124 // Alternatively we can throw this exception so
125 // that it will appear on the client browser
126 log.error("Could not load "+className, ine);
127 break; // for()
128 }
129 catch (IllegalAccessException ilae)
130 {
131 // This means trouble!
132 // Alternatively we can throw this exception so
133 // that it will appear on the client browser
134 log.error("Could not load "+className, ilae);
135 break; // for()
136 }
137 // With ClassCastException, InstantiationException we hit big problems
138 }
139 }
140
141 if (log.isDebugEnabled())
142 {
143 log.debug("Returning: " + assembler);
144 }
145
146 return assembler;
147 }
148
149 /**
150 * Get the loader for this type of assembler
151 *
152 * @return a Loader
153 */
154 @Override
155 public abstract Loader<T> getLoader();
156
157 /**
158 * Get the size of a possibly configured cache
159 *
160 * @return the size of the cache in bytes
161 */
162 @Override
163 public int getCacheSize()
164 {
165 return getLoader().getCacheSize();
166 }
167 }