incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bdelacre...@apache.org
Subject svn commit: r1520565 - in /sling/trunk/bundles/scripting: api/ api/src/main/java/org/apache/sling/scripting/api/ core/ core/src/main/java/org/apache/sling/scripting/core/impl/ core/src/test/java/org/apache/sling/scripting/core/impl/
Date Fri, 06 Sep 2013 12:57:28 GMT
Author: bdelacretaz
Date: Fri Sep  6 12:57:27 2013
New Revision: 1520565

URL: http://svn.apache.org/r1520565
Log:
SLING-3038 - take context service property into account for BindingsValuesProvider services

Added:
    sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvidersByContext.java
    sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
    sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ContextBvpCollector.java
    sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
Removed:
    sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProviderCustomizer.java
Modified:
    sling/trunk/bundles/scripting/api/pom.xml
    sling/trunk/bundles/scripting/core/pom.xml
    sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java

Modified: sling/trunk/bundles/scripting/api/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/pom.xml?rev=1520565&r1=1520564&r2=1520565&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/api/pom.xml (original)
+++ sling/trunk/bundles/scripting/api/pom.xml Fri Sep  6 12:57:27 2013
@@ -63,7 +63,7 @@
                             javax.script
                         </Import-Package>
                         <Export-Package>
-                            org.apache.sling.scripting.api;version=2.1.0
+                            org.apache.sling.scripting.api;version=2.2.0
                         </Export-Package>
                     </instructions>
                 </configuration>

Added: sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvidersByContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvidersByContext.java?rev=1520565&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvidersByContext.java
(added)
+++ sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvidersByContext.java
Fri Sep  6 12:57:27 2013
@@ -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.sling.scripting.api;
+
+import java.util.Collection;
+
+import javax.script.ScriptEngineFactory;
+
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+
+/** Provides {@link BindingsValuesProvider} for specific contexts, based on
+ *  their "context" service property.
+ *  */
+public interface BindingsValuesProvidersByContext {
+    
+    /** The name of the multi-value service property that defines the context(s) to which

+     *  a BindingsValuesProvider applies. 
+     */
+    String CONTEXT = "context";
+    
+    /** The default value of the CONTEXT service property, used for compatibility with
+     *  previous versions of this bundle that didn't require it. 
+     */
+    String DEFAULT_CONTEXT = "request";
+    
+    /** Retrieve the current {@link BindingsValuesProvider} for
+     *  the supplied ScriptEngineFactory and context.
+     *  
+     * @param scriptEngineFactory metadata of the ScriptEngine that's being used
+     * @param context Only BindingsValuesProviders that have this value in their CONTEXT
+     *          service property are considered. For backwards compatibility, BindingsValuesProviders
+     *          which do not have a CONTEXT service property are considered to have CONTEXT=request.
 
+     * @return The returned Collection of BindingsValuesProvider is sorted
+     *          so as to give preference to more specific BindingsValuesProvider
+     *          over those that match a compatible.javax.script.name ScriptEngineFactory
property,
+     *          for example, in the same way that the SlingScriptAdapterFactory did before
+     *          this service was implemented. 
+     */
+    Collection<BindingsValuesProvider> getBindingsValuesProviders(
+            ScriptEngineFactory scriptEngineFactory,
+            String context);
+}

Modified: sling/trunk/bundles/scripting/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/pom.xml?rev=1520565&r1=1520564&r2=1520565&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/core/pom.xml (original)
+++ sling/trunk/bundles/scripting/core/pom.xml Fri Sep  6 12:57:27 2013
@@ -36,6 +36,13 @@
         Sling Scripting core functionality
     </description>
 
+    <properties>
+        <exam.version>3.0.3</exam.version>
+        <url.version>1.5.2</url.version>
+        <bundle.file.name>${basedir}/target/${project.build.finalName}.jar</bundle.file.name>
+        <sling.java.version>6</sling.java.version>
+    </properties>
+    
     <scm>
         <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/scripting/core</connection>
         <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/scripting/core</developerConnection>
@@ -67,6 +74,25 @@
                     </instructions>
                 </configuration>
             </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                  <execution>
+                    <goals>
+                      <goal>integration-test</goal>
+                      <goal>verify</goal>
+                    </goals>
+                  </execution>
+                </executions>
+                <configuration>
+                    <systemProperties>
+                        <property>
+                            <name>bundle.file.name</name>
+                            <value>${bundle.file.name}</value>
+                        </property>
+                    </systemProperties>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
     <reporting>
@@ -110,17 +136,21 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.scripting.api</artifactId>
-            <version>2.1.4</version>
+            <version>2.1.5-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
 
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
+            <version>4.2.0</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
+            <version>4.2.0</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
@@ -155,5 +185,39 @@
         	<version>2.0.6</version>
         	<scope>test</scope>
         </dependency>
-    </dependencies>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <version>${url.version}</version>
+            <scope>test</scope>
+        </dependency>
+ 
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>3.2.2</version>
+            <scope>test</scope>
+        </dependency>
+     </dependencies>
 </project>

Added: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java?rev=1520565&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
(added)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
Fri Sep  6 12:57:27 2013
@@ -0,0 +1,193 @@
+/*
+ * 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.sling.scripting.core.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.script.ScriptEngineFactory;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
+import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Our default {@link BindingsValuesProvidersByContext} implementation */
+@Component
+@Service
+public class BindingsValuesProvidersByContextImpl implements BindingsValuesProvidersByContext,
ServiceTrackerCustomizer {
+
+    private final Map<String, ContextBvpCollector> customizers = new HashMap<String,
ContextBvpCollector>();
+    public static final String [] DEFAULT_CONTEXT_ARRAY = new String [] { DEFAULT_CONTEXT
};
+    
+    private ServiceTracker bvpTracker;
+    private ServiceTracker mapsTracker;
+    private BundleContext bundleContext;
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+    private final List<ServiceReference> pendingRefs = new ArrayList<ServiceReference>();
+    
+    @Reference
+    private SlingScriptEngineManager scriptEngineManager;
+    
+    private abstract class ContextLoop {
+        Object apply(ServiceReference ref) {
+            final Object service = bundleContext.getService(ref);
+            if(service != null) {
+                for(String context : getContexts(ref)) {
+                    ContextBvpCollector c = customizers.get(context);
+                    if(c == null) {
+                        synchronized (BindingsValuesProvidersByContextImpl.this) {
+                            c = new ContextBvpCollector(bundleContext);
+                            customizers.put(context, c);
+                        }
+                    }
+                    applyInContext(c);
+                }
+            }
+            return service;
+        }
+        
+        protected abstract void applyInContext(ContextBvpCollector c);
+    };
+    
+    @Activate
+    public void activate(ComponentContext ctx) {
+        bundleContext = ctx.getBundleContext();
+        
+        synchronized (pendingRefs) {
+            for(ServiceReference ref : pendingRefs) {
+                addingService(ref);
+            }
+            pendingRefs.clear();
+        }
+        
+        bvpTracker = new ServiceTracker(bundleContext, BindingsValuesProvider.class.getName(),
this);
+        bvpTracker.open();
+        
+        // Map services can also be registered to provide bindings
+        mapsTracker = new ServiceTracker(bundleContext, Map.class.getName(), this);
+        mapsTracker.open();
+    }
+    
+    @Deactivate
+    public void deactivate(ComponentContext ctx) {
+        bvpTracker.close();
+        mapsTracker.close();
+        bundleContext = null;
+    }
+    
+    public Collection<BindingsValuesProvider> getBindingsValuesProviders(
+            ScriptEngineFactory scriptEngineFactory,
+            String context) {
+        final List<BindingsValuesProvider> results = new ArrayList<BindingsValuesProvider>();
+        if(context == null) {
+            context = DEFAULT_CONTEXT;
+        }
+        final ContextBvpCollector bvpc = customizers.get(context);
+        if(bvpc == null) {
+            logger.debug("no BindingsValuesProviderCustomizer available for context '{}'",
context);
+            return results;
+        }
+        
+        results.addAll(bvpc.getGenericBindingsValuesProviders().values());
+        logger.debug("Generic BindingsValuesProviders added for engine {}: {}", scriptEngineFactory.getNames(),
results);
+
+        // we load the compatible language ones first so that the most specific
+        // overrides these
+        Map<Object, Object> factoryProps = scriptEngineManager.getProperties(scriptEngineFactory);
+        if (factoryProps != null) {
+            String[] compatibleLangs = PropertiesUtil.toStringArray(factoryProps.get("compatible.javax.script.name"),
new String[0]);
+            for (final String name : compatibleLangs) {
+                final Map<Object, BindingsValuesProvider> langProviders = bvpc.getLangBindingsValuesProviders().get(name);
+                if (langProviders != null) {
+                    results.addAll(langProviders.values());
+                }
+            }
+            logger.debug("Compatible BindingsValuesProviders added for engine {}: {}", scriptEngineFactory.getNames(),
results);
+        }
+
+        for (final String name : scriptEngineFactory.getNames()) {
+            final Map<Object, BindingsValuesProvider> langProviders = bvpc.getLangBindingsValuesProviders().get(name);
+            if (langProviders != null) {
+                results.addAll(langProviders.values());
+            }
+        }
+        logger.debug("All BindingsValuesProviders added for engine {}: {}", scriptEngineFactory.getNames(),
results);
+
+        return results;
+    }
+    
+    private String [] getContexts(ServiceReference reference) {
+        return PropertiesUtil.toStringArray(reference.getProperty(CONTEXT), new String[]
{ DEFAULT_CONTEXT });
+    }
+
+    public Object addingService(final ServiceReference reference) {
+        if(bundleContext == null) {
+            synchronized (pendingRefs) {
+                pendingRefs.add(reference);
+            }
+            return null;
+        }
+        return new ContextLoop() {
+            @Override
+            protected void applyInContext(ContextBvpCollector c) {
+                c.addingService(reference);
+            }
+        }.apply(reference);
+    }
+
+    public void modifiedService(final ServiceReference reference, final Object service) {
+        new ContextLoop() {
+            @Override
+            protected void applyInContext(ContextBvpCollector c) {
+                c.modifiedService(reference, service);
+            }
+        }.apply(reference);
+    }
+
+    public void removedService(final ServiceReference reference, final Object service) {
+        if(bundleContext == null) {
+            synchronized (pendingRefs) {
+                pendingRefs.remove(reference);
+            }
+            return;
+        }
+        new ContextLoop() {
+            @Override
+            protected void applyInContext(ContextBvpCollector c) {
+                c.removedService(reference, service);
+            }
+        }.apply(reference);
+    }
+}

Added: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ContextBvpCollector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ContextBvpCollector.java?rev=1520565&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ContextBvpCollector.java
(added)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ContextBvpCollector.java
Fri Sep  6 12:57:27 2013
@@ -0,0 +1,130 @@
+/*
+ * 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.sling.scripting.core.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/** Keeps track of {@link BindingsValuesProvider} for a single context */
+class ContextBvpCollector {
+    
+    /** list of service property values which indicate 'any' script engine */
+    private static final List<String> ANY_ENGINE = Arrays.asList("*", "ANY");
+
+    private final BundleContext bundleContext;
+    
+    /**
+     * The BindingsValuesProvider impls which apply to all languages. Keys are serviceIds.
+     */
+    private final Map<Object, BindingsValuesProvider> genericBindingsValuesProviders;
+
+    /**
+     * The BindingsValuesProvider impls which apply to a specific language.
+     */
+    private final Map<String, Map<Object, BindingsValuesProvider>> langBindingsValuesProviders;
+    
+    ContextBvpCollector(BundleContext bc) {
+        bundleContext = bc;
+        genericBindingsValuesProviders = new ConcurrentHashMap<Object, BindingsValuesProvider>();
+        langBindingsValuesProviders = new ConcurrentHashMap<String, Map<Object, BindingsValuesProvider>>();
+    }
+
+    @SuppressWarnings("unchecked")
+    public Object addingService(final ServiceReference ref) {
+        final String[] engineNames = PropertiesUtil
+                .toStringArray(ref.getProperty(ScriptEngine.NAME), new String[0]);
+        final Object serviceId = ref.getProperty(Constants.SERVICE_ID);
+        Object service = bundleContext.getService(ref);
+        if (service != null) {
+            if (service instanceof Map) {
+                service = new MapWrappingBindingsValuesProvider((Map<String, Object>)
service);
+            }
+            if (engineNames.length == 0) {
+                genericBindingsValuesProviders.put(serviceId, (BindingsValuesProvider) service);
+            } else if (engineNames.length == 1 && ANY_ENGINE.contains(engineNames[0].toUpperCase()))
{
+                genericBindingsValuesProviders.put(serviceId, (BindingsValuesProvider) service);
+            } else {
+                for (String engineName : engineNames) {
+                    Map<Object, BindingsValuesProvider> langProviders = langBindingsValuesProviders.get(engineName);
+                    if (langProviders == null) {
+                        langProviders = new ConcurrentHashMap<Object, BindingsValuesProvider>();
+                        langBindingsValuesProviders.put(engineName, langProviders);
+                    }
+
+                    langProviders.put(serviceId, (BindingsValuesProvider) service);
+                }
+            }
+        }
+        return service;
+    }
+
+    public void modifiedService(final ServiceReference ref, final Object service) {
+        removedService(ref, service);
+        addingService(ref);
+    }
+
+    public void removedService(final ServiceReference ref, final Object service) {
+        Object serviceId = ref.getProperty(Constants.SERVICE_ID);
+        if (genericBindingsValuesProviders.remove(serviceId) == null) {
+            for (Map<Object, BindingsValuesProvider> coll : langBindingsValuesProviders.values())
{
+                if (coll.remove(service) != null) {
+                    return;
+                }
+            }
+        }
+    }
+    
+    Map<Object, BindingsValuesProvider> getGenericBindingsValuesProviders() {
+        return genericBindingsValuesProviders;
+    }
+
+    Map<String, Map<Object, BindingsValuesProvider>> getLangBindingsValuesProviders()
{
+        return langBindingsValuesProviders;
+    }
+
+    private class MapWrappingBindingsValuesProvider implements BindingsValuesProvider {
+
+        private Map<String,Object> map;
+
+        MapWrappingBindingsValuesProvider(Map<String, Object> map) {
+            this.map = map;
+        }
+
+        public void addBindings(Bindings bindings) {
+            for (String key : map.keySet()) {
+                bindings.put(key, map.get(key));
+            }
+        }
+        
+        @Override
+        public String toString() {
+            return map.toString();
+        }
+    }
+
+}
\ No newline at end of file

Modified: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java?rev=1520565&r1=1520564&r2=1520565&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
(original)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
Fri Sep  6 12:57:27 2013
@@ -16,13 +16,10 @@
  */
 package org.apache.sling.scripting.core.impl;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 
 import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
@@ -32,16 +29,11 @@ import org.apache.felix.scr.annotations.
 import org.apache.sling.api.adapter.AdapterFactory;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.commons.mime.MimeTypeProvider;
-import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
 import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.service.component.ComponentContext;
-import org.osgi.util.tracker.ServiceTracker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * AdapterFactory that adapts Resources to the DefaultSlingScript servlet, which
@@ -59,19 +51,10 @@ import org.slf4j.LoggerFactory;
 })
 public class SlingScriptAdapterFactory implements AdapterFactory, MimeTypeProvider {
 
-    private final Logger log = LoggerFactory.getLogger(SlingScriptAdapterFactory.class);
-
     private BundleContext bundleContext;
 
-    /**
-     * The service tracker for BindingsValuesProvider impls
-     */
-    private ServiceTracker bindingsValuesProviderTracker;
-
-    /**
-     * The service tracker for Map impls with scripting bindings
-     */
-    private ServiceTracker mapBindingsValuesProviderTracker;
+    /** The context string to use to select BindingsValuesProviders */
+    public static final String BINDINGS_CONTEXT = BindingsValuesProvidersByContext.DEFAULT_CONTEXT;
 
     /**
      * The service cache for script execution.
@@ -85,9 +68,10 @@ public class SlingScriptAdapterFactory i
     private SlingScriptEngineManager scriptEngineManager;
     
     /**
-     * The customizer for BindingsValuesProvider service trackers
+     * The BindingsValuesProviderTracker
      */
-    private BindingsValuesProviderCustomizer bindingsValuesProviderCustomizer;
+    @Reference
+    private BindingsValuesProvidersByContext bindingsValuesProviderTracker;
 
     // ---------- AdapterFactory -----------------------------------------------
 
@@ -100,7 +84,8 @@ public class SlingScriptAdapterFactory i
 
         ScriptEngine engine = scriptEngineManager.getEngineByExtension(ext);
         if (engine != null) {
-            Collection<BindingsValuesProvider> bindingsValuesProviders = getBindingsValuesProviders(engine.getFactory());
+            final Collection<BindingsValuesProvider> bindingsValuesProviders = 
+                    bindingsValuesProviderTracker.getBindingsValuesProviders(engine.getFactory(),
BINDINGS_CONTEXT);
             // unchecked cast
             return (AdapterType) new DefaultSlingScript(this.bundleContext,
                     resource, engine, bindingsValuesProviders, this.serviceCache);
@@ -161,62 +146,12 @@ public class SlingScriptAdapterFactory i
 
     protected void activate(ComponentContext context) {
         bundleContext = context.getBundleContext();
-        bindingsValuesProviderCustomizer = new BindingsValuesProviderCustomizer(bundleContext);
-
-        this.bindingsValuesProviderTracker = new ServiceTracker(this.bundleContext, BindingsValuesProvider.class.getName(),
bindingsValuesProviderCustomizer);
-        this.bindingsValuesProviderTracker.open();
-
-        try {
-            Filter filter = this.bundleContext.createFilter(String.format("(&(objectclass=%s)(javax.script.name=*))",
-                    Map.class.getName()));
-
-            this.mapBindingsValuesProviderTracker = new ServiceTracker(this.bundleContext,
filter, bindingsValuesProviderCustomizer);
-            this.mapBindingsValuesProviderTracker.open();
-        } catch (InvalidSyntaxException e) {
-            log.warn("Unable to create ServiceTracker for Map-based script bindiings", e);
-        }
         this.serviceCache = new ServiceCache(this.bundleContext);
     }
 
     protected void deactivate(ComponentContext context) {
         this.serviceCache.dispose();
         this.serviceCache = null;
-
-        if (this.bindingsValuesProviderTracker != null) {
-            this.bindingsValuesProviderTracker.close();
-            this.bindingsValuesProviderTracker = null;
-        }
-        if (this.mapBindingsValuesProviderTracker != null) {
-            this.mapBindingsValuesProviderTracker.close();
-            this.mapBindingsValuesProviderTracker = null;
-        }
         this.bundleContext = null;
     }
-
-    private Collection<BindingsValuesProvider> getBindingsValuesProviders(ScriptEngineFactory
scriptEngineFactory) {
-        final List<BindingsValuesProvider> results = new ArrayList<BindingsValuesProvider>();
-        results.addAll(bindingsValuesProviderCustomizer.getGenericBindingsValuesProviders().values());
-
-        // we load the compatible language ones first so that the most specific
-        // overrides these
-        Map<Object, Object> factoryProps = scriptEngineManager.getProperties(scriptEngineFactory);
-        if (factoryProps != null) {
-            String[] compatibleLangs = PropertiesUtil.toStringArray(factoryProps.get("compatible.javax.script.name"),
new String[0]);
-            for (final String name : compatibleLangs) {
-                final Map<Object, BindingsValuesProvider> langProviders = bindingsValuesProviderCustomizer.getLangBindingsValuesProviders().get(name);
-                if (langProviders != null) {
-                    results.addAll(langProviders.values());
-                }
-            }
-        }
-
-        for (final String name : scriptEngineFactory.getNames()) {
-            final Map<Object, BindingsValuesProvider> langProviders = bindingsValuesProviderCustomizer.getLangBindingsValuesProviders().get(name);
-            if (langProviders != null) {
-                results.addAll(langProviders.values());
-            }
-        }
-
-        return results;
-    }
 }

Added: sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java?rev=1520565&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
(added)
+++ sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
Fri Sep  6 12:57:27 2013
@@ -0,0 +1,256 @@
+/*
+ * 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.sling.scripting.core.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.ops4j.pax.exam.CoreOptions.bundle;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.when;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+@RunWith(PaxExam.class)
+public class BindingsValuesProvidersByContextIT {
+    
+    @Inject
+    private BindingsValuesProvidersByContext bvpProvider;
+    
+    @Inject
+    private BundleContext bundleContext;
+    
+    private final List<ServiceRegistration> regs = new ArrayList<ServiceRegistration>();
+    
+    @org.ops4j.pax.exam.Configuration
+    public Option[] config() {
+        final String localRepo = System.getProperty("maven.repo.local", "");
+
+        final String bundleFileName = System.getProperty( "bundle.file.name", "BUNDLE_FILE_NOT_SET"
);
+        final File bundleFile = new File( bundleFileName );
+        if(!bundleFile.canRead()) {
+            throw new IllegalArgumentException( "Cannot read from bundle file " + bundleFile.getAbsolutePath());
+        }
+        
+        return options(
+                when( localRepo.length() > 0 ).useOptions(
+                        systemProperty("org.ops4j.pax.url.mvn.localRepository").value(localRepo)
+                ),
+                provision(
+                        bundle(bundleFile.toURI().toString()),
+                        mavenBundle("org.apache.felix", "org.apache.felix.scr", "1.6.2"),
+                        
+                        mavenBundle("org.apache.sling", "org.apache.sling.scripting.api",
"2.1.5-SNAPSHOT"),
+                        mavenBundle("org.apache.sling", "org.apache.sling.api", "2.4.2"),
+                        mavenBundle("org.apache.sling", "org.apache.sling.commons.mime",
"2.1.4"),
+                        mavenBundle("org.apache.sling", "org.apache.sling.commons.osgi",
"2.2.0"),
+                        
+                        mavenBundle("org.mortbay.jetty", "servlet-api-2.5", "6.1.14")
+                ),
+                junitBundles()
+                );
+    }
+    
+    @Before
+    public void setup() {
+        regs.clear();
+    }
+    
+    @After
+    public void cleanup() {
+        for(ServiceRegistration reg : regs) {
+            reg.unregister();
+        }
+    }
+    
+
+    private Dictionary<String, Object> getProperties(String context, String engineName)
{
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        if(context != null) {
+            props.put(BindingsValuesProvidersByContext.CONTEXT, context.split(","));
+        }
+        if(engineName != null) {
+            props.put(ScriptEngine.NAME, engineName);
+        }
+        return props;
+    }
+
+    private void addBVP(final String id, String context, String engineName) {
+        final BindingsValuesProvider bvp = new BindingsValuesProvider() {
+            @Override
+            public String toString() {
+                return id;
+            }
+            
+            public void addBindings(Bindings b) {
+            }
+        };
+        
+        regs.add(bundleContext.registerService(BindingsValuesProvider.class.getName(), bvp,
getProperties(context, engineName)));
+    }
+    
+    private void addMap(final String id, String context, String engineName) {
+        final Map<String, Object> result = new HashMap<String, Object>() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public String toString() {
+                return "M_" + id;
+            }
+        };
+        
+        regs.add(bundleContext.registerService(Map.class.getName(), result, getProperties(context,
engineName)));
+    }
+    
+    private ScriptEngineFactory factory(final String engineName) {
+        return new ScriptEngineFactory() {
+            
+            public ScriptEngine getScriptEngine() {
+                return null;
+            }
+            
+            public String getProgram(String... arg0) {
+                return null;
+            }
+            
+            public Object getParameter(String arg0) {
+                return null;
+            }
+            
+            public String getOutputStatement(String arg0) {
+                return null;
+            }
+            
+            public List<String> getNames() {
+                final List<String> names = new ArrayList<String>();
+                names.add(engineName);
+                return names;
+            }
+            
+            public List<String> getMimeTypes() {
+                return null;
+            }
+            
+            public String getMethodCallSyntax(String arg0, String arg1, String... arg2) {
+                return null;
+            }
+            
+            public String getLanguageVersion() {
+                return null;
+            }
+            
+            public String getLanguageName() {
+                return null;
+            }
+            
+            public List<String> getExtensions() {
+                return null;
+            }
+            
+            public String getEngineVersion() {
+                return null;
+            }
+            
+            public String getEngineName() {
+                return engineName;
+            }
+        };
+    }
+    
+    private String asString(Collection<?> data) {
+        final StringBuilder sb = new StringBuilder();
+        for(Object o : data) {
+            if(sb.length() > 0) {
+                sb.append(",");
+            }
+            sb.append(o.toString());
+        }
+        return sb.toString();
+    }
+    
+    @Test
+    public void testAny() {
+        addBVP("one", null, "js");
+        addBVP("two", null, null);
+        addBVP("three", null, "*");
+        addBVP("four", null, "ANY");
+        addBVP("five", null, "basic");
+        
+        assertEquals("four,three,two,one", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
null)));
+        assertEquals("four,three,two,five", asString(bvpProvider.getBindingsValuesProviders(factory("basic"),
null)));
+        assertEquals("four,three,two", asString(bvpProvider.getBindingsValuesProviders(factory("other"),
null)));
+    }
+    
+    @Test
+    public void testContextsAndLanguages() {
+        addBVP("foo", null, "js");
+        addBVP("bar", null, null);
+        addBVP("r1", "request", "js");
+        addBVP("r2", "request",  null);
+        addBVP("o1", "other", "js");
+        addBVP("o2", "other", null);
+        addBVP("o3", "other,request", null);
+        addBVP("python", "python", "python");
+        assertEquals("o3,r2,bar,r1,foo", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
"request")));
+        assertEquals("With default content", "o3,r2,bar,r1,foo", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
null)));
+        assertEquals("o3,o2,o1", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
"other")));
+        assertEquals("", asString(bvpProvider.getBindingsValuesProviders(factory("js"), "unusedContext")));
+    }
+    
+    @Test
+    public void testMapsAndBvps() {
+        addBVP("foo", null, "js");
+        addMap("bar", null, null);
+        addMap("r1", "request", "js");
+        addMap("r2", "request",  null);
+        addMap("o1", "other", "js");
+        addBVP("o2", "other", null);
+        addMap("o3", "other,request", null);
+        addMap("python", "python", "python");
+        assertEquals("M_o3,M_r2,M_bar,M_r1,foo", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
"request")));
+        assertEquals("With default content", "M_o3,M_r2,M_bar,M_r1,foo", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
null)));
+        assertEquals("M_o3,o2,M_o1", asString(bvpProvider.getBindingsValuesProviders(factory("js"),
"other")));
+        assertEquals("", asString(bvpProvider.getBindingsValuesProviders(factory("js"), "unusedContext")));
+    }
+}
\ No newline at end of file



Mime
View raw message