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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/SlingContextImpl.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/SlingContextImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

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

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/context/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/context/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContext.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContext.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContext.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContext.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,207 @@
+/*
+ * 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.junit;
+
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.context.SlingContextImpl;
+import org.junit.rules.ExternalResource;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit rule for setting up and tearing down Sling context objects for unit
+ * tests.
+ */
+public final class SlingContext extends SlingContextImpl implements TestRule {
+
+    private final SlingContextCallback setUpCallback;
+    private final SlingContextCallback tearDownCallback;
+    private final ResourceResolverType resourceResolverType;
+    private final TestRule delegate;
+
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     */
+    public SlingContext() {
+        this(null, null, null);
+    }
+
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     * @param resourceResolverType Resource resolver type.
+     */
+    public SlingContext(final ResourceResolverType resourceResolverType) {
+        this(null, null, resourceResolverType);
+    }
+
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     * @param setUpCallback Allows the application to register an own callback
+     *            function that is called after the built-in setup rules are
+     *            executed.
+     */
+    public SlingContext(final SlingContextCallback setUpCallback) {
+        this(setUpCallback, null, null);
+    }
+
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     * @param setUpCallback Allows the application to register an own callback
+     *            function that is called after the built-in setup rules are
+     *            executed.
+     * @param resourceResolverType Resource resolver type.
+     */
+    public SlingContext(final SlingContextCallback setUpCallback, final 
ResourceResolverType resourceResolverType) {
+        this(setUpCallback, null, resourceResolverType);
+    }
+
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     * @param setUpCallback Allows the application to register an own callback
+     *            function that is called after the built-in setup rules are
+     *            executed.
+     * @param tearDownCallback Allows the application to register an own
+     *            callback function that is called before the built-in teardown
+     *            rules are executed.
+     */
+    public SlingContext(final SlingContextCallback setUpCallback, final 
SlingContextCallback tearDownCallback) {
+        this(setUpCallback, tearDownCallback, null);
+    }
+    
+    /**
+     * Initialize Sling context.
+     * <p>
+     * If context is initialized with:
+     * </p>
+     * <ul>
+     * <li>No resource resolver type - default is used
+     * {@link MockSling#DEFAULT_RESOURCERESOLVER_TYPE}.</li>
+     * <li>One resource resolver type - exactly this is used.</li>
+     * <li>More than one: all unit test methods are executed for all resource
+     * resolver types using {@link ListGenerator}.</li>
+     * </ul>
+     * @param setUpCallback Allows the application to register an own callback
+     *            function that is called after the built-in setup rules are
+     *            executed.
+     * @param tearDownCallback Allows the application to register an own
+     *            callback function that is called before the built-in teardown
+     *            rules are executed.
+     * @param resourceResolverType Resource resolver type.
+     */
+    public SlingContext(final SlingContextCallback setUpCallback, final 
SlingContextCallback tearDownCallback,
+            final ResourceResolverType resourceResolverType) {
+
+        this.setUpCallback = setUpCallback;
+        this.tearDownCallback = tearDownCallback;
+        this.resourceResolverType = resourceResolverType;
+
+        // user default rule that directly executes each test method once
+        setResourceResolverType(this.resourceResolverType);
+        this.delegate = new ExternalResource() {
+            @Override
+            protected void before() {
+                SlingContext.this.setUp();
+                SlingContext.this.executeSetUpCallback();
+            }
+
+            @Override
+            protected void after() {
+                SlingContext.this.executeTearDownCallback();
+                SlingContext.this.tearDown();
+            }
+        };
+    }
+
+    @Override
+    public Statement apply(final Statement base, final Description 
description) {
+        return this.delegate.apply(base, description);
+    }
+
+    private void executeSetUpCallback() {
+        if (this.setUpCallback != null) {
+            try {
+                this.setUpCallback.execute(this);
+            } catch (Throwable ex) {
+                throw new RuntimeException("Executing setup callback failed.", 
ex);
+            }
+        }
+    }
+
+    private void executeTearDownCallback() {
+        if (this.tearDownCallback != null) {
+            try {
+                this.tearDownCallback.execute(this);
+            } catch (Throwable ex) {
+                throw new RuntimeException("Executing setup callback failed.", 
ex);
+            }
+        }
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContext.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/junit/SlingContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContextCallback.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContextCallback.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContextCallback.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContextCallback.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,37 @@
+/*
+ * 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.junit;
+
+import java.io.IOException;
+
+import org.apache.sling.api.resource.PersistenceException;
+
+/**
+ * Callback-interface for application-specific setup and teardown operations to
+ * customize the {@link AemContext} JUnit rule.
+ */
+public interface SlingContextCallback {
+
+    /**
+     * Execute callback action
+     * @param context Sling context
+     */
+    void execute(SlingContext context) throws IOException, 
PersistenceException;
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/SlingContextCallback.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/junit/SlingContextCallback.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/package-info.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/package-info.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/package-info.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/package-info.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Rule for providing easy access to Sling context in JUnit tests.
+ */
+package org.apache.sling.testing.mock.sling.junit;
+

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/junit/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/junit/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/ContentLoader.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/ContentLoader.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/ContentLoader.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/ContentLoader.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,586 @@
+/*
+ * 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.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+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.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.json.jcr.JsonItemWriter;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Imports JSON data and binary data into Sling resource hierarchy.
+ */
+public final class ContentLoader {
+
+    private static final String REFERENCE = "jcr:reference:";
+    private static final String PATH = "jcr:path:";
+    private static final String CONTENTTYPE_OCTET_STREAM = 
"application/octet-stream";
+
+    private static final Set<String> IGNORED_NAMES = 
ImmutableSet.of(JcrConstants.JCR_PRIMARYTYPE,
+            JcrConstants.JCR_MIXINTYPES, JcrConstants.JCR_UUID, 
JcrConstants.JCR_BASEVERSION,
+            JcrConstants.JCR_PREDECESSORS, JcrConstants.JCR_SUCCESSORS, 
JcrConstants.JCR_CREATED, "jcr:checkedOut");
+
+    private final ResourceResolver resourceResolver;
+    private final BundleContext bundleContext;
+    private final DateFormat calendarFormat;
+
+    /**
+     * @param resourceResolver Resource resolver
+     */
+    public ContentLoader(ResourceResolver resourceResolver) {
+        this(resourceResolver, null);
+    }
+
+    /**
+     * @param resourceResolver Resource resolver
+     * @param bundleContext Bundle context
+     */
+    public ContentLoader(ResourceResolver resourceResolver, BundleContext 
bundleContext) {
+        this.resourceResolver = resourceResolver;
+        this.bundleContext = bundleContext;
+        this.calendarFormat = new 
SimpleDateFormat(JsonItemWriter.ECMA_DATE_FORMAT, 
JsonItemWriter.DATE_FORMAT_LOCALE);
+    }
+
+    /**
+     * Import content of JSON file into repository.
+     * @param classpathResource Classpath resource URL for JSON content
+     * @param parentResource Parent resource
+     * @param childName Name of child resource to create with JSON content
+     * @return Resource
+     */
+    public Resource json(String classpathResource, Resource parentResource, 
String childName) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return json(is, parentResource, childName);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import content of JSON file into repository. Auto-creates parent
+     * hierarchies as nt:unstrucured nodes if missing.
+     * @param classpathResource Classpath resource URL for JSON content
+     * @param destPath Path to import the JSON content to
+     * @return Resource
+     */
+    public Resource json(String classpathResource, String destPath) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return json(is, destPath);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import content of JSON file into repository.
+     * @param inputStream Input stream with JSON content
+     * @param parentResource Parent resource
+     * @param childName Name of child resource to create with JSON content
+     * @return Resource
+     */
+    public Resource json(InputStream inputStream, Resource parentResource, 
String childName) {
+        return json(inputStream, parentResource.getPath() + "/" + childName);
+    }
+
+    /**
+     * Import content of JSON file into repository. Auto-creates parent
+     * hierarchies as nt:unstrucured nodes if missing.
+     * @param inputStream Input stream with JSON content
+     * @param destPath Path to import the JSON content to
+     * @return Resource
+     */
+    public Resource json(InputStream inputStream, String destPath) {
+        try {
+            String parentPath = ResourceUtil.getParent(destPath);
+            String childName = ResourceUtil.getName(destPath);
+
+            Resource parentResource = resourceResolver.getResource(parentPath);
+            if (parentResource == null) {
+                parentResource = createResourceHierarchy(parentPath);
+            }
+            if (parentResource.getChild(childName) != null) {
+                throw new IllegalArgumentException("Resource does already 
exist: " + destPath);
+            }
+
+            String jsonString = convertToJsonString(inputStream).trim();
+            JSONObject json = new JSONObject(jsonString);
+            return this.createResource(parentResource, childName, json);
+        } catch (JSONException ex) {
+            throw new RuntimeException(ex);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private Resource createResourceHierarchy(String path) {
+        String parentPath = ResourceUtil.getParent(path);
+        if (parentPath == null) {
+            return null;
+        }
+        Resource parentResource = resourceResolver.getResource(parentPath);
+        if (parentResource == null) {
+            parentResource = createResourceHierarchy(parentPath);
+        }
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+        try {
+            return resourceResolver.create(parentResource, 
ResourceUtil.getName(path), props);
+        } catch (PersistenceException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private Resource createResource(Resource parentResource, String childName, 
JSONObject jsonObject)
+            throws IOException, JSONException {
+
+        // collect all properties first
+        Map<String, Object> props = new HashMap<String, Object>();
+        JSONArray names = jsonObject.names();
+        for (int i = 0; names != null && i < names.length(); i++) {
+            final String name = names.getString(i);
+            if (!IGNORED_NAMES.contains(name)) {
+                Object obj = jsonObject.get(name);
+                if (!(obj instanceof JSONObject)) {
+                    this.setProperty(props, name, obj);
+                }
+            }
+        }
+
+        // validate JCR primary type
+        Object primaryTypeObj = jsonObject.opt(JcrConstants.JCR_PRIMARYTYPE);
+        String primaryType = null;
+        if (primaryTypeObj != null) {
+            primaryType = String.valueOf(primaryTypeObj);
+        }
+        if (primaryType == null) {
+            primaryType = JcrConstants.NT_UNSTRUCTURED;
+        }
+        props.put(JcrConstants.JCR_PRIMARYTYPE, primaryType);
+
+        // create resource
+        Resource resource = resourceResolver.create(parentResource, childName, 
props);
+
+        // add child resources
+        for (int i = 0; names != null && i < names.length(); i++) {
+            final String name = names.getString(i);
+            if (!IGNORED_NAMES.contains(name)) {
+                Object obj = jsonObject.get(name);
+                if (obj instanceof JSONObject) {
+                    createResource(resource, name, (JSONObject) obj);
+                }
+            }
+        }
+
+        return resource;
+    }
+
+    private void setProperty(Map<String, Object> props, String name, Object 
value) throws JSONException {
+        if (value instanceof JSONArray) {
+            // multivalue
+            final JSONArray array = (JSONArray) value;
+            if (array.length() > 0) {
+                final Object[] values = new Object[array.length()];
+                for (int i = 0; i < array.length(); i++) {
+                    values[i] = array.get(i);
+                }
+
+                if (values[0] instanceof Double || values[0] instanceof Float) 
{
+                    Double[] arrayValues = new Double[values.length];
+                    for (int i = 0; i < values.length; i++) {
+                        arrayValues[i] = (Double) values[i];
+                    }
+                    props.put(cleanupJsonName(name), arrayValues);
+                } else if (values[0] instanceof Number) {
+                    Long[] arrayValues = new Long[values.length];
+                    for (int i = 0; i < values.length; i++) {
+                        arrayValues[i] = ((Number) values[i]).longValue();
+                    }
+                    props.put(cleanupJsonName(name), arrayValues);
+                } else if (values[0] instanceof Boolean) {
+                    Boolean[] arrayValues = new Boolean[values.length];
+                    for (int i = 0; i < values.length; i++) {
+                        arrayValues[i] = (Boolean) values[i];
+                    }
+                    props.put(cleanupJsonName(name), arrayValues);
+                } else {
+                    String[] arrayValues = new String[values.length];
+                    for (int i = 0; i < values.length; i++) {
+                        arrayValues[i] = values[i].toString();
+                    }
+                    props.put(cleanupJsonName(name), arrayValues);
+                }
+            } else {
+                props.put(cleanupJsonName(name), new String[0]);
+            }
+
+        } else {
+            // single value
+            if (value instanceof Double || value instanceof Float) {
+                props.put(cleanupJsonName(name), value);
+            } else if (value instanceof Number) {
+                props.put(cleanupJsonName(name), ((Number) value).longValue());
+            } else if (value instanceof Boolean) {
+                props.put(cleanupJsonName(name), value);
+            } else {
+                String stringValue = value.toString();
+
+                // check if value is a Calendar object
+                Calendar calendar = tryParseCalendarValue(stringValue);
+                if (calendar != null) {
+                    props.put(cleanupJsonName(name), calendar);
+                } else {
+                    props.put(cleanupJsonName(name), stringValue);
+                }
+
+            }
+        }
+    }
+
+    private String cleanupJsonName(String name) {
+        if (name.startsWith(REFERENCE)) {
+            return name.substring(REFERENCE.length());
+        }
+        if (name.startsWith(PATH)) {
+            return name.substring(PATH.length());
+        }
+        return name;
+    }
+
+    private String convertToJsonString(InputStream inputStream) {
+        try {
+            return IOUtils.toString(inputStream);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    private Calendar tryParseCalendarValue(String value) {
+        if (StringUtils.isNotBlank(value)) {
+            synchronized (calendarFormat) {
+                try {
+                    Date date = calendarFormat.parse(value);
+                    Calendar calendar = Calendar.getInstance();
+                    calendar.setTime(date);
+                    return calendar;
+                } catch (ParseException ex) {
+                    // ignore
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
+     * auto-detected from resource name.
+     * @param classpathResource Classpath resource URL for binary file.
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(String classpathResource, String path) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return binaryFile(is, path, detectMimeTypeFromName(path));
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing.
+     * @param classpathResource Classpath resource URL for binary file.
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(String classpathResource, String path, String 
mimeType) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return binaryFile(is, path, mimeType);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
+     * auto-detected from resource name.
+     * @param inputStream Input stream for binary data
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(InputStream inputStream, String path) {
+        return binaryFile(inputStream, path, detectMimeTypeFromName(path));
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing.
+     * @param inputStream Input stream for binary data
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(InputStream inputStream, String path, String 
mimeType) {
+        String parentPath = ResourceUtil.getParent(path, 1);
+        String name = ResourceUtil.getName(path);
+        Resource parentResource = resourceResolver.getResource(parentPath);
+        if (parentResource == null) {
+            parentResource = createResourceHierarchy(parentPath);
+        }
+        return binaryFile(inputStream, parentResource, name, mimeType);
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing. Mime type is
+     * auto-detected from resource name.
+     * @param inputStream Input stream for binary data
+     * @param parentResource Parent resource
+     * @param name Resource name for nt:file
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(InputStream inputStream, Resource 
parentResource, String name) {
+        return binaryFile(inputStream, parentResource, name, 
detectMimeTypeFromName(name));
+    }
+
+    /**
+     * Import binary file as nt:file binary node into repository. Auto-creates
+     * parent hierarchies as nt:unstrucured nodes if missing.
+     * @param inputStream Input stream for binary data
+     * @param parentResource Parent resource
+     * @param name Resource name for nt:file
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryFile(InputStream inputStream, Resource 
parentResource, String name, String mimeType) {
+        try {
+            Resource file = resourceResolver.create(parentResource, name,
+                    ImmutableMap.<String, Object> 
builder().put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_FILE)
+                            .build());
+            resourceResolver.create(file, JcrConstants.JCR_CONTENT,
+                    ImmutableMap.<String, Object> 
builder().put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_RESOURCE)
+                            .put(JcrConstants.JCR_DATA, 
inputStream).put(JcrConstants.JCR_MIMETYPE, mimeType).build());
+            return file;
+        } catch (PersistenceException ex) {
+            throw new RuntimeException("Unable to create resource at " + 
parentResource.getPath() + "/" + name, ex);
+        }
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
+     * type is auto-detected from resource name.
+     * @param classpathResource Classpath resource URL for binary file.
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(String classpathResource, String path) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return binaryResource(is, path, detectMimeTypeFromName(path));
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
+     * @param classpathResource Classpath resource URL for binary file.
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(String classpathResource, String path, 
String mimeType) {
+        InputStream is = 
ContentLoader.class.getResourceAsStream(classpathResource);
+        if (is == null) {
+            throw new IllegalArgumentException("Classpath resource not found: 
" + classpathResource);
+        }
+        try {
+            return binaryResource(is, path, mimeType);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
+     * type is auto-detected from resource name.
+     * @param inputStream Input stream for binary data
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(InputStream inputStream, String path) {
+        return binaryResource(inputStream, path, detectMimeTypeFromName(path));
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
+     * @param inputStream Input stream for binary data
+     * @param path Path to mount binary data to (parent nodes created
+     *            automatically)
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(InputStream inputStream, String path, 
String mimeType) {
+        String parentPath = ResourceUtil.getParent(path, 1);
+        String name = ResourceUtil.getName(path);
+        Resource parentResource = resourceResolver.getResource(parentPath);
+        if (parentResource == null) {
+            parentResource = createResourceHierarchy(parentPath);
+        }
+        return binaryResource(inputStream, parentResource, name, mimeType);
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing. Mime
+     * type is auto-detected from resource name.
+     * @param inputStream Input stream for binary data
+     * @param parentResource Parent resource
+     * @param name Resource name for nt:resource
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(InputStream inputStream, Resource 
parentResource, String name) {
+        return binaryResource(inputStream, parentResource, name, 
detectMimeTypeFromName(name));
+    }
+
+    /**
+     * Import binary file as nt:resource binary node into repository.
+     * Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
+     * @param inputStream Input stream for binary data
+     * @param parentResource Parent resource
+     * @param name Resource name for nt:resource
+     * @param mimeType Mime type of binary data
+     * @return Resource with binary data
+     */
+    public Resource binaryResource(InputStream inputStream, Resource 
parentResource, String name, String mimeType) {
+        try {
+            return resourceResolver.create(parentResource, name,
+                    ImmutableMap.<String, Object> 
builder().put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_RESOURCE)
+                            .put(JcrConstants.JCR_DATA, 
inputStream).put(JcrConstants.JCR_MIMETYPE, mimeType).build());
+        } catch (PersistenceException ex) {
+            throw new RuntimeException("Unable to create resource at " + 
parentResource.getPath() + "/" + name, ex);
+        }
+    }
+
+    /**
+     * Detected mime type from name (file extension) using Mime Type service.
+     * Fallback to application/octet-stream.
+     * @param name Node name
+     * @return Mime type (never null)
+     */
+    private String detectMimeTypeFromName(String name) {
+        String mimeType = null;
+        String fileExtension = StringUtils.substringAfterLast(name, ".");
+        if (bundleContext != null && StringUtils.isNotEmpty(fileExtension)) {
+            ServiceReference ref = 
bundleContext.getServiceReference(MimeTypeService.class.getName());
+            if (ref != null) {
+                MimeTypeService mimeTypeService = (MimeTypeService) 
bundleContext.getService(ref);
+                mimeType = mimeTypeService.getMimeType(fileExtension);
+            }
+        }
+        return StringUtils.defaultString(mimeType, CONTENTTYPE_OCTET_STREAM);
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/ContentLoader.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/loader/ContentLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/package-info.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/package-info.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/package-info.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/package-info.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Helpers for importing test content into the mocked repositories / resource 
hierarchies.
+ */
+package org.apache.sling.testing.mock.sling.loader;
+

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/loader/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/loader/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/package-info.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/package-info.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Mock implementation of selected Sling APIs.
+ */
+package org.apache.sling.testing.mock.sling;
+

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/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/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockMimeTypeService.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockMimeTypeService.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockMimeTypeService.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockMimeTypeService.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,78 @@
+/*
+ * 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.services;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.commons.mime.internal.MimeTypeServiceImpl;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Mock {@link MimeTypeService} implementation.
+ */
+@Component(inherit = false)
+@Service(MimeTypeService.class)
+public final class MockMimeTypeService extends MimeTypeServiceImpl {
+
+    private boolean initialized;
+
+    /**
+     * Do lazy initializing because reading to avoid reading all defined mime
+     * types from disk if not required
+     */
+    private void lazyInitialization() {
+        if (!this.initialized) {
+            this.initialized = true;
+            // activate service in simulated OSGi environment
+            ComponentContext componentContext = MockOsgi.newComponentContext();
+            this.bindLogService(MockOsgi.newLogService(getClass()));
+            activate(componentContext);
+        }
+    }
+
+    @Override
+    public String getMimeType(final String name) {
+        lazyInitialization();
+        return super.getMimeType(name);
+    }
+
+    @Override
+    public String getExtension(final String mimeType) {
+        lazyInitialization();
+        return super.getExtension(mimeType);
+    }
+
+    @Override
+    public void registerMimeType(final String mimeType, final String... 
extensions) {
+        lazyInitialization();
+        super.registerMimeType(mimeType, extensions);
+    }
+
+    @Override
+    public void registerMimeType(final InputStream mimeTabStream) throws 
IOException {
+        lazyInitialization();
+        super.registerMimeType(mimeTabStream);
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockMimeTypeService.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/services/MockMimeTypeService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockModelAdapterFactory.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockModelAdapterFactory.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockModelAdapterFactory.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockModelAdapterFactory.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,295 @@
+/*
+ * 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.services;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.impl.ModelAdapterFactory;
+import org.apache.sling.models.spi.ImplementationPicker;
+import org.apache.sling.models.spi.Injector;
+import 
org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory;
+import org.apache.sling.testing.mock.osgi.MockOsgi;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.component.ComponentContext;
+import org.reflections.Reflections;
+
+/**
+ * Mock {@link ModelAdapterFactory} implementation.
+ */
+@Component(inherit = false)
+@Service(AdapterFactory.class)
+public final class MockModelAdapterFactory extends ModelAdapterFactory {
+
+    private final BundleContext bundleContext;
+
+    /**
+     * @param componentContext OSGi component context
+     */
+    public MockModelAdapterFactory(ComponentContext componentContext) {
+        bundleContext = componentContext.getBundleContext();
+
+        // register service listener to collect injectors
+        // this allows detecting injectors even if they are registered after
+        // this bundle
+        // (which is otherwise currently not supported in the osgi mock
+        // environment)
+        bundleContext.addServiceListener(new InjectorServiceListener());
+
+        // activate service in simulated OSGi environment
+        activate(componentContext);
+    }
+
+    /**
+     * Constructor with default component context
+     */
+    public MockModelAdapterFactory() {
+        this(MockOsgi.newComponentContext());
+    }
+
+    private class InjectorServiceListener implements ServiceListener {
+
+        @Override
+        public void serviceChanged(ServiceEvent event) {
+            Object service = 
bundleContext.getService(event.getServiceReference());
+            if (service instanceof Injector) {
+                if (event.getType() == ServiceEvent.REGISTERED) {
+                    bindInjector((Injector) service, 
getServiceProperties(event.getServiceReference()));
+                } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+                    unbindInjector((Injector) service, 
getServiceProperties(event.getServiceReference()));
+                }
+            }
+            if (service instanceof InjectAnnotationProcessorFactory) {
+                if (event.getType() == ServiceEvent.REGISTERED) {
+                    
bindInjectAnnotationProcessorFactory((InjectAnnotationProcessorFactory) service,
+                            getServiceProperties(event.getServiceReference()));
+                } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+                    
unbindInjectAnnotationProcessorFactory((InjectAnnotationProcessorFactory) 
service,
+                            getServiceProperties(event.getServiceReference()));
+                }
+            }
+            if (service instanceof ImplementationPicker) {
+                if (event.getType() == ServiceEvent.REGISTERED) {
+                    bindImplementationPicker((ImplementationPicker) service,
+                            getServiceProperties(event.getServiceReference()));
+                } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+                    unbindImplementationPicker((ImplementationPicker) service,
+                            getServiceProperties(event.getServiceReference()));
+                }
+            }
+        }
+
+        private Map<String, Object> getServiceProperties(ServiceReference 
reference) {
+            Map<String, Object> props = new HashMap<String, Object>();
+            String[] propertyKeys = reference.getPropertyKeys();
+            for (String key : propertyKeys) {
+                props.put(key, reference.getProperty(key));
+            }
+            return props;
+        }
+
+    }
+
+    /**
+     * 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 void addModelsForPackage(String packageName) {
+        Bundle bundle = new ModelsPackageBundle(packageName, Bundle.ACTIVE);
+        BundleEvent event = new BundleEvent(BundleEvent.STARTED, bundle);
+        MockOsgi.sendBundleEvent(this.bundleContext, event);
+    }
+
+    @SuppressWarnings("unused")
+    private class ModelsPackageBundle implements Bundle {
+
+        private final String packageName;
+        private final int state;
+
+        public ModelsPackageBundle(String packageName, int state) {
+            this.packageName = packageName;
+            this.state = state;
+        }
+
+        @Override
+        public int getState() {
+            return this.state;
+        }
+
+        @Override
+        public Dictionary getHeaders() {
+            Dictionary<String, Object> headers = new Hashtable<String, 
Object>();
+            headers.put("Sling-Model-Packages", this.packageName);
+            return headers;
+        }
+
+        @Override
+        public Enumeration findEntries(String path, String filePattern, 
boolean recurse) {
+            Reflections reflections = new Reflections(this.packageName);
+            Set<Class<?>> types = 
reflections.getTypesAnnotatedWith(Model.class);
+            Vector<URL> urls = new Vector<URL>(); // NOPMD
+            try {
+                for (Class<?> type : types) {
+                    urls.add(new URL("file:/" + type.getName().replace('.', 
'/') + ".class"));
+                }
+            } catch (MalformedURLException ex) {
+                throw new RuntimeException("Malformed URL.", ex);
+            }
+            return urls.elements();
+        }
+
+        @Override
+        public Class loadClass(String name) throws ClassNotFoundException {
+            return getClass().getClassLoader().loadClass(name);
+        }
+
+        @Override
+        public BundleContext getBundleContext() {
+            return bundleContext;
+        }
+
+        @Override
+        public void start(int options) throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void start() throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void stop(int options) throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void stop() throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void update(InputStream input) throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void update() throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public void uninstall() throws BundleException {
+            // do nothing
+        }
+
+        @Override
+        public long getBundleId() {
+            return 0;
+        }
+
+        @Override
+        public String getLocation() {
+            return null;
+        }
+
+        @Override
+        public ServiceReference[] getRegisteredServices() { // NOPMD
+            return null;
+        }
+
+        @Override
+        public ServiceReference[] getServicesInUse() { // NOPMD
+            return null;
+        }
+
+        @Override
+        public boolean hasPermission(Object permission) {
+            return false;
+        }
+
+        @Override
+        public URL getResource(String name) {
+            return null;
+        }
+
+        @Override
+        public Dictionary getHeaders(String locale) {
+            return null;
+        }
+
+        @Override
+        public String getSymbolicName() {
+            return null;
+        }
+
+        @Override
+        public Enumeration getResources(String name) throws IOException {
+            return null;
+        }
+
+        @Override
+        public Enumeration getEntryPaths(String path) {
+            return null;
+        }
+
+        @Override
+        public URL getEntry(String path) {
+            return null;
+        }
+
+        @Override
+        public long getLastModified() {
+            return 0;
+        }
+
+        // this is part of org.osgi 4.2.0
+        public Map getSignerCertificates(int signersType) {
+            return null;
+        }
+
+        // this is part of org.osgi 4.2.0
+        public Version getVersion() {
+            return null;
+        }
+
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockModelAdapterFactory.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/services/MockModelAdapterFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockSlingSettingService.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockSlingSettingService.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockSlingSettingService.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockSlingSettingService.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,90 @@
+/*
+ * 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.services;
+
+import java.net.URL;
+import java.util.Set;
+
+import org.apache.sling.settings.SlingSettingsService;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Mock implementation of {@link SlingSettingsService}.
+ */
+public final class MockSlingSettingService implements SlingSettingsService {
+
+    private Set<String> runModes;
+
+    /**
+     * Instantiate with no default run modes.
+     */
+    public MockSlingSettingService() {
+        this(ImmutableSet.<String> of());
+    }
+
+    /**
+     * Instantiate with given run modes
+     * @param defaultRunModes Run modes
+     */
+    public MockSlingSettingService(Set<String> defaultRunModes) {
+        this.runModes = defaultRunModes;
+    }
+
+    @Override
+    public Set<String> getRunModes() {
+        return ImmutableSet.copyOf(this.runModes);
+    }
+
+    public void setRunModes(Set<String> runModes) {
+        this.runModes = runModes;
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public String getAbsolutePathWithinSlingHome(String relativePath) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getSlingId() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getSlingHomePath() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public URL getSlingHome() {
+        throw new UnsupportedOperationException();
+    }
+
+    // part of Sling API 2.7
+    public String getSlingName() {
+        throw new UnsupportedOperationException();
+    }
+
+    // part of Sling API 2.7
+    public String getSlingDescription() {
+        throw new UnsupportedOperationException();
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/services/MockSlingSettingService.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/services/MockSlingSettingService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/CookieSupport.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/CookieSupport.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/CookieSupport.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/CookieSupport.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,53 @@
+/*
+ * 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.servlet;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+
+/**
+ * Manages cookies for request and response.
+ */
+class CookieSupport {
+
+    private Map<String, Cookie> cookies = new LinkedHashMap<String, Cookie>();
+
+    public void addCookie(Cookie cookie) {
+        cookies.put(cookie.getName(), cookie);
+    }
+
+    public Cookie getCookie(String name) {
+        return cookies.get(name);
+    }
+
+    public Cookie[] getCookies() {
+        if (cookies.isEmpty()) {
+            return null;
+        } else {
+            return cookies.values().toArray(new Cookie[cookies.size()]);
+        }
+    }
+
+    public void reset() {
+        cookies.clear();
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/CookieSupport.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/servlet/CookieSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/HeaderSupport.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/HeaderSupport.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/HeaderSupport.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/HeaderSupport.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,175 @@
+/*
+ * 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.servlet;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.Vector;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+/**
+ * Manage HTTP headers for request and response.
+ */
+class HeaderSupport {
+
+    private static final String RFC_1123_DATE_PATTERN = "EEE, dd MMM yyyy 
HH:mm:ss z";
+    private static final DateFormat RFC1123_DATE_FORMAT = new 
SimpleDateFormat(RFC_1123_DATE_PATTERN, Locale.US);
+    private static final TimeZone TIMEZONE_GMT = TimeZone.getTimeZone("GMT");
+    static {
+        RFC1123_DATE_FORMAT.setTimeZone(TIMEZONE_GMT);
+    }
+
+    private List<HeaderValue> headers = new ArrayList<HeaderValue>();
+
+    private static class HeaderValue {
+
+        private String key;
+        private String value;
+
+        public HeaderValue(String key, String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        public String getKey() {
+            return this.key;
+        }
+
+        public String getValue() {
+            return this.value;
+        }
+
+    }
+
+    public void addHeader(String name, String value) {
+        headers.add(new HeaderValue(name, value));
+    }
+
+    public void addIntHeader(String name, int value) {
+        headers.add(new HeaderValue(name, Integer.toString(value)));
+    }
+
+    public void addDateHeader(String name, long date) {
+        Calendar calendar = Calendar.getInstance(TIMEZONE_GMT, Locale.US);
+        calendar.setTimeInMillis(date);
+        headers.add(new HeaderValue(name, formatDate(calendar)));
+    }
+
+    public void setHeader(String name, String value) {
+        removeHeaders(name);
+        addHeader(name, value);
+    }
+
+    public void setIntHeader(String name, int value) {
+        removeHeaders(name);
+        addIntHeader(name, value);
+    }
+
+    public void setDateHeader(String name, long date) {
+        removeHeaders(name);
+        addDateHeader(name, date);
+    }
+
+    private void removeHeaders(String name) {
+        for (int i = this.headers.size() - 1; i >= 0; i--) {
+            if (StringUtils.equals(this.headers.get(i).getKey(), name)) {
+                headers.remove(i);
+            }
+        }
+    }
+
+    public boolean containsHeader(String name) {
+        return !getHeaders(name).isEmpty();
+    }
+
+    public String getHeader(String name) {
+        Collection<String> values = getHeaders(name);
+        if (!values.isEmpty()) {
+            return values.iterator().next();
+        } else {
+            return null;
+        }
+    }
+
+    public int getIntHeader(String name) {
+        String value = getHeader(name);
+        return NumberUtils.toInt(value);
+    }
+
+    public long getDateHeader(String name) {
+        String value = getHeader(name);
+        if (StringUtils.isEmpty(value)) {
+            return 0L;
+        } else {
+            try {
+                return parseDate(value).getTimeInMillis();
+            } catch (ParseException ex) {
+                return 0L;
+            }
+        }
+    }
+
+    public Collection<String> getHeaders(String name) {
+        List<String> values = new ArrayList<String>();
+        for (HeaderValue entry : headers) {
+            if (StringUtils.equals(entry.getKey(), name)) {
+                values.add(entry.getValue());
+            }
+        }
+        return values;
+    }
+
+    public Collection<String> getHeaderNames() {
+        Set<String> values = new HashSet<String>();
+        for (HeaderValue entry : headers) {
+            values.add(entry.getKey());
+        }
+        return values;
+    }
+
+    public void reset() {
+        headers.clear();
+    }
+
+    public static Enumeration<String> toEnumeration(Collection<String> 
collection) {
+        return new Vector<String>(collection).elements();
+    }
+
+    private static synchronized String formatDate(Calendar date) {
+        return RFC1123_DATE_FORMAT.format(date.getTime());
+    }
+
+    private static synchronized Calendar parseDate(String dateString) throws 
ParseException {
+        RFC1123_DATE_FORMAT.parse(dateString);
+        return RFC1123_DATE_FORMAT.getCalendar();
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/HeaderSupport.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/servlet/HeaderSupport.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockHttpSession.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockHttpSession.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockHttpSession.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockHttpSession.java
 Mon Oct 13 11:54:39 2014
@@ -0,0 +1,129 @@
+/*
+ * 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.servlet;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.collections.IteratorUtils;
+
+/**
+ * Mock {@link HttpSession} implementation.
+ */
+public final class MockHttpSession implements HttpSession {
+
+    private final ServletContext servletContext = new MockServletContext();
+    private final Map<String, Object> attributeMap = new HashMap<String, 
Object>();
+    private final String sessionID = UUID.randomUUID().toString();
+    private final long creationTime = System.currentTimeMillis();
+
+    @Override
+    public ServletContext getServletContext() {
+        return this.servletContext;
+    }
+
+    @Override
+    public Object getAttribute(final String name) {
+        return this.attributeMap.get(name);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Enumeration<String> getAttributeNames() {
+        return 
IteratorUtils.asEnumeration(this.attributeMap.keySet().iterator());
+    }
+
+    @Override
+    public String getId() {
+        return this.sessionID;
+    }
+
+    @Override
+    public long getCreationTime() {
+        return this.creationTime;
+    }
+
+    @Override
+    public Object getValue(final String name) {
+        return getAttribute(name);
+    }
+
+    @Override
+    public String[] getValueNames() {
+        return this.attributeMap.keySet().toArray(new 
String[this.attributeMap.keySet().size()]);
+    }
+
+    @Override
+    public void putValue(final String name, final Object value) {
+        setAttribute(name, value);
+    }
+
+    @Override
+    public void removeAttribute(final String name) {
+        this.attributeMap.remove(name);
+    }
+
+    @Override
+    public void removeValue(final String name) {
+        this.attributeMap.remove(name);
+    }
+
+    @Override
+    public void setAttribute(final String name, final Object value) {
+        this.attributeMap.put(name, value);
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public long getLastAccessedTime() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getMaxInactiveInterval() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    public javax.servlet.http.HttpSessionContext getSessionContext() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void invalidate() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isNew() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setMaxInactiveInterval(final int interval) {
+        throw new UnsupportedOperationException();
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockHttpSession.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/servlet/MockHttpSession.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockRequestPathInfo.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockRequestPathInfo.java?rev=1631356&view=auto
==============================================================================
--- 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockRequestPathInfo.java
 (added)
+++ 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockRequestPathInfo.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.servlet;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.request.RequestPathInfo;
+import org.apache.sling.api.resource.Resource;
+
+/**
+ * Mock {@link RequestPathInfo} implementation.
+ */
+public final class MockRequestPathInfo implements RequestPathInfo {
+
+    private String extension;
+    private String resourcePath;
+    private String selectorString;
+    private String suffix;
+
+    @Override
+    public String getExtension() {
+        return this.extension;
+    }
+
+    @Override
+    public String getResourcePath() {
+        return this.resourcePath;
+    }
+
+    @Override
+    public String[] getSelectors() {
+        if (StringUtils.isEmpty(this.selectorString)) {
+            return new String[0];
+        } else {
+            return StringUtils.split(this.selectorString, ".");
+        }
+    }
+
+    @Override
+    public String getSelectorString() {
+        return this.selectorString;
+    }
+
+    @Override
+    public String getSuffix() {
+        return this.suffix;
+    }
+
+    public void setExtension(final String extension) {
+        this.extension = extension;
+    }
+
+    public void setResourcePath(final String resourcePath) {
+        this.resourcePath = resourcePath;
+    }
+
+    public void setSelectorString(final String selectorString) {
+        this.selectorString = selectorString;
+    }
+
+    public void setSuffix(final String suffix) {
+        this.suffix = suffix;
+    }
+
+    // --- unsupported operations ---
+    @Override
+    public Resource getSuffixResource() {
+        throw new UnsupportedOperationException();
+    }
+
+}

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

Propchange: 
sling/trunk/testing/sling-mock/src/main/java/org/apache/sling/testing/mock/sling/servlet/MockRequestPathInfo.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/servlet/MockRequestPathInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to