/** * This file Copyright (c) 2011-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.objectfactory.configuration; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.magnolia.init.MagnoliaConfigurationProperties; import info.magnolia.module.model.ComponentDefinition; import info.magnolia.objectfactory.Classes; import info.magnolia.objectfactory.ComponentConfigurationPath; import info.magnolia.objectfactory.ComponentFactory; import info.magnolia.objectfactory.ComponentProvider; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * This ComponentConfigurer configures components from properties. Each property key is the interface/base-class, and the * value is either the implementation-to-use class name, an implementation of {@link ComponentFactory} which is used to * instantiate the desired implementation, or the path to a node in the repository (in the form of * repository:/path/to/node or /path/to/node, which defaults to the config * repository). In the latter case, the component is constructed via * {@link info.magnolia.objectfactory.ObservedComponentFactory} and reflects (through observation) the contents of the * given path. *

* This behaviour exists for backwards compatibility reasons, prefer configuring your components in a module * descriptor instead, inside a components tag. *

* In order to remain backwards compatible implementations are added both as type mappings and as components and then * always scoped as lazy singletons. *

* Note that this mechanism can pose problems for properties that are fully classified class names, that class exists * on the class path and the class does not pass Guice static analysis which requires it to have a default constructor * or a constructor annotated with @Inject. If you encounter this problem you can exclude this class using the * {@link #EXCLUDED_PROPERTIES_PROPERTY_NAME} property. * * @version $Id$ */ public class LegacyComponentsConfigurer implements ComponentConfigurer { private final static Logger log = LoggerFactory.getLogger(LegacyComponentsConfigurer.class); public final static String EXCLUDED_PROPERTIES_PROPERTY_NAME = "magnolia.components.config.properties.excluded"; @Override public void doWithConfiguration(ComponentProvider parentComponentProvider, ComponentProviderConfiguration configuration) { MagnoliaConfigurationProperties configurationProperties = parentComponentProvider.getComponent(MagnoliaConfigurationProperties.class); Set excludedKeys = getExcludedKeys(configurationProperties); if (configurationProperties != null) { for (String key : configurationProperties.getKeys()) { if (!excludedKeys.contains(key)) { addComponent(configuration, key, configurationProperties.getProperty(key)); } } } } protected Set getExcludedKeys(MagnoliaConfigurationProperties configurationProperties) { HashSet excluded = new HashSet(); // We know this property to cause problem when using JRebel excluded.add("com.zeroturnaround.bundled.org.apache.commons.logging.Log"); // Properties explicitly configured String propertyNames = configurationProperties.getProperty(EXCLUDED_PROPERTIES_PROPERTY_NAME); if (propertyNames != null) { Collections.addAll(excluded, StringUtils.split(propertyNames, " \t,")); } return excluded; } protected void addComponent(ComponentProviderConfiguration componentProviderConfiguration, String key, String value) { final Class type = (Class) classForName(key); if (type == null) { log.debug("{} does not seem to resolve to a class. (property value: {})", key, value); return; } if (ComponentConfigurationPath.isComponentConfigurationPath(value)) { componentProviderConfiguration.addComponent(getObserved(type, value)); } else { Class valueType = (Class) classForName(value); if (valueType == null) { log.debug("{} does not seem to resolve a class or a configuration path. (property key: {})", value, key); } else { if (ComponentFactory.class.isAssignableFrom(valueType)) { componentProviderConfiguration.addComponent(getComponentFactory(type, (Class>) valueType)); } else { componentProviderConfiguration.addComponent(getImplementation(type, valueType)); componentProviderConfiguration.addTypeMapping(type, valueType); } } } } protected ImplementationConfiguration getImplementation(Class type, Class implementation) { ImplementationConfiguration configuration = new ImplementationConfiguration(); configuration.setType(type); configuration.setImplementation(implementation); configuration.setScope(ComponentDefinition.SCOPE_SINGLETON); configuration.setLazy(true); return configuration; } protected ProviderConfiguration getComponentFactory(Class type, Class> factoryClass) { ProviderConfiguration configuration = new ProviderConfiguration(); configuration.setType(type); configuration.setProviderClass(factoryClass); configuration.setScope(ComponentDefinition.SCOPE_SINGLETON); configuration.setLazy(true); return configuration; } protected ConfiguredComponentConfiguration getObserved(Class type, String workspaceAndPath) { ComponentConfigurationPath path = new ComponentConfigurationPath(workspaceAndPath); ConfiguredComponentConfiguration configuration = new ConfiguredComponentConfiguration(); configuration.setType(type); configuration.setWorkspace(path.getRepository()); configuration.setPath(path.getPath()); configuration.setObserved(true); configuration.setScope(ComponentDefinition.SCOPE_SINGLETON); configuration.setLazy(true); return configuration; } protected Class classForName(String value) { try { return Classes.getClassFactory().forName(value); } catch (ClassNotFoundException e) { return null; } } }