You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2014/10/13 13:54:43 UTC

svn commit: r1631356 [5/9] - in /sling/trunk: ./ testing/jcr-mock/ testing/jcr-mock/src/ testing/jcr-mock/src/main/ testing/jcr-mock/src/main/java/ testing/jcr-mock/src/main/java/org/ testing/jcr-mock/src/main/java/org/apache/ testing/jcr-mock/src/main...

Added: sling/trunk/testing/sling-mock/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/pom.xml?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/pom.xml (added)
+++ sling/trunk/testing/sling-mock/pom.xml Mon Oct 13 11:54:39 2014
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>22</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.testing.sling-mock</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling Testing Sling Mock</name>
+    <description>Mock implementation of selected Sling APIs.</description>
+
+    <properties>
+        <sling.java.version>6</sling.java.version>
+    </properties>
+
+    <dependencies>
+  
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.jcr-mock</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
+            <version>0.3.1-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.api</artifactId>
+            <version>1.1.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.models.impl</artifactId>
+            <version>1.1.0</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.4.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.resourceresolver</artifactId>
+            <version>1.1.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.api</artifactId>
+            <version>2.2.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.resource</artifactId>
+            <version>2.3.6</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.mime</artifactId>
+            <version>2.1.4</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.json</artifactId>
+            <version>2.0.6</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.classloader</artifactId>
+            <version>1.3.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.settings</artifactId>
+            <version>1.2.2</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2.1</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.5</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.8.3</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.9-RC2</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>3.0.20100224</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <version>2.0</version>
+            <scope>compile</scope>
+        </dependency>
+    
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.9.5</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+  
+    <build>
+        <plugins>
+    
+          <!-- Publish test artifact -->
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>test-jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+    
+          <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <extensions>true</extensions>
+          </plugin>
+    
+          <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-scr-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>generate-scr-scrdescriptor</id>
+                <goals>
+                  <goal>scr</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+    
+        </plugins>
+    </build>
+  
+</project>

Propchange: sling/trunk/testing/sling-mock/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/pom.xml
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,44 @@
+/*
+ * 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.testing.mock.sling;
+
+import javax.jcr.Repository;
+
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.testing.mock.jcr.MockJcr;
+import org.apache.sling.testing.mock.sling.spi.ResourceResolverTypeAdapter;
+
+/**
+ * Resource resolver type adapter for JCR Mocks implementation.
+ */
+class JcrMockResourceResolverAdapter implements ResourceResolverTypeAdapter {
+
+    @Override
+    public ResourceResolverFactory newResourceResolverFactory() {
+        return null;
+    }
+
+    @Override
+    public SlingRepository newSlingRepository() {
+        Repository repository = MockJcr.newRepository();
+        return new MockSlingRepository(repository);
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/JcrMockResourceResolverAdapter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,81 @@
+/*
+ * 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.testing.mock.sling;
+
+import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.api.adapter.AdapterManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Mock {@link AdapterManager} implementation.
+ */
+class MockAdapterManager implements AdapterManager {
+
+    /**
+     * OSGi bundle context to detect all services that implement
+     * {@link AdapterFactory}.
+     */
+    private BundleContext bundleContext;
+
+    /**
+     * Returns the adapted <code>adaptable</code> or <code>null</code> if the
+     * object cannot be adapted.
+     */
+    @Override
+    public <AdapterType> AdapterType getAdapter(final Object adaptable, final Class<AdapterType> type) {
+
+        // iterate over all adapter factories and try to adapt the object
+        if (this.bundleContext != null) {
+            try {
+                ServiceReference[] references = bundleContext
+                        .getServiceReferences(AdapterFactory.class.getName(), null);
+                for (ServiceReference serviceReference : references) {
+                    AdapterFactory adapterFactory = (AdapterFactory) bundleContext.getService(serviceReference);
+                    AdapterType instance = adapterFactory.getAdapter(adaptable, type);
+                    if (instance != null) {
+                        return instance;
+                    }
+                }
+            } catch (InvalidSyntaxException ex) {
+                throw new RuntimeException("Unable to get adapter factories.", ex);
+            }
+        }
+
+        // no matching adapter factory found
+        return null;
+    }
+
+    /**
+     * Sets bundle context.
+     * @param bundleContext Bundle context
+     */
+    public void setBundleContext(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    /**
+     * Removes bundle context reference.
+     */
+    public void clearBundleContext() {
+        this.bundleContext = null;
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockAdapterManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,117 @@
+/*
+ * 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.testing.mock.sling;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderFactory;
+import org.apache.sling.resourceresolver.impl.CommonResourceResolverFactoryImpl;
+import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
+import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
+import org.apache.sling.resourceresolver.impl.helper.ResourceResolverContext;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Mock {@link ResourceResolver} implementation. Simulates OSGi environment and
+ * intatiates real Sling ResourceResolver and JCR implementation, but with a
+ * mocked JCR repository implementation underneath.
+ */
+class MockJcrResourceResolverFactory implements ResourceResolverFactory {
+
+    private final SlingRepository slingRepository;
+
+    public MockJcrResourceResolverFactory(final SlingRepository repository) {
+        this.slingRepository = repository;
+    }
+
+    @Override
+    public ResourceResolver getResourceResolver(final Map<String, Object> authenticationInfo) throws LoginException {
+        // setup mock OSGi environment
+        Dictionary<String, Object> resourceProviderFactoryProps = new Hashtable<String, Object>();
+        resourceProviderFactoryProps.put(Constants.SERVICE_VENDOR, "sling-mock");
+        resourceProviderFactoryProps.put(Constants.SERVICE_DESCRIPTION, "sling-mock");
+        resourceProviderFactoryProps.put("resource.resolver.manglenamespaces", true);
+        ComponentContext componentContext = MockOsgi.newComponentContext(resourceProviderFactoryProps);
+
+        // setup mocked JCR environment
+        componentContext.getBundleContext()
+                .registerService(SlingRepository.class.getName(), this.slingRepository, null);
+
+        // setup real sling JCR resource provider implementation for use in
+        // mocked context
+        JcrResourceProviderFactory jcrResourceProviderFactory = new JcrResourceProviderFactory();
+        MockOsgi.injectServices(jcrResourceProviderFactory, componentContext.getBundleContext());
+        MockOsgi.activate(jcrResourceProviderFactory, componentContext.getBundleContext(),
+                ImmutableMap.<String, Object> of());
+        ResourceProvider resourceProvider = jcrResourceProviderFactory
+                .getAdministrativeResourceProvider(new HashMap<String, Object>());
+        Dictionary<Object, Object> resourceProviderProps = new Hashtable<Object, Object>();
+        resourceProviderProps.put(ResourceProvider.ROOTS, new String[] { "/" });
+        componentContext.getBundleContext().registerService(ResourceProvider.class.getName(), resourceProvider,
+                resourceProviderProps);
+        ServiceReference resourceProviderServiceReference = componentContext.getBundleContext().getServiceReference(
+                ResourceProvider.class.getName());
+
+        // setup real sling resource resolver implementation for use in mocked
+        // context
+        MockResourceResolverFactoryActivator activator = new MockResourceResolverFactoryActivator();
+        activator.bindResourceProvider(resourceProvider,
+                getServiceReferenceProperties(resourceProviderServiceReference));
+        activator.activate(componentContext);
+        CommonResourceResolverFactoryImpl commonFactoryImpl = new CommonResourceResolverFactoryImpl(activator);
+        ResourceResolverContext context = new ResourceResolverContext(true, null, new ResourceAccessSecurityTracker());
+        ResourceResolverImpl resourceResolver = new ResourceResolverImpl(commonFactoryImpl, context);
+        return resourceResolver;
+    }
+
+    private Map<String, Object> getServiceReferenceProperties(final ServiceReference serviceReference) {
+        Map<String, Object> props = new HashMap<String, Object>();
+        String[] keys = serviceReference.getPropertyKeys();
+        for (String key : keys) {
+            props.put(key, serviceReference.getProperty(key));
+        }
+        return props;
+    }
+
+    @Override
+    public ResourceResolver getAdministrativeResourceResolver(final Map<String, Object> authenticationInfo)
+            throws LoginException {
+        return getResourceResolver(authenticationInfo);
+    }
+
+    // part of Sling API 2.7
+    public ResourceResolver getServiceResourceResolver(final Map<String, Object> authenticationInfo)
+            throws LoginException {
+        return getResourceResolver(authenticationInfo);
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockJcrResourceResolverFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java Mon Oct 13 11:54:39 2014
@@ -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.sling.testing.mock.sling;
+
+import java.util.Map;
+
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceProviderFactory;
+import org.apache.sling.resourceresolver.impl.ResourceResolverFactoryActivator;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Overrides some behavior of {@link ResourceResolverFactoryActivator} to allow
+ * usage in mocking.
+ */
+class MockResourceResolverFactoryActivator extends ResourceResolverFactoryActivator {
+
+    // make public
+    @Override
+    public void activate(final ComponentContext componentContext) {
+        super.activate(componentContext);
+    }
+
+    // make public
+    @Override
+    public void bindResourceProviderFactory(final ResourceProviderFactory provider, final Map<String, Object> props) {
+        super.bindResourceProviderFactory(provider, props);
+    }
+
+    // make public
+    @Override
+    public void bindResourceProvider(final ResourceProvider provider, final Map<String, Object> props) {
+        super.bindResourceProvider(provider, props);
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockResourceResolverFactoryActivator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,167 @@
+/*
+ * 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.testing.mock.sling;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.adapter.SlingAdaptable;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse;
+import org.apache.sling.testing.mock.sling.spi.ResourceResolverTypeAdapter;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Factory for mock Sling objects.
+ */
+public final class MockSling {
+
+    /**
+     * Default resource resolver type is {@link ResourceResolverType#RESOURCERESOLVER_MOCK}.
+     */
+    public static final ResourceResolverType DEFAULT_RESOURCERESOLVER_TYPE = ResourceResolverType.RESOURCERESOLVER_MOCK;
+
+    private static final ThreadsafeMockAdapterManagerWrapper ADAPTER_MANAGER = new ThreadsafeMockAdapterManagerWrapper();
+    static {
+        // register mocked adapter manager
+        SlingAdaptable.setAdapterManager(ADAPTER_MANAGER);
+    }
+
+    private MockSling() {
+        // static methods only
+    }
+
+    /**
+     * Creates new sling resource resolver factory instance.
+     * @param type Type of underlying repository.
+     * @return Resource resolver factory instance
+     */
+    public static ResourceResolverFactory newResourceResolverFactory(final ResourceResolverType type) {
+        ResourceResolverTypeAdapter adapter = getResourceResolverTypeAdapter(type);
+        ResourceResolverFactory factory = adapter.newResourceResolverFactory();
+        if (factory == null) {
+            SlingRepository repository = adapter.newSlingRepository();
+            if (repository == null) {
+                throw new RuntimeException("Adapter neither provides resource resolver factory nor sling repository.");
+            }
+            factory = new MockJcrResourceResolverFactory(repository);
+        }
+        return factory;
+    }
+
+    private static ResourceResolverTypeAdapter getResourceResolverTypeAdapter(final ResourceResolverType type) {
+        try {
+            Class clazz = Class.forName(type.getResourceResolverTypeAdapterClass());
+            return (ResourceResolverTypeAdapter) clazz.newInstance();
+        } catch (ClassNotFoundException ex) {
+            throw new RuntimeException("Unable to instantiate resourcer resolver: "
+                    + type.getResourceResolverTypeAdapterClass()
+                    + (type.getArtifactCoordinates() != null ? "Make sure this maven dependency is included: "
+                            + type.getArtifactCoordinates() : ""), ex);
+        } catch (InstantiationException ex) {
+            throw new RuntimeException("Unable to instantiate resourcer resolver: "
+                    + type.getResourceResolverTypeAdapterClass()
+                    + (type.getArtifactCoordinates() != null ? "Make sure this maven dependency is included: "
+                            + type.getArtifactCoordinates() : ""), ex);
+        } catch (IllegalAccessException ex) {
+            throw new RuntimeException("Unable to instantiate resourcer resolver: "
+                    + type.getResourceResolverTypeAdapterClass()
+                    + (type.getArtifactCoordinates() != null ? "Make sure this maven dependency is included: "
+                            + type.getArtifactCoordinates() : ""), ex);
+        }
+    }
+
+    /**
+     * Creates new sling resource resolver factory instance using
+     * {@link #DEFAULT_RESOURCERESOLVER_TYPE}.
+     * @return Resource resolver factory instance
+     */
+    public static ResourceResolverFactory newResourceResolverFactory() {
+        return newResourceResolverFactory(DEFAULT_RESOURCERESOLVER_TYPE);
+    }
+
+    /**
+     * Creates new sling resource resolver instance.
+     * @param type Type of underlying repository.
+     * @return Resource resolver instance
+     */
+    public static ResourceResolver newResourceResolver(final ResourceResolverType type) {
+        ResourceResolverFactory factory = newResourceResolverFactory(type);
+        try {
+            return factory.getResourceResolver(null);
+        } catch (LoginException ex) {
+            throw new RuntimeException("Mock resource resolver factory implementation seems to require login.", ex);
+        }
+    }
+
+    /**
+     * Creates new sling resource resolver instance using
+     * {@link #DEFAULT_RESOURCERESOLVER_TYPE}.
+     * @return Resource resolver instance
+     */
+    public static ResourceResolver newResourceResolver() {
+        return newResourceResolver(DEFAULT_RESOURCERESOLVER_TYPE);
+    }
+
+    /**
+     * Creates a new sling script helper instance.
+     * @param request Request
+     * @param response Response
+     * @param bundleContext Bundle context
+     * @return Sling script helper instance
+     */
+    public static SlingScriptHelper newSlingScriptHelper(final SlingHttpServletRequest request,
+            final SlingHttpServletResponse response, final BundleContext bundleContext) {
+        return new MockSlingScriptHelper(request, response, bundleContext);
+    }
+
+    /**
+     * Creates a new sling script helper instance using
+     * {@link #DEFAULT_RESOURCERESOLVER_TYPE} for the resource resolver.
+     * @return Sling script helper instance
+     */
+    public static SlingScriptHelper newSlingScriptHelper() {
+        SlingHttpServletRequest request = new MockSlingHttpServletRequest(newResourceResolver());
+        SlingHttpServletResponse response = new MockSlingHttpServletResponse();
+        BundleContext bundleContext = MockOsgi.newBundleContext();
+        return newSlingScriptHelper(request, response, bundleContext);
+    }
+
+    /**
+     * Set bundle context for adapter manager. From this bundle context the
+     * adapter factories are detected.
+     * @param bundleContext OSGi bundle context
+     */
+    public static void setAdapterManagerBundleContext(final BundleContext bundleContext) {
+        ADAPTER_MANAGER.setBundleContext(bundleContext);
+    }
+
+    /**
+     * Clear adapter registrations..
+     */
+    public static void clearAdapterManagerBundleContext() {
+        ADAPTER_MANAGER.clearBundleContext();
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSling.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,112 @@
+/*
+ * 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.testing.mock.sling;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.testing.mock.jcr.MockJcr;
+
+/**
+ * Mock {@link SlingRepository} implementation.
+ */
+class MockSlingRepository implements SlingRepository {
+
+    private final Repository delegate;
+
+    public MockSlingRepository(final Repository delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public Session loginAdministrative(final String workspace) throws RepositoryException {
+        return login();
+    }
+
+    @Override
+    public Session loginService(final String subServiceName, final String workspace) throws LoginException,
+            RepositoryException {
+        return login();
+    }
+
+    @Override
+    public String getDefaultWorkspace() {
+        return MockJcr.DEFAULT_WORKSPACE;
+    }
+
+    // delegated methods
+    @Override
+    public String[] getDescriptorKeys() {
+        return this.delegate.getDescriptorKeys();
+    }
+
+    @Override
+    public boolean isStandardDescriptor(final String key) {
+        return this.delegate.isStandardDescriptor(key);
+    }
+
+    @Override
+    public boolean isSingleValueDescriptor(final String key) {
+        return this.delegate.isSingleValueDescriptor(key);
+    }
+
+    @Override
+    public Value getDescriptorValue(final String key) {
+        return this.delegate.getDescriptorValue(key);
+    }
+
+    @Override
+    public Value[] getDescriptorValues(final String key) {
+        return this.delegate.getDescriptorValues(key);
+    }
+
+    @Override
+    public String getDescriptor(final String key) {
+        return this.delegate.getDescriptor(key);
+    }
+
+    @Override
+    public Session login(final Credentials credentials, final String workspaceName) throws LoginException,
+            NoSuchWorkspaceException, RepositoryException {
+        return this.delegate.login(credentials, workspaceName);
+    }
+
+    @Override
+    public Session login(final Credentials credentials) throws LoginException, RepositoryException {
+        return this.delegate.login(credentials);
+    }
+
+    @Override
+    public Session login(final String workspaceName) throws LoginException, NoSuchWorkspaceException,
+            RepositoryException {
+        return this.delegate.login(workspaceName);
+    }
+
+    @Override
+    public Session login() throws LoginException, RepositoryException {
+        return this.delegate.login();
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingRepository.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,163 @@
+/*
+ * 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.testing.mock.sling;
+
+import java.lang.reflect.Array;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.InvalidServiceFilterSyntaxException;
+import org.apache.sling.api.scripting.SlingScript;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Mock {@link SlingScriptHelper} implementation.
+ */
+class MockSlingScriptHelper implements SlingScriptHelper {
+
+    private final SlingHttpServletRequest request;
+    private final SlingHttpServletResponse response;
+    private final BundleContext bundleContext;
+
+    public MockSlingScriptHelper(final SlingHttpServletRequest request, final SlingHttpServletResponse response,
+            final BundleContext bundleContext) {
+        this.request = request;
+        this.response = response;
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public SlingHttpServletRequest getRequest() {
+        return this.request;
+    }
+
+    @Override
+    public SlingHttpServletResponse getResponse() {
+        return this.response;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <ServiceType> ServiceType getService(final Class<ServiceType> serviceType) {
+        ServiceReference serviceReference = this.bundleContext.getServiceReference(serviceType.getName());
+        if (serviceReference != null) {
+            return (ServiceType) this.bundleContext.getService(serviceReference);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <ServiceType> ServiceType[] getServices(final Class<ServiceType> serviceType, final String filter) {
+        try {
+            ServiceReference[] serviceReferences = this.bundleContext.getServiceReferences(serviceType.getName(),
+                    filter);
+            if (serviceReferences != null) {
+                ServiceType[] services = (ServiceType[]) Array.newInstance(serviceType, serviceReferences.length);
+                for (int i = 0; i < serviceReferences.length; i++) {
+                    services[i] = (ServiceType) this.bundleContext.getService(serviceReferences[i]);
+                }
+                return services;
+            } else {
+                return (ServiceType[]) ArrayUtils.EMPTY_OBJECT_ARRAY;
+            }
+        } catch (InvalidSyntaxException ex) {
+            throw new InvalidServiceFilterSyntaxException(filter, ex.getMessage(), ex);
+        }
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public void dispose() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final String path, final RequestDispatcherOptions requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final String path, final String requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final String path) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final Resource resource) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final Resource resource, final String requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void forward(final Resource resource, final RequestDispatcherOptions requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SlingScript getScript() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final String path, final RequestDispatcherOptions requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final String path, final String requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final String path) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final Resource resource) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final Resource resource, final String requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void include(final Resource resource, final RequestDispatcherOptions requestDispatcherOptions) {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/MockSlingScriptHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java Mon Oct 13 11:54:39 2014
@@ -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.sling.testing.mock.sling;
+
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.testing.mock.sling.spi.ResourceResolverTypeAdapter;
+import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
+import org.apache.sling.testing.resourceresolver.MockResourceResolverFactoryOptions;
+
+/**
+ * Resource resolver type adapter for Sling Resource Resolver Mock implementation.
+ */
+class RRMockMockResourceResolverAdapter implements ResourceResolverTypeAdapter {
+
+    private final MockResourceResolverFactoryOptions options;
+
+    /**
+     * Constructor
+     */
+    public RRMockMockResourceResolverAdapter() {
+        options = new MockResourceResolverFactoryOptions();
+        options.setMangleNamespacePrefixes(true);
+    }
+
+    @Override
+    public ResourceResolverFactory newResourceResolverFactory() {
+        return new MockResourceResolverFactory(options);
+    }
+
+    @Override
+    public SlingRepository newSlingRepository() {
+        return null;
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/RRMockMockResourceResolverAdapter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,86 @@
+/*
+ * 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.testing.mock.sling;
+
+/**
+ * The resource resolver mock implementation supports different underlying
+ * repository implementations.
+ */
+public enum ResourceResolverType {
+
+    /**
+     * Uses Sling "resourceresolver-mock" implementation, no underlying JCR
+     * repository.
+     * <ul>
+     * <li>Simulates an In-Memory resource tree, does not provide adaptions to
+     * JCR.</li>
+     * <li>You can use it to make sure the code you want to test does not
+     * contain references to JCR API.</li>
+     * <li>Behaves slightly different from JCR resource mapping e.g. handling
+     * binary and date values.</li>
+     * <li>This resource resolver type is very fast.</li>
+     * </ul>
+     */
+    RESOURCERESOLVER_MOCK(RRMockMockResourceResolverAdapter.class.getName(), null),
+
+    /**
+     * Uses a simple JCR "in-memory" mock as underlying repository.
+     * <ul>
+     * <li>Uses the real Sling Resource Resolver and JCR Resource mapping
+     * implementation.</li>
+     * <li>The mock JCR implementation from Apache Sling is used.</li>
+     * <li>It supports the most important, but not all JCR features. Extended
+     * features like Versioning, Eventing, Search, Transaction handling etc. are
+     * not supported.</li>
+     * <li>This resource resolver type is quite fast.</li>
+     * </ul>
+     */
+    JCR_MOCK(JcrMockResourceResolverAdapter.class.getName(), null),
+
+    /**
+     * Uses a real JCR Jackrabbit repository.
+     * <ul>
+     * <li>Uses the real Sling Resource Resolver and JCR Resource mapping
+     * implementation.</li>
+     * <li>The JCR repository is started on first access, this may take some
+     * seconds.</li>
+     * <li>Beware: The repository is not cleared for each unit test, so make
+     * sure us use a unique node path for each unit test.</li>
+     * </ul>
+     */
+    JCR_JACKRABBIT("org.apache.sling.testing.mock.sling.jackrabbit.JackrabbitMockResourceResolverAdapter",
+            "org.apache.sling:org.apache.sling.testing.sling-mock-jackrabbit");
+
+    private final String resourceResolverTypeAdapterClass;
+    private final String artifactCoordinates;
+
+    private ResourceResolverType(final String resourceResolverTypeAdapterClass, final String artifactCoordinates) {
+        this.resourceResolverTypeAdapterClass = resourceResolverTypeAdapterClass;
+        this.artifactCoordinates = artifactCoordinates;
+    }
+
+    String getResourceResolverTypeAdapterClass() {
+        return this.resourceResolverTypeAdapterClass;
+    }
+
+    String getArtifactCoordinates() {
+        return this.artifactCoordinates;
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ResourceResolverType.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,61 @@
+/*
+ * 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.testing.mock.sling;
+
+import org.apache.sling.api.adapter.AdapterManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Wrapper for {@link MockAdapterManager} which makes sure multiple unit tests
+ * running in parallel do not get in conflict with each other. Instead, a
+ * different {@link MockAdapterManager} is used per thread.
+ */
+class ThreadsafeMockAdapterManagerWrapper implements AdapterManager {
+
+    private static final ThreadLocal<MockAdapterManager> THREAD_LOCAL = new ThreadLocal<MockAdapterManager>() {
+        @Override
+        protected MockAdapterManager initialValue() {
+            return new MockAdapterManager();
+        }
+    };
+
+    @Override
+    public <AdapterType> AdapterType getAdapter(final Object adaptable, final Class<AdapterType> type) {
+        MockAdapterManager adapterManager = THREAD_LOCAL.get();
+        return adapterManager.getAdapter(adaptable, type);
+    }
+
+    /**
+     * Sets bundle context.
+     * @param bundleContext Bundle context
+     */
+    public void setBundleContext(final BundleContext bundleContext) {
+        MockAdapterManager adapterManager = THREAD_LOCAL.get();
+        adapterManager.setBundleContext(bundleContext);
+    }
+
+    /**
+     * Removes bundle context reference.
+     */
+    public void clearBundleContext() {
+        MockAdapterManager adapterManager = THREAD_LOCAL.get();
+        adapterManager.clearBundleContext();
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/ThreadsafeMockAdapterManagerWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,108 @@
+/*
+ * 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.testing.mock.sling.builder;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Helper class for building test content in the resource hierarchy with as less
+ * boilerplate code as possible.
+ */
+public class ContentBuilder {
+
+    static final String DUMMY_TEMPLATE = "/apps/sample/templates/template1";
+
+    protected final ResourceResolver resourceResolver;
+
+    /**
+     * @param resourceResolver Resource resolver
+     */
+    public ContentBuilder(ResourceResolver resourceResolver) {
+        this.resourceResolver = resourceResolver;
+    }
+
+    /**
+     * Create resource. If parent resource(s) do not exist they are created
+     * automatically using <code>nt:unstructured</code> nodes.
+     * @param path Page path
+     * @return Resource object
+     */
+    public final Resource resource(String path) {
+        return resource(path, ValueMap.EMPTY);
+    }
+
+    /**
+     * Create resource. If parent resource(s) do not exist they are created
+     * automatically using <code>nt:unstructured</code> nodes.
+     * @param path Page path
+     * @param properties Properties for resource.
+     * @return Resource object
+     */
+    public final Resource resource(String path, Map<String, Object> properties) {
+        String parentPath = ResourceUtil.getParent(path);
+        Resource parentResource = ensureResourceExists(parentPath);
+        String name = ResourceUtil.getName(path);
+        try {
+            return resourceResolver.create(parentResource, name, properties);
+        } catch (PersistenceException ex) {
+            throw new RuntimeException("Unable to create page at " + path, ex);
+        }
+    }
+
+    /**
+     * Ensure that a resource exists at the given path. If not, it is created
+     * using <code>nt:unstructured</code> node type.
+     * @param path Resource path
+     * @return Resource at path (existing or newly created)
+     */
+    protected final Resource ensureResourceExists(String path) {
+        if (StringUtils.isEmpty(path) || StringUtils.equals(path, "/")) {
+            return resourceResolver.getResource("/");
+        }
+        Resource resource = resourceResolver.getResource(path);
+        if (resource != null) {
+            return resource;
+        }
+        String parentPath = ResourceUtil.getParent(path);
+        String name = ResourceUtil.getName(path);
+        Resource parentResource = ensureResourceExists(parentPath);
+        try {
+            resource = resourceResolver.create(
+                    parentResource,
+                    name,
+                    ImmutableMap.<String, Object> builder()
+                            .put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED).build());
+            resourceResolver.commit();
+            return resource;
+        } catch (PersistenceException ex) {
+            throw new RuntimeException("Unable to create resource at " + path, ex);
+        }
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/ContentBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+/**
+ * Content builder for creating test content.
+ */
+package org.apache.sling.testing.mock.sling.builder;

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/builder/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,77 @@
+/*
+ * 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.testing.mock.sling.context;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.testing.mock.sling.MockSling;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+
+/**
+ * Create resolve resolver instance and initialize it depending on it's type.
+ */
+final class ContextResourceResolverFactory {
+
+    private ContextResourceResolverFactory() {
+        // static methods only
+    }
+
+    public static ResourceResolver initializeResourceResolver(final ResourceResolverType resourceResolverType) {
+        try {
+            ResourceResolver resourceResolver = MockSling.newResourceResolver(resourceResolverType);
+
+            switch (resourceResolverType) {
+            case JCR_MOCK:
+                initializeJcrMock(resourceResolver);
+                break;
+            case JCR_JACKRABBIT:
+                initializeJcrJackrabbit(resourceResolver);
+                break;
+            case RESOURCERESOLVER_MOCK:
+                initializeResourceResolverMock(resourceResolver);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid resource resolver type: " + resourceResolverType);
+            }
+
+            return resourceResolver;
+        } catch (Throwable ex) {
+            throw new RuntimeException("Unable to initialize " + resourceResolverType + " resource resolver.", ex);
+        }
+    }
+
+    private static void initializeJcrMock(final ResourceResolver resourceResolver) throws RepositoryException {
+        // register default namespaces
+        NamespaceRegistry namespaceRegistry = resourceResolver.adaptTo(Session.class).getWorkspace()
+                .getNamespaceRegistry();
+        namespaceRegistry.registerNamespace("sling", "http://sling.apache.org/jcr/sling/1.0");
+    }
+
+    private static void initializeJcrJackrabbit(final ResourceResolver resourceResolver) {
+        // TODO: register sling node types
+    }
+
+    private static void initializeResourceResolverMock(final ResourceResolver resourceResolver) {
+        // nothing to do
+    }
+
+}

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Oct 13 11:54:39 2014
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/ContextResourceResolverFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java?rev=1631356&view=auto
==============================================================================
--- sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java (added)
+++ sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.java Mon Oct 13 11:54:39 2014
@@ -0,0 +1,401 @@
+/*
+ * 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.testing.mock.sling.context;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.models.impl.FirstImplementationPicker;
+import org.apache.sling.models.impl.injectors.BindingsInjector;
+import org.apache.sling.models.impl.injectors.ChildResourceInjector;
+import org.apache.sling.models.impl.injectors.OSGiServiceInjector;
+import org.apache.sling.models.impl.injectors.RequestAttributeInjector;
+import org.apache.sling.models.impl.injectors.ResourcePathInjector;
+import org.apache.sling.models.impl.injectors.ResourceResolverInjector;
+import org.apache.sling.models.impl.injectors.SelfInjector;
+import org.apache.sling.models.impl.injectors.SlingObjectInjector;
+import org.apache.sling.models.impl.injectors.ValueMapInjector;
+import org.apache.sling.models.spi.ImplementationPicker;
+import org.apache.sling.models.spi.Injector;
+import org.apache.sling.settings.SlingSettingsService;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.apache.sling.testing.mock.sling.MockSling;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.builder.ContentBuilder;
+import org.apache.sling.testing.mock.sling.loader.ContentLoader;
+import org.apache.sling.testing.mock.sling.services.MockMimeTypeService;
+import org.apache.sling.testing.mock.sling.services.MockModelAdapterFactory;
+import org.apache.sling.testing.mock.sling.services.MockSlingSettingService;
+import org.apache.sling.testing.mock.sling.servlet.MockRequestPathInfo;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Defines Sling context objects with lazy initialization. Should not be used
+ * directly but via the {@link org.apache.sling.testing.mock.sling.junit.SlingContext} JUnit
+ * rule.
+ */
+public class SlingContextImpl {
+
+    // default to publish instance run mode
+    static final Set<String> DEFAULT_RUN_MODES = ImmutableSet.<String> builder().add("publish").build();
+
+    protected MockModelAdapterFactory modelAdapterFactory;
+    protected ResourceResolverType resourceResolverType;
+    protected ComponentContext componentContext;
+    protected ResourceResolver resourceResolver;
+    protected MockSlingHttpServletRequest request;
+    protected MockSlingHttpServletResponse response;
+    protected SlingScriptHelper slingScriptHelper;
+    protected ContentLoader contentLoader;
+    protected ContentBuilder contentBuilder;
+
+    /**
+     * @param resourceResolverType Resource resolver type
+     */
+    protected void setResourceResolverType(final ResourceResolverType resourceResolverType) {
+        this.resourceResolverType = resourceResolverType;
+    }
+
+    /**
+     * Setup actions before test method execution
+     */
+    protected void setUp() {
+        MockSling.setAdapterManagerBundleContext(bundleContext());
+        registerDefaultServices();
+    }
+
+    /**
+     * Default services that should be available for every unit test
+     */
+    protected void registerDefaultServices() {
+
+        // adapter factories
+        modelAdapterFactory = new MockModelAdapterFactory(componentContext());
+        registerService(AdapterFactory.class, modelAdapterFactory);
+
+        // sling models injectors
+        registerService(Injector.class, new BindingsInjector());
+        registerService(Injector.class, new ChildResourceInjector());
+        OSGiServiceInjector osgiServiceInjector = new OSGiServiceInjector();
+        osgiServiceInjector.activate(componentContext());
+        registerService(Injector.class, osgiServiceInjector);
+        registerService(Injector.class, new RequestAttributeInjector());
+        registerService(Injector.class, new ResourcePathInjector());
+        registerService(Injector.class, new ResourceResolverInjector());
+        registerService(Injector.class, new SelfInjector());
+        registerService(Injector.class, new SlingObjectInjector());
+        registerService(Injector.class, new ValueMapInjector());
+
+        // sling models implementation pickers
+        registerService(ImplementationPicker.class, new FirstImplementationPicker());
+
+        // other services
+        registerService(SlingSettingsService.class, new MockSlingSettingService(DEFAULT_RUN_MODES));
+        registerService(MimeTypeService.class, new MockMimeTypeService());
+    }
+
+    /**
+     * Teardown actions after test method execution
+     */
+    protected void tearDown() {
+
+        if (this.resourceResolver != null) {
+            // revert potential unsaved changes in resource resolver/JCR session
+            this.resourceResolver.revert();
+            Session session = this.resourceResolver.adaptTo(Session.class);
+            if (session != null) {
+                try {
+                    session.refresh(false);
+                } catch (RepositoryException ex) {
+                    // ignore
+                }
+            }
+        }
+
+        this.modelAdapterFactory = null;
+        this.componentContext = null;
+        this.resourceResolver = null;
+        this.request = null;
+        this.response = null;
+        this.slingScriptHelper = null;
+        this.contentLoader = null;
+        this.contentBuilder = null;
+
+        MockSling.clearAdapterManagerBundleContext();
+    }
+
+    /**
+     * @return Resource resolver type
+     */
+    public final ResourceResolverType resourceResolverType() {
+        return this.resourceResolverType;
+    }
+
+    /**
+     * @return OSGi component context
+     */
+    public final ComponentContext componentContext() {
+        if (this.componentContext == null) {
+            this.componentContext = MockOsgi.newComponentContext();
+        }
+        return this.componentContext;
+    }
+
+    /**
+     * @return OSGi Bundle context
+     */
+    public final BundleContext bundleContext() {
+        return componentContext().getBundleContext();
+    }
+
+    /**
+     * @return Resource resolver
+     */
+    public final ResourceResolver resourceResolver() {
+        if (this.resourceResolver == null) {
+            this.resourceResolver = createMockResourceResolver();
+        }
+        return this.resourceResolver;
+    }
+    
+    protected ResourceResolver createMockResourceResolver() {
+        return ContextResourceResolverFactory.initializeResourceResolver(resourceResolverType());
+    }
+
+    /**
+     * @return Sling request
+     */
+    public final MockSlingHttpServletRequest request() {
+        if (this.request == null) {
+            this.request = new MockSlingHttpServletRequest(this.resourceResolver());
+
+            // initialize sling bindings
+            SlingBindings bindings = new SlingBindings();
+            bindings.put(SlingBindings.REQUEST, this.request);
+            bindings.put(SlingBindings.RESPONSE, response());
+            bindings.put(SlingBindings.SLING, slingScriptHelper());
+            this.request.setAttribute(SlingBindings.class.getName(), bindings);
+        }
+        return this.request;
+    }
+
+    /**
+     * @return Request path info
+     */
+    public final MockRequestPathInfo requestPathInfo() {
+        return (MockRequestPathInfo) request().getRequestPathInfo();
+    }
+
+    /**
+     * @return Sling response
+     */
+    public final MockSlingHttpServletResponse response() {
+        if (this.response == null) {
+            this.response = new MockSlingHttpServletResponse();
+        }
+        return this.response;
+    }
+
+    /**
+     * @return Sling script helper
+     */
+    public final SlingScriptHelper slingScriptHelper() {
+        if (this.slingScriptHelper == null) {
+            this.slingScriptHelper = MockSling.newSlingScriptHelper(this.request(), this.response(),
+                    this.bundleContext());
+        }
+        return this.slingScriptHelper;
+    }
+
+    /**
+     * @return Content loader
+     */
+    public ContentLoader load() {
+        if (this.contentLoader == null) {
+            this.contentLoader = new ContentLoader(resourceResolver(), bundleContext());
+        }
+        return this.contentLoader;
+    }
+
+    /**
+     * @return Content builder for building test content
+     */
+    public ContentBuilder create() {
+        if (this.contentBuilder == null) {
+            this.contentBuilder = new ContentBuilder(resourceResolver());
+        }
+        return this.contentBuilder;
+    }
+
+    /**
+     * Registers a service in the mocked OSGi environment.
+     * @param service Service instance
+     * @return Registered service instance
+     */
+    public final <T> T registerService(final T service) {
+        return registerService(null, service, null);
+    }
+
+    /**
+     * Registers a service in the mocked OSGi environment.
+     * @param serviceClass Service class
+     * @param service Service instance
+     * @return Registered service instance
+     */
+    public final <T> T registerService(final Class<T> serviceClass, final T service) {
+        return registerService(serviceClass, service, null);
+    }
+
+    /**
+     * Registers a service in the mocked OSGi environment.
+     * @param serviceClass Service class
+     * @param service Service instance
+     * @param properties Service properties (optional)
+     * @return Registered service instance
+     */
+    public final <T> T registerService(final Class<T> serviceClass, final T service, final Map<String, Object> properties) {
+        Dictionary<String, Object> serviceProperties = null;
+        if (properties != null) {
+            serviceProperties = new Hashtable<String, Object>(properties);
+        }
+        bundleContext().registerService(serviceClass != null ? serviceClass.getName() : null, service,
+                serviceProperties);
+        return service;
+    }
+
+    /**
+     * Injects dependencies, activates and registers a service in the mocked
+     * OSGi environment.
+     * @param service Service instance
+     * @return Registered service instance
+     */
+    public final <T> T registerInjectActivateService(final T service) {
+        return registerInjectActivateService(service, ImmutableMap.<String, Object> of());
+    }
+
+    /**
+     * Injects dependencies, activates and registers a service in the mocked
+     * OSGi environment.
+     * @param service Service instance
+     * @param properties Service properties (optional)
+     * @return Registered service instance
+     */
+    public final <T> T registerInjectActivateService(final T service, final Map<String, Object> properties) {
+        MockOsgi.injectServices(service, bundleContext());
+        MockOsgi.activate(service, bundleContext(), properties);
+        registerService(null, service, null);
+        return service;
+    }
+
+    /**
+     * Lookup a single service
+     * @param serviceType The type (interface) of the service.
+     * @return The service instance, or null if the service is not available.
+     */
+    public final <ServiceType> ServiceType getService(final Class<ServiceType> serviceType) {
+        return slingScriptHelper().getService(serviceType);
+    }
+
+    /**
+     * Lookup one or several services
+     * @param serviceType The type (interface) of the service.
+     * @param filter An optional filter (LDAP-like, see OSGi spec)
+     * @return The services object or null.
+     * @throws InvalidServiceFilterSyntaxException If the <code>filter</code>
+     *             string is not a valid OSGi service filter string.
+     */
+    public final <ServiceType> ServiceType[] getServices(final Class<ServiceType> serviceType, final String filter) {
+        return slingScriptHelper().getServices(serviceType, filter);
+    }
+
+    /**
+     * @return Current resource
+     */
+    public final Resource currentResource() {
+        return request().getResource();
+    }
+
+    /**
+     * Set current resource in request.
+     * @param resourcePath Resource path
+     * @return Current resource
+     */
+    public final Resource currentResource(String resourcePath) {
+        if (resourcePath != null) {
+            Resource resource = resourceResolver().getResource(resourcePath);
+            if (resource == null) {
+                throw new IllegalArgumentException("Resource does not exist: " + resourcePath);
+            }
+            return currentResource(resource);
+        } else {
+            return currentResource((Resource) null);
+        }
+    }
+
+    /**
+     * Set current resource in request.
+     * @param resource Resource
+     * @return Current resource
+     */
+    public final Resource currentResource(Resource resource) {
+        request().setResource(resource);
+        return resource;
+    }
+
+    /**
+     * Scan classpaths for given package name (and sub packages) to scan for and
+     * register all classes with @Model annotation.
+     * @param packageName Java package name
+     */
+    public final void addModelsForPackage(String packageName) {
+        this.modelAdapterFactory.addModelsForPackage(packageName);
+    }
+
+    /**
+     * Set current run mode(s).
+     * @param runModes Run mode(s).
+     */
+    public final void runMode(String... runModes) {
+        Set<String> newRunModes = ImmutableSet.<String> builder().add(runModes).build();
+        ServiceReference ref = bundleContext().getServiceReference(SlingSettingsService.class.getName());
+        if (ref != null) {
+            MockSlingSettingService slingSettings = (MockSlingSettingService) bundleContext().getService(ref);
+            slingSettings.setRunModes(newRunModes);
+        }
+    }
+
+}