You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by at...@apache.org on 2008/03/31 01:47:11 UTC

svn commit: r642842 - /portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/

Author: ate
Date: Sun Mar 30 16:47:07 2008
New Revision: 642842

URL: http://svn.apache.org/viewvc?rev=642842&view=rev
Log:
Restarting support for dynamic Spring assembly filtering based on configurable categories and bean meta data.
The previous solution using a Spring BeanFactoryPostProcessor didn't work out for all required use-cases.
This solution is more directly going to *prevent* registering BeanDefinitions.
Concrete Implementation and usage of these will follow later.

Added:
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java   (with props)

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import java.util.Properties;
+
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * Configures and adds a Spring PropertyPlaceholderConfigurer to an ConfigurableApplicationContext
+ * for replacing specific property placeholders at initialization time.
+ * <p>
+ * The PropertyPlaceholderConfigurer will be setup to ignore unresolved property placeholders
+ * and to <emp>never</emp> fallback to System properties if a property is unresolved.
+ * </p>
+ * <p>
+ * The PropertyPlaceholderConfigurer is then added to the provided ConfigurableApplicationContext
+ * using {@link ConfigurableApplicationContext#addBeanFactoryPostProcessor}.
+ * <p/>
+ * <p>
+ * This should be done before the context is refreshed for the first time.
+ * </p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class ApplicationContextBootPropertiesConfigurer
+{
+    public static void init(ConfigurableApplicationContext context, Properties bootProperties)
+    {
+        PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+        ppc.setIgnoreUnresolvablePlaceholders(true);
+        ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_NEVER);
+        ppc.setProperties(bootProperties);
+        context.addBeanFactoryPostProcessor(ppc);
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/ApplicationContextBootPropertiesConfigurer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import java.util.Properties;
+
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class FilteringClassPathXmlApplicationContext extends ClassPathXmlApplicationContext
+{
+    private JetspeedBeanDefinitionFilter filter;
+    
+    public FilteringClassPathXmlApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties)
+    {
+        this(filter, configLocations, initProperties, null);
+    }
+    
+    public FilteringClassPathXmlApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties, ApplicationContext parent)
+    {
+        super(parent);
+        if (initProperties != null)
+        {
+            PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+            ppc.setIgnoreUnresolvablePlaceholders(true);
+            ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK);
+            ppc.setProperties(initProperties);
+            this.addBeanFactoryPostProcessor(ppc);
+        }
+        this.setConfigLocations(configLocations);
+        this.filter = filter;
+    }
+    
+    protected DefaultListableBeanFactory createBeanFactory()
+    {
+        return new FilteringListableBeanFactory(filter, getInternalParentBeanFactory());
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringClassPathXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import java.util.Properties;
+
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+/**
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class FilteringFileSystemXmlApplicationContext extends FileSystemXmlApplicationContext
+{
+    private JetspeedBeanDefinitionFilter filter;
+        
+    public FilteringFileSystemXmlApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties)
+    {
+        this(filter, configLocations, initProperties, null);
+    }
+    
+    public FilteringFileSystemXmlApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties, ApplicationContext parent)
+    {
+        super();
+        if (parent != null)
+        {
+            this.setParent(parent);
+        }
+        if (initProperties != null)
+        {
+            PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+            ppc.setIgnoreUnresolvablePlaceholders(true);
+            ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK);
+            ppc.setProperties(initProperties);
+            this.addBeanFactoryPostProcessor(ppc);
+        }
+        this.setConfigLocations(configLocations);
+        this.filter = filter;
+    }
+    
+    protected DefaultListableBeanFactory createBeanFactory()
+    {
+        return new FilteringListableBeanFactory(filter, getInternalParentBeanFactory());
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringFileSystemXmlApplicationContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+
+/**
+ * Extension of the default/standard Spring BeanFactory (as used by Jetspeed) to allow
+ * conditional filtering of BeanDefinition with the (optionally) provided JetspeedBeanDefinitionFilter.
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class FilteringListableBeanFactory extends DefaultListableBeanFactory
+{
+    private JetspeedBeanDefinitionFilter filter;
+    
+    public FilteringListableBeanFactory(JetspeedBeanDefinitionFilter filter, BeanFactory parentBeanFactory)
+    {
+        super(parentBeanFactory);
+        this.filter = filter;
+        if (filter != null)
+        {
+            this.filter.init();
+        }
+    }
+
+    /**
+     * Override of the registerBeanDefinition method to optionally filter out a BeanDefinition and
+     * if requested dynamically register an bean alias
+     */
+    public void registerBeanDefinition(String beanName, BeanDefinition bd)
+            throws BeanDefinitionStoreException
+    {
+        boolean match = filter != null && filter.match(bd);
+        if (filter == null || match)
+        {
+            super.registerBeanDefinition(beanName, bd);
+            if (filter != null)
+            {
+                filter.registerDynamicAlias(this, beanName, bd);
+            }
+        }
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringListableBeanFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+/**
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class FilteringXmlWebApplicationContext extends XmlWebApplicationContext
+{
+    private JetspeedBeanDefinitionFilter filter;
+    
+    public FilteringXmlWebApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties, ServletContext servletContext)
+    {
+        this(filter, configLocations, initProperties, servletContext, null);
+    }
+    
+    public FilteringXmlWebApplicationContext(JetspeedBeanDefinitionFilter filter, String[] configLocations, Properties initProperties, ServletContext servletContext, ApplicationContext parent)
+    {
+        super();
+        if (parent != null)
+        {
+            this.setParent(parent);
+        }
+        if (initProperties != null)
+        {
+            PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+            ppc.setIgnoreUnresolvablePlaceholders(true);
+            ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK);
+            ppc.setProperties(initProperties);
+            addBeanFactoryPostProcessor(ppc);
+        }
+        setConfigLocations(configLocations);
+        setServletContext(servletContext);
+        this.filter = filter;
+    }
+    
+    protected DefaultListableBeanFactory createBeanFactory()
+    {
+        return new FilteringListableBeanFactory(filter, getInternalParentBeanFactory());
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/FilteringXmlWebApplicationContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java?rev=642842&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java Sun Mar 30 16:47:07 2008
@@ -0,0 +1,377 @@
+/*
+ * 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.
+ */
+package org.apache.jetspeed.components;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanDefinitionValidationException;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.io.support.PropertiesLoaderSupport;
+
+/**
+ * The JetspeedBeanDefinitionFilter makes it possible to dynamically filter out a BeanDefinition
+ * before it is registered in a Spring BeanFactory based on category meta data in the Spring configuration.
+ * <p>
+ * Categories definitions are loaded from one or more properties files and are simply sets of names to
+ * evaluate bean definitions against. A categories set is a comma separated list of names.
+ * Multiple sets of categories can be defined in the provided properties files, and also reference (include)
+ * each other using standard ${property} syntax.
+ * </p>
+ * <p>
+ * A specific property containing the categories to be used for filtering is defined through
+ * method {@link #setCategoriesKey}, or as <code>JetspeedBeanDefinitionFilter.categoriesKey</code>
+ * property in one of the loaded property files, or as System (-D) parameter.
+ * A System parameter is checked first, then the loaded properties and only as last resort the bean property itself.
+ * </p>
+ * <p>
+ * The categories set to be used can also be set directly through the {@link #categories} method.
+ * </p>
+ * <p>
+ * Beans which needs to be matched against active categories must define a:<br/>
+ * <pre>&lt;meta key="j2:cat" value="&lt;categories&gt;"/&gt;</pre> meta value within the bean definition.
+ * The bean categories value may contain multiple comma separated values.
+ * </p>
+ * <p>
+ * Unmatched beans (having a "j2:cat" meta value for which none were active) will not be registered in the
+ * Spring beanFactory (see: {@link FilteringListableBeanFactory}. By not defining an id or name attribute,
+ * or a unique one not referenced by other beans with different (or no) set of categories, different versions
+ * of a similar bean can be defined within a single Spring configuration file.
+ * </p>
+ * <p>
+ * Additionally an alias can be defined as bean meta value, allowing multiple beans to
+ * be defined using the same alias:<br/>
+ * <pre>&lt;meta key="j2:alias" value="&lt;alias&gt;"/&gt;</pre>
+ * Only a matched bean its alias will be registered and thereby able to be referenced by other beans
+ * (on this dynamically created alias).
+ * For this type of "enabling" only one of many possible beans definitions, these beans should
+ * not define an id or name attribute directly, or only an unique one which is not referenced or
+ * only referenced by other beans which have a "matching" j2:cat meta value.
+ * </p>
+ * <p>
+ * Optionally, all beans without a "j2:cat" meta value can be set to lazy initialization
+ * too, through method {@link #setDefaultLazyInit} (default value: null). This property can also
+ * be defined directly as <code>CategoryFilteringPostProcessor.defaultLazyInit</code> property in one
+ * of the loaded properties files or as System parameter. The order of evaluation is the same as with
+ * the <code>categoriesKey</code> (see above).
+ * </p>
+ * <p>
+ * For beans which explicitely need lazy initialization (or not), a meta value can
+ * be defined to overrule/enforce the default behavior:
+ * <pre>&lt;meta key="j2:lazy" value="&lt;true|false&gt;"/&gt;</pre>
+ * </p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @since 2.2
+ * @version $Id$
+ */
+public class JetspeedBeanDefinitionFilter extends PropertiesLoaderSupport
+{
+    private static Log log = LogFactory.getLog(JetspeedBeanDefinitionFilter.class);
+    
+    public static final String SYSTEM_PROPERTY_CATEGORIES_KEY = "JetspeedBeanDefinitionFilter.categoriesKey";
+    public static final String SYSTEM_PROPERTY_DEFAULT_LAZY_INIT = "JetspeedBeanDefinitionFilter.defaultLazyInit";
+    
+    public static final String CATEGORY_META_KEY = "j2:cat";
+    public static final String ALIAS_META_KEY = "j2:alias";
+    public static final String LAZY_META_KEY = "j2:lazy";
+
+    private String categoriesKey;
+    private Boolean defaultLazyInit;
+    private Properties props;
+    private Set categories;
+    private boolean initialized;
+    
+    public JetspeedBeanDefinitionFilter()
+    {
+    }
+    
+    public JetspeedBeanDefinitionFilter(Boolean defaultLazyInit, String categories)
+    {
+        setDefaultLazyInit(defaultLazyInit);
+        setCategories(categories);
+    }
+    
+    public JetspeedBeanDefinitionFilter(Boolean defaultLazyInit, Set categories)
+    {
+        setDefaultLazyInit(defaultLazyInit);
+        setCategories(categories);
+    }
+    
+    public JetspeedBeanDefinitionFilter(String categoriesKey, Boolean defaultLazyInit)
+    {
+        setCategoriesKey(categoriesKey);
+        setDefaultLazyInit(defaultLazyInit);
+    }
+    
+    public JetspeedBeanDefinitionFilter(String propertiesLocation) throws IOException
+    {
+        loadProperties(new String[]{propertiesLocation});
+    }
+    
+    public JetspeedBeanDefinitionFilter(String propertiesLocation, String categoriesKey, Boolean defaultLazyInit) throws IOException
+    {
+        this(categoriesKey, defaultLazyInit);
+        loadProperties(new String[]{propertiesLocation});
+    }
+    
+    public JetspeedBeanDefinitionFilter(String[] propertiesLocations, String categoriesKey, Boolean defaultLazyInit) throws IOException
+    {
+        this(categoriesKey, defaultLazyInit);
+        loadProperties(propertiesLocations);
+    }
+    
+    protected void loadProperties(String[] propertiesLocations) throws IOException
+    {
+        if (propertiesLocations != null)
+        {
+            ResourceLoader resourceLoader = new DefaultResourceLoader();
+            Resource[] resources = new Resource[propertiesLocations.length];
+            for (int i = 0; i < propertiesLocations.length; i++)
+            {
+                resources[i] = resourceLoader.getResource(propertiesLocations[i]);
+            }
+            setLocations(resources);
+            props = new Properties();
+            loadProperties(props);
+            
+            // interpolation of property references within properties delimited by '${' and '}'
+            // based on org.apache.maven.plugin.resources.PropertiesUtils
+            HashSet circularRefs = new HashSet();
+            ArrayList visitedProps = new ArrayList();
+            for ( Enumeration n = props.propertyNames(); n.hasMoreElements(); )
+            {
+                String k = (String) n.nextElement();
+                String v = props.getProperty( k );
+                String result = "";
+                String nk, nv;
+                int idx, idx2;
+                visitedProps.clear();
+                visitedProps.add(k);
+
+                while ( ( idx = v.indexOf( "${" ) ) >= 0 )
+                {
+                    // append prefix to result
+                    result += v.substring( 0, idx );
+
+                    // strip prefix from original
+                    v = v.substring( idx + 2 );
+
+                    // if no matching } then bail
+                    if ( ( idx2 = v.indexOf( '}' ) ) < 0 )
+                    {
+                        break;
+                    }
+
+                    // strip out the key and resolve it
+                    // resolve the key/value for the ${statement}
+                    nk = v.substring( 0, idx2 );
+                    v = v.substring( idx2 + 1 );
+                    
+                    nv = null;
+                    
+                    if (circularRefs.contains(nk) || visitedProps.contains(nk))
+                    {
+                        // prevent looping
+                        log.error("Circular property reference: "+nk+" encountered for: "+k+". Property value not fully resolved");
+                        circularRefs.add(k);
+                    }
+                    else
+                    {                    
+                        nv = props.getProperty( nk );
+
+                        // try global environment..
+                        if ( nv == null )
+                        {
+                            nv = System.getProperty( nk );
+                        }
+                        else
+                        {
+                            visitedProps.add(nk);
+                        }
+                    }
+
+                    // if the key cannot be resolved,
+                    // leave it alone ( and don't parse again )
+                    // else prefix the original string with the
+                    // resolved property ( so it can be parsed further )
+                    // taking recursion into account.
+                    if ( nv == null || nv.equals( k ) )
+                    {
+                        result += "${" + nk + "}";
+                    }
+                    else
+                    {
+                        v = nv + v;
+                    }
+                }
+                props.setProperty( k, result + v );
+            }
+        }
+    }
+    
+    public void setCategoriesKey(String categoriesKey)
+    {
+        this.categoriesKey = categoriesKey;
+    }
+
+    public void setDefaultLazyInit(Boolean defaultLazyInit)
+    {
+        this.defaultLazyInit = defaultLazyInit;
+    }
+    
+    public void setCategories(String categories)
+    {
+        if (categories != null && categories.length()>0)
+        {            
+            this.categories = new HashSet();
+            StringTokenizer st = new StringTokenizer(categories, " ,;\t");
+            while (st.hasMoreTokens())
+            {
+                this.categories.add(st.nextToken());
+            }
+        }
+        else
+        {
+            this.categories = null;
+        }
+    }
+
+    public void setCategories(Set categories)
+    {
+        this.categories = categories;
+    }
+    
+    public void init() throws IllegalStateException
+    {
+        if (!initialized)
+        {
+            initialized = true;
+            
+            if (props != null && categories == null)
+            {
+                this.categories = new HashSet();
+                String value = System.getProperty(SYSTEM_PROPERTY_CATEGORIES_KEY);
+                if (value == null && props != null)
+                {
+                    value = props.getProperty(SYSTEM_PROPERTY_CATEGORIES_KEY);
+                }
+                if (value != null)
+                {
+                    categoriesKey = value;
+                }
+                if (categoriesKey == null || categoriesKey.length() == 0)
+                {            
+                    throw new IllegalStateException("Required property categoriesKey undefined");
+                }
+                else
+                {
+                    String categories = (String)props.get(categoriesKey);
+                    if (categories != null && categories.length()>0)
+                    {
+                        StringTokenizer st = new StringTokenizer(categories, " ,;\t");
+                        while (st.hasMoreTokens())
+                        {
+                            this.categories.add(st.nextToken());
+                        }
+                    }
+                    props = null;
+                }               
+            }
+            if (this.categories == null)
+            {
+                this.categories = new HashSet();
+            }
+            String value = System.getProperty(SYSTEM_PROPERTY_DEFAULT_LAZY_INIT);
+            if (value == null && props != null)
+            {
+                value = props.getProperty(SYSTEM_PROPERTY_DEFAULT_LAZY_INIT);
+            }
+            if (value != null)
+            {
+                defaultLazyInit = Boolean.valueOf(value);
+            }
+        }
+    }
+    
+    public boolean match(BeanDefinition bd)
+    {
+        String beanCategories = (String)bd.getAttribute(CATEGORY_META_KEY);
+        Boolean lazyInit = defaultLazyInit;
+        boolean matched = true;
+        if (beanCategories != null)
+        {
+            matched = false;
+            StringTokenizer st = new StringTokenizer(beanCategories, " ,;\t");
+            while (st.hasMoreTokens())
+            {
+                if (categories.contains(st.nextToken()))
+                {
+                    matched = true;
+                    break;
+                }
+            }
+        }
+        if (matched)
+        {
+            if (bd instanceof AbstractBeanDefinition)
+            {
+                AbstractBeanDefinition abd = (AbstractBeanDefinition)bd;
+                String j2Lazy = (String)bd.getAttribute(LAZY_META_KEY);
+                if (j2Lazy != null)
+                {
+                    lazyInit = Boolean.valueOf((String)bd.getAttribute(LAZY_META_KEY));
+                }
+                if (lazyInit != null)
+                {
+                    abd.setLazyInit(lazyInit.booleanValue());
+                }
+            }
+        }
+        return matched;
+    }
+    
+    public void registerDynamicAlias(BeanDefinitionRegistry registry, String beanName, BeanDefinition bd)
+    {
+        String alias = (String)bd.getAttribute(ALIAS_META_KEY);
+        if (alias != null && !alias.equals(beanName))
+        {
+            if (registry.isBeanNameInUse(alias))
+            {
+                String src = "";
+                if (bd.getSource() != null)
+                {
+                    src = "("+bd.getSource().toString()+")";
+                }
+                throw new BeanDefinitionValidationException("j2:alias '"+alias+"' for bean '"+beanName+"' already in use "+src);
+            }
+            registry.registerAlias(beanName, alias);
+        }
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/main/java/org/apache/jetspeed/components/JetspeedBeanDefinitionFilter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org