View Javadoc
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 }