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.lang3.StringUtils;
27  import org.apache.logging.log4j.LogManager;
28  import org.apache.logging.log4j.Logger;
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 Logger log = LogManager.getLogger(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<>();
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          log.debug("Class Fragment is {}", name);
70  
71          if (StringUtils.isNotEmpty(name))
72          {
73              for (String p : packages)
74              {
75                  StringBuilder sb = new StringBuilder();
76  
77                  sb.append(p).append('.').append(packageName).append('.').append(name);
78                  String className = sb.toString();
79  
80                  log.debug("Trying {}", className);
81  
82                  try
83                  {
84                      Class<T> servClass = classCache.get(className);
85                      if (servClass == null)
86                      {
87                          servClass = (Class<T>) Class.forName(className);
88                          Class<T> _servClass = classCache.putIfAbsent(className, servClass);
89                          if (_servClass != null)
90                          {
91                              servClass = _servClass;
92                          }
93                      }
94                      assembler = servClass.newInstance();
95                      break; // for()
96                  }
97                  catch (ClassNotFoundException cnfe)
98                  {
99                      // Do this so we loop through all the packages.
100                     log.debug("{}: Not found", className);
101                 }
102                 catch (NoClassDefFoundError ncdfe)
103                 {
104                     // Do this so we loop through all the packages.
105                     log.debug("{}: No Class Definition found", className);
106                 }
107                 // With ClassCastException, InstantiationException we hit big problems
108                 catch (ClassCastException | InstantiationException | IllegalAccessException e)
109                 {
110                     // This means trouble!
111                     // Alternatively we can throw this exception so
112                     // that it will appear on the client browser
113                     log.error("Could not load {}", className, e);
114                     break; // for()
115                 }
116             }
117         }
118 
119         log.debug("Returning: {}", assembler);
120 
121         return assembler;
122     }
123 
124     /**
125      * Get the loader for this type of assembler
126      *
127      * @return a Loader
128      */
129     @Override
130     public abstract Loader<T> getLoader();
131 
132     /**
133      * Get the size of a possibly configured cache
134      *
135      * @return the size of the cache in bytes
136      */
137     @Override
138     public int getCacheSize()
139     {
140         return getLoader().getCacheSize();
141     }
142 }