You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2009/07/31 18:11:00 UTC

svn commit: r799652 - in /felix/trunk/scr/src: main/java/org/apache/felix/scr/impl/BundleComponentActivator.java test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java

Author: fmeschbe
Date: Fri Jul 31 16:10:59 2009
New Revision: 799652

URL: http://svn.apache.org/viewvc?rev=799652&view=rev
Log:
FELIX-928 Apply patch by Alin Derhiciu (thanks) and factored the actual descriptor
reading into a separate method.

Added:
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java   (with props)
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java?rev=799652&r1=799651&r2=799652&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java Fri Jul 31 16:10:59 2009
@@ -25,6 +25,7 @@
 import java.io.InputStreamReader;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -35,6 +36,7 @@
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.XmlHandler;
 import org.apache.felix.scr.impl.parser.KXml2SAXParser;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentException;
 import org.osgi.service.log.LogService;
@@ -127,8 +129,8 @@
         {
             String descriptorLocation = st.nextToken();
 
-            URL descriptorURL = m_context.getBundle().getResource( descriptorLocation );
-            if ( descriptorURL == null )
+            URL[] descriptorURLs = findDescriptors( m_context.getBundle(), descriptorLocation );
+            if ( descriptorURLs.length == 0 )
             {
                 // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
                 // fragments, SCR must log an error message with the Log Service, if present, and continue.
@@ -137,80 +139,150 @@
                 continue;
             }
 
-            InputStream stream = null;
-            try
+            // load from the descriptors
+            for ( int i = 0; i < descriptorURLs.length; i++ )
+            {
+                loadDescriptor( descriptorURLs[i] );
+            }
+        }
+    }
+
+
+    /**
+     * Finds component descriptors based on descriptor location.
+     *
+     * @param bundle bundle to search for descriptor files
+     * @param descriptorLocation descriptor location
+     * @return array of descriptors or empty array if none found
+     */
+    static URL[] findDescriptors( final Bundle bundle, final String descriptorLocation )
+    {
+        if ( bundle == null || descriptorLocation == null || descriptorLocation.trim().length() == 0 )
+        {
+            return new URL[0];
+        }
+
+        // for compatibility with previoues versions (<= 1.0.8) use getResource() for non wildcarded entries
+        if ( descriptorLocation.indexOf( "*" ) == -1 )
+        {
+            final URL descriptor = bundle.getResource( descriptorLocation );
+            if ( descriptor == null )
             {
-                stream = descriptorURL.openStream();
+                return new URL[0];
+            }
+            return new URL[]
+                { descriptor };
+        }
+
+        // split pattern and path
+        final int lios = descriptorLocation.lastIndexOf( "/" );
+        final String path;
+        final String filePattern;
+        if ( lios > 0 )
+        {
+            path = descriptorLocation.substring( 0, lios );
+            filePattern = descriptorLocation.substring( lios + 1 );
+        }
+        else
+        {
+            path = "/";
+            filePattern = descriptorLocation;
+        }
+
+        // find the entries
+        final Enumeration entries = bundle.findEntries( path, filePattern, false );
+        if ( entries == null || !entries.hasMoreElements() )
+        {
+            return new URL[0];
+        }
+
+        // create the result list
+        List urls = new ArrayList();
+        while ( entries.hasMoreElements() )
+        {
+            urls.add( entries.nextElement() );
+        }
+        return ( URL[] ) urls.toArray( new URL[urls.size()] );
+    }
+
+
+    private void loadDescriptor( final URL descriptorURL )
+    {
+        // simple path for log messages
+        final String descriptorLocation = descriptorURL.getPath();
+
+        InputStream stream = null;
+        try
+        {
+            stream = descriptorURL.openStream();
 
-                BufferedReader in = new BufferedReader( new InputStreamReader( stream ) );
-                XmlHandler handler = new XmlHandler( m_context.getBundle(), this );
-                KXml2SAXParser parser;
+            BufferedReader in = new BufferedReader( new InputStreamReader( stream ) );
+            XmlHandler handler = new XmlHandler( m_context.getBundle(), this );
+            KXml2SAXParser parser;
 
-                parser = new KXml2SAXParser( in );
+            parser = new KXml2SAXParser( in );
 
-                parser.parseXML( handler );
+            parser.parseXML( handler );
 
-                // 112.4.2 Component descriptors may contain a single, root component element
-                // or one or more component elements embedded in a larger document
-                Iterator i = handler.getComponentMetadataList().iterator();
-                while ( i.hasNext() )
+            // 112.4.2 Component descriptors may contain a single, root component element
+            // or one or more component elements embedded in a larger document
+            Iterator i = handler.getComponentMetadataList().iterator();
+            while ( i.hasNext() )
+            {
+                ComponentMetadata metadata = ( ComponentMetadata ) i.next();
+                try
                 {
-                    ComponentMetadata metadata = ( ComponentMetadata ) i.next();
-                    try
-                    {
-                        // check and reserve the component name
-                        m_componentRegistry.checkComponentName( metadata.getName() );
+                    // check and reserve the component name
+                    m_componentRegistry.checkComponentName( metadata.getName() );
 
-                        // validate the component metadata
-                        metadata.validate( this );
+                    // validate the component metadata
+                    metadata.validate( this );
 
-                        // Request creation of the component manager
-                        ComponentHolder holder = m_componentRegistry.createComponentHolder( this, metadata );
+                    // Request creation of the component manager
+                    ComponentHolder holder = m_componentRegistry.createComponentHolder( this, metadata );
 
-                        // register the component after validation
-                        m_componentRegistry.registerComponent( metadata.getName(), holder );
-                        m_managers.add( holder );
-
-                        // enable the component
-                        if ( metadata.isEnabled() )
-                        {
-                            holder.enableComponents();
-                        }
-                   }
-                    catch ( Throwable t )
-                    {
-                        // There is a problem with this particular component, we'll log the error
-                        // and proceed to the next one
-                        log( LogService.LOG_ERROR, "Cannot register Component", metadata, t );
+                    // register the component after validation
+                    m_componentRegistry.registerComponent( metadata.getName(), holder );
+                    m_managers.add( holder );
 
-                        // make sure the name is not reserved any more
-                        m_componentRegistry.unregisterComponent( metadata.getName() );
+                    // enable the component
+                    if ( metadata.isEnabled() )
+                    {
+                        holder.enableComponents();
                     }
                 }
-            }
-            catch ( IOException ex )
-            {
-                // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
-                // fragments, SCR must log an error message with the Log Service, if present, and continue.
+                catch ( Throwable t )
+                {
+                    // There is a problem with this particular component, we'll log the error
+                    // and proceed to the next one
+                    log( LogService.LOG_ERROR, "Cannot register Component", metadata, t );
 
-                log( LogService.LOG_ERROR, "Problem reading descriptor entry '" + descriptorLocation + "'", null, ex );
-            }
-            catch ( Exception ex )
-            {
-                log( LogService.LOG_ERROR, "General problem with descriptor entry '" + descriptorLocation + "'", null,
-                    ex );
+                    // make sure the name is not reserved any more
+                    m_componentRegistry.unregisterComponent( metadata.getName() );
+                }
             }
-            finally
+        }
+        catch ( IOException ex )
+        {
+            // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
+            // fragments, SCR must log an error message with the Log Service, if present, and continue.
+
+            log( LogService.LOG_ERROR, "Problem reading descriptor entry '" + descriptorLocation + "'", null, ex );
+        }
+        catch ( Exception ex )
+        {
+            log( LogService.LOG_ERROR, "General problem with descriptor entry '" + descriptorLocation + "'", null, ex );
+        }
+        finally
+        {
+            if ( stream != null )
             {
-                if ( stream != null )
+                try
+                {
+                    stream.close();
+                }
+                catch ( IOException ignore )
                 {
-                    try
-                    {
-                        stream.close();
-                    }
-                    catch ( IOException ignore )
-                    {
-                    }
                 }
             }
         }

Added: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java?rev=799652&view=auto
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java (added)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java Fri Jul 31 16:10:59 2009
@@ -0,0 +1,183 @@
+/*
+ * 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.felix.scr.impl;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+
+public class BundleComponentActivatorTest extends TestCase
+{
+
+    /**
+     * Test that an empty array is returned for a null bundle.
+     */
+    public void test_findDescriptors_withNullBundle()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( null, "foo.xml" );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for a null location.
+     */
+    public void test_findDescriptors_withNullLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new MockBundle(), null );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for an empty location.
+     */
+    public void test_findDescriptors_withEmptyLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new MockBundle(), "" );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that an empty array is returned for a location containing only blanks.
+     */
+    public void test_findDescriptors_withBlankLocation()
+    {
+        final URL[] urls = BundleComponentActivator.findDescriptors( new MockBundle(), " " );
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor array length", 0, urls.length );
+    }
+
+    /**
+     * Test that when using a non wilcarded location, getResource() will be used (for legacy reasons) and the returned
+     * array is the one returned by bundle method call.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withNonWildcardLocation()
+        throws MalformedURLException
+    {
+        URL descriptor = new URL( "file:foo.xml" );
+        final Bundle bundle = EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.getResource( "/some/location/foo.xml" ) ).andReturn( descriptor );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] urls = BundleComponentActivator.findDescriptors( bundle, "/some/location/foo.xml" );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", urls );
+        assertEquals( "Descriptor length", 1, urls.length );
+        assertEquals( "Descriptor", descriptor, urls[ 0 ] );
+    }
+
+    public void findDescriptors_withWildcardLocation( final String location,
+                                                      final String path,
+                                                      final String filePattern )
+        throws MalformedURLException
+    {
+        final URL[] urls = new URL[]
+            {
+                new URL( "file:foo1.xml" ),
+                new URL( "file:foo2.xml" )
+            };
+        final Enumeration de = new Vector( Arrays.asList( urls ) ).elements();
+        final Bundle bundle = EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( path, filePattern, false ) ).andReturn( de );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( bundle, location );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", urls.length, actualUrls.length );
+        for( int i = 0; i < actualUrls.length; i++ )
+        {
+            assertEquals( "Descriptor", urls[ i ], actualUrls[ i ] );
+        }
+    }
+
+    /**
+     * Test that when using "*.xml", path will be root of bundle "/" and file pattern will be "*.xml".
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation01()
+        throws MalformedURLException
+    {
+        findDescriptors_withWildcardLocation( "*.xml", "/", "*.xml" );
+    }
+
+    /**
+     * Test that when using "/foo/*.xml", path will be "/foo/" and file pattern will be "*.xml".
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation02()
+        throws MalformedURLException
+    {
+        findDescriptors_withWildcardLocation( "/foo/*.xml", "/foo", "*.xml" );
+    }
+
+    /**
+     * Test that in case that no resources are found (bundle return null) an empty array is returned.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation_nullEnum()
+        throws MalformedURLException
+    {
+        final Bundle bundle = EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( "/", "*.xml", false ) ).andReturn( null );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( bundle, "*.xml" );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", 0, actualUrls.length );
+    }
+
+    /**
+     * Test that in case that no resources are found (bundle return empty enum) an empty array is returned.
+     *
+     * @throws MalformedURLException unexpected
+     */
+    public void test_findDescriptors_withWildcardLocation_emptyEnum()
+        throws MalformedURLException
+    {
+        final Bundle bundle = EasyMock.createNiceMock( Bundle.class );
+        EasyMock.expect( bundle.findEntries( "/", "*.xml", false ) ).andReturn( new Vector().elements() );
+
+        EasyMock.replay( new Object[]{ bundle } );
+        final URL[] actualUrls = BundleComponentActivator.findDescriptors( bundle, "*.xml" );
+        EasyMock.verify( new Object[]{ bundle } );
+
+        assertNotNull( "Descriptor array is not null", actualUrls );
+        assertEquals( "Descriptor length", 0, actualUrls.length );
+    }
+
+}
\ No newline at end of file

Propchange: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/BundleComponentActivatorTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url