| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang=""><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>TurbineAssemblerBrokerService.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Turbine</a> > <a href="index.source.html" class="el_package">org.apache.turbine.services.assemblerbroker</a> > <span class="el_source">TurbineAssemblerBrokerService.java</span></div><h1>TurbineAssemblerBrokerService.java</h1><pre class="source lang-java linenums">package org.apache.turbine.services.assemblerbroker; |
| |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| |
| import org.apache.commons.configuration2.Configuration; |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.turbine.Turbine; |
| import org.apache.turbine.TurbineConstants; |
| import org.apache.turbine.annotation.AnnotationProcessor; |
| import org.apache.turbine.modules.Assembler; |
| import org.apache.turbine.modules.Loader; |
| import org.apache.turbine.services.InitializationException; |
| import org.apache.turbine.services.TurbineBaseService; |
| import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory; |
| import org.apache.turbine.util.HttpUtils; |
| import org.apache.turbine.util.TurbineException; |
| import org.apache.turbine.util.uri.URIConstants; |
| |
| /** |
| * TurbineAssemblerBrokerService allows assemblers (like screens, |
| * actions and layouts) to be loaded from one or more AssemblerFactory |
| * classes. AssemblerFactory classes are registered with this broker |
| * by adding them to the TurbineResources.properties file. |
| * |
| * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a> |
| * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
| * @version $Id$ |
| */ |
| <span class="fc" id="L57">public class TurbineAssemblerBrokerService</span> |
| extends TurbineBaseService |
| implements AssemblerBrokerService |
| { |
| /** Logging */ |
| <span class="fc" id="L62"> private static Logger log</span> |
| <span class="fc" id="L63"> = LogManager.getLogger(TurbineAssemblerBrokerService.class);</span> |
| |
| /** A structure that holds the registered AssemblerFactories */ |
| <span class="fc" id="L66"> private Map<Class<?>, List<?>> factories = null;</span> |
| |
| /** A cache that holds the generated Assemblers */ |
| <span class="fc" id="L69"> private ConcurrentMap<String, Assembler> assemblerCache = null;</span> |
| |
| /** A cache that holds the Loaders */ |
| <span class="fc" id="L72"> private ConcurrentMap<Class<?>, Loader<? extends Assembler>> loaderCache = null;</span> |
| |
| /** Caching on/off */ |
| private boolean isCaching; |
| |
| /** |
| * Get a list of AssemblerFactories of a certain type |
| * |
| * @param type type of Assembler |
| * |
| * @param <T> the type of the assembler |
| * |
| * @return list of AssemblerFactories |
| */ |
| @SuppressWarnings("unchecked") |
| private <T extends Assembler> List<AssemblerFactory<T>> getFactoryGroup(Class<T> type) |
| { |
| <span class="fc bfc" id="L89" title="All 2 branches covered."> if (!factories.containsKey(type))</span> |
| { |
| <span class="fc" id="L91"> factories.put(type, new ArrayList<AssemblerFactory<T>>());</span> |
| } |
| <span class="fc" id="L93"> return (List<AssemblerFactory<T>>) factories.get(type);</span> |
| } |
| |
| /** |
| * Utility method to register all factories for a given type. |
| * |
| * @param type type of Assembler |
| * @throws TurbineException if the factory for the given type could not be registered |
| */ |
| private void registerFactories(String type) |
| throws TurbineException |
| { |
| <span class="fc" id="L105"> List<Object> names = getConfiguration().getList(type);</span> |
| |
| <span class="fc" id="L107"> log.info("Registering {} {} factories.", Integer.valueOf(names.size()), type);</span> |
| |
| <span class="fc bfc" id="L109" title="All 2 branches covered."> for (Object name2 : names)</span> |
| { |
| <span class="fc" id="L111"> String factory = (String) name2;</span> |
| try |
| { |
| @SuppressWarnings("unchecked") |
| <span class="fc" id="L115"> AssemblerFactory<? extends Assembler> af =</span> |
| <span class="fc" id="L116"> (AssemblerFactory<? extends Assembler>) Class.forName(factory).getDeclaredConstructor().newInstance();</span> |
| <span class="fc" id="L117"> registerFactory(af);</span> |
| } |
| // these must be passed to the VM |
| <span class="nc" id="L120"> catch (ThreadDeath | OutOfMemoryError e)</span> |
| { |
| <span class="nc" id="L122"> throw e;</span> |
| } |
| // when using Class.forName(), NoClassDefFoundErrors are likely |
| // to happen (missing jar files) |
| <span class="nc" id="L126"> catch (Throwable t)</span> |
| { |
| <span class="nc" id="L128"> throw new TurbineException("Failed registering " + type</span> |
| + " factory: " + factory, t); |
| <span class="fc" id="L130"> }</span> |
| <span class="fc" id="L131"> }</span> |
| <span class="fc" id="L132"> }</span> |
| |
| /** |
| * Initializes the AssemblerBroker and loads the AssemblerFactory |
| * classes registered in TurbineResources.Properties. |
| * |
| * @throws InitializationException if problems occur while registering the factories |
| */ |
| @Override |
| public void init() |
| throws InitializationException |
| { |
| <span class="fc" id="L144"> factories = new HashMap<>();</span> |
| |
| try |
| { |
| <span class="fc" id="L148"> Configuration conf = getConfiguration();</span> |
| |
| <span class="fc bfc" id="L150" title="All 2 branches covered."> for (Iterator<String> i = conf.getKeys(); i.hasNext();)</span> |
| { |
| <span class="fc" id="L152"> String type = i.next();</span> |
| |
| <span class="fc bfc" id="L154" title="All 2 branches covered."> if (!"classname".equalsIgnoreCase(type))</span> |
| { |
| <span class="fc" id="L156"> registerFactories(type);</span> |
| } |
| <span class="fc" id="L158"> }</span> |
| } |
| <span class="nc" id="L160"> catch (TurbineException e)</span> |
| { |
| <span class="nc" id="L162"> throw new InitializationException(</span> |
| "AssemblerBrokerService failed to initialize", e); |
| <span class="fc" id="L164"> }</span> |
| |
| <span class="fc" id="L166"> isCaching = Turbine.getConfiguration()</span> |
| <span class="fc" id="L167"> .getBoolean(TurbineConstants.MODULE_CACHE_KEY,</span> |
| TurbineConstants.MODULE_CACHE_DEFAULT); |
| |
| <span class="pc bpc" id="L170" title="1 of 2 branches missed."> if (isCaching)</span> |
| { |
| <span class="nc" id="L172"> int cacheSize = Turbine.getConfiguration()</span> |
| <span class="nc" id="L173"> .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,</span> |
| TurbineConstants.MODULE_CACHE_SIZE_DEFAULT); |
| |
| <span class="nc" id="L176"> assemblerCache = new ConcurrentHashMap<>(cacheSize);</span> |
| <span class="nc" id="L177"> loaderCache = new ConcurrentHashMap<>(cacheSize);</span> |
| } |
| |
| <span class="fc" id="L180"> setInit(true);</span> |
| <span class="fc" id="L181"> }</span> |
| |
| /** |
| * Register a new AssemblerFactory |
| * |
| * @param factory factory to register |
| * |
| * @param <T> the type of the assembler |
| * |
| */ |
| @Override |
| public <T extends Assembler> void registerFactory(AssemblerFactory<T> factory) |
| { |
| <span class="fc" id="L194"> getFactoryGroup(factory.getManagedClass()).add(factory);</span> |
| <span class="fc" id="L195"> }</span> |
| |
| /** |
| * Attempt to retrieve an Assembler of a given type with |
| * a name. Cycle through all the registered AssemblerFactory |
| * classes of type and return the first non-null assembly |
| * found. If an assembly was not found return null. |
| * |
| * @param type type of Assembler |
| * @param name name of the requested Assembler |
| * |
| * @param <T> the type of the assembler |
| * |
| * @return an Assembler or null |
| * @throws TurbineException if the assembler could not be loaded |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T extends Assembler> T getAssembler(Class<T> type, String name) |
| throws TurbineException |
| { |
| <span class="nc" id="L216"> String key = type + ":" + name;</span> |
| <span class="nc" id="L217"> T assembler = null;</span> |
| |
| <span class="nc" id="L219"> log.debug("Check name in key {} in assembler.", key);</span> |
| <span class="nc bnc" id="L220" title="All 2 branches missed."> if (HttpUtils.keyRequiresClean( name ))</span> |
| { |
| <span class="nc" id="L222"> String message = "Assembler key has invalid characters.";</span> |
| <span class="nc" id="L223"> log.warn("{}. Abort assembling for cleaned key {}:{}.", message, type, HttpUtils.getCleanedKey( name ) );</span> |
| <span class="nc" id="L224"> throw new TurbineException( message );</span> |
| } |
| |
| <span class="nc bnc" id="L227" title="All 4 branches missed."> if (isCaching && assemblerCache.containsKey(key))</span> |
| { |
| <span class="nc" id="L229"> assembler = (T) assemblerCache.get(key);</span> |
| <span class="nc" id="L230"> log.debug("Found {} in the cache!", key);</span> |
| } |
| else |
| { |
| <span class="nc" id="L234"> log.debug("Loading {}", key);</span> |
| <span class="nc" id="L235"> List<AssemblerFactory<T>> facs = getFactoryGroup(type);</span> |
| |
| <span class="nc bnc" id="L237" title="All 4 branches missed."> for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (assembler == null) && it.hasNext();)</span> |
| { |
| <span class="nc" id="L239"> AssemblerFactory<T> fac = it.next();</span> |
| |
| try |
| { |
| <span class="nc" id="L243"> assembler = fac.getAssembler(name);</span> |
| } |
| <span class="nc" id="L245"> catch (Exception e)</span> |
| { |
| <span class="nc" id="L247"> throw new TurbineException("Failed to load an assembler for "</span> |
| + name + " from the " |
| + type + " factory " |
| <span class="nc" id="L250"> + fac.getClass().getName(), e);</span> |
| <span class="nc" id="L251"> }</span> |
| |
| <span class="nc bnc" id="L253" title="All 2 branches missed."> if (assembler != null)</span> |
| { |
| <span class="nc" id="L255"> AnnotationProcessor.process(assembler);</span> |
| |
| <span class="nc bnc" id="L257" title="All 2 branches missed."> if (isCaching)</span> |
| { |
| <span class="nc" id="L259"> T oldAssembler = (T) assemblerCache.putIfAbsent(key, assembler);</span> |
| <span class="nc bnc" id="L260" title="All 2 branches missed."> if (oldAssembler != null)</span> |
| { |
| <span class="nc" id="L262"> assembler = oldAssembler;</span> |
| } |
| } |
| } |
| <span class="nc" id="L266"> }</span> |
| } |
| |
| <span class="nc" id="L269"> return assembler;</span> |
| } |
| |
| /** |
| * Get a Loader for the given assembler type |
| * |
| * @param type The Type of the Assembler |
| * |
| * @param <T> the type of the assembler |
| * |
| * @return A Loader instance for the requested type |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T extends Assembler> Loader<T> getLoader(Class<T> type) |
| { |
| <span class="fc" id="L285"> Loader<T> loader = null;</span> |
| |
| <span class="pc bpc" id="L287" title="3 of 4 branches missed."> if (isCaching && loaderCache.containsKey(type))</span> |
| { |
| <span class="nc" id="L289"> loader = (Loader<T>) loaderCache.get(type);</span> |
| <span class="nc" id="L290"> log.debug("Found {} loader in the cache!", type);</span> |
| } |
| else |
| { |
| <span class="fc" id="L294"> log.debug("Getting Loader for {}", type);</span> |
| <span class="fc" id="L295"> List<AssemblerFactory<T>> facs = getFactoryGroup(type);</span> |
| |
| <span class="pc bpc" id="L297" title="1 of 4 branches missed."> for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (loader == null) && it.hasNext();)</span> |
| { |
| <span class="fc" id="L299"> AssemblerFactory<T> fac = it.next();</span> |
| <span class="fc" id="L300"> loader = fac.getLoader();</span> |
| <span class="fc" id="L301"> }</span> |
| |
| <span class="pc bpc" id="L303" title="3 of 4 branches missed."> if (isCaching && loader != null)</span> |
| { |
| <span class="nc" id="L305"> loaderCache.put(type, loader);</span> |
| } |
| } |
| |
| <span class="pc bpc" id="L309" title="1 of 2 branches missed."> if (loader == null)</span> |
| { |
| <span class="nc" id="L311"> log.warn("Loader for {} is null.", type);</span> |
| } |
| |
| <span class="fc" id="L314"> return loader;</span> |
| } |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.12.202403310830</span></div></body></html> |