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

svn commit: r1562431 - in /sling/trunk/contrib/extensions/resourcemerger: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/resourcemerger/ src/main/java/org/apa...

Author: cziegeler
Date: Wed Jan 29 12:59:42 2014
New Revision: 1562431

URL: http://svn.apache.org/r1562431
Log:
SLING-2986 : Merged Resource Provider. Apply contribution by Gilles Knobloch

Added:
    sling/trunk/contrib/extensions/resourcemerger/
    sling/trunk/contrib/extensions/resourcemerger/pom.xml   (with props)
    sling/trunk/contrib/extensions/resourcemerger/src/
    sling/trunk/contrib/extensions/resourcemerger/src/main/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java   (with props)
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java   (with props)
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java   (with props)
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java   (with props)
    sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java   (with props)

Added: sling/trunk/contrib/extensions/resourcemerger/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/pom.xml?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/pom.xml (added)
+++ sling/trunk/contrib/extensions/resourcemerger/pom.xml Wed Jan 29 12:59:42 2014
@@ -0,0 +1,108 @@
+<?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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>18</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.resourcemerger</artifactId>
+    <packaging>bundle</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <name>Apache Sling Resource Merger</name>
+    <description>
+        This bundle provides services to merge resources.
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/resourcemerger</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/resourcemerger</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>maven-sling-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.5.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.testing</artifactId>
+            <version>2.0.14</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+            <version>2.0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Propchange: sling/trunk/contrib/extensions/resourcemerger/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Added: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java (added)
+++ sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java Wed Jan 29 12:59:42 2014
@@ -0,0 +1,180 @@
+/*
+ * 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.resourcemerger.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * {@inheritDoc}
+ */
+public class MergedResource extends AbstractResource {
+
+    private final ResourceResolver resolver;
+    private final String mergeRootPath;
+    private final String relativePath;
+    private final List<String> mappedResources = new ArrayList<String>();
+
+    /**
+     * Constructor
+     *
+     * @param resolver      Resource resolver
+     * @param mergeRootPath Merge root path
+     * @param relativePath  Relative path
+     */
+    MergedResource(ResourceResolver resolver, String mergeRootPath, String relativePath) {
+        this.resolver = resolver;
+        this.mergeRootPath = mergeRootPath;
+        this.relativePath = relativePath;
+    }
+
+    /**
+     * Constructor
+     *
+     * @param resolver      Resource resolver
+     * @param mergeRootPath   Merge root path
+     * @param relativePath    Relative path
+     * @param mappedResources List of physical mapped resources' paths
+     */
+    MergedResource(ResourceResolver resolver, String mergeRootPath, String relativePath, List<String> mappedResources) {
+        this.resolver = resolver;
+        this.mergeRootPath = mergeRootPath;
+        this.relativePath = relativePath;
+        this.mappedResources.addAll(mappedResources);
+    }
+
+
+    // ---- MergedResource interface ------------------------------------------
+
+    public String getRelativePath() {
+        return relativePath;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addMappedResource(String path) {
+        mappedResources.add(path);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterable<String> getMappedResources() {
+        return mappedResources;
+    }
+
+
+    // ---- Resource interface ------------------------------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getPath() {
+        return ResourceUtil.normalize(mergeRootPath + "/" + relativePath);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Resource> listChildren() {
+        return resolver.listChildren(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getResourceType() {
+        return relativePath;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getResourceSuperType() {
+        // So far, there's no concept of resource super type for a merged resource
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ResourceMetadata getResourceMetadata() {
+        ResourceMetadata metadata = new ResourceMetadata();
+        metadata.put(ResourceMetadata.RESOLUTION_PATH, getPath());
+        metadata.put("sling.mergedResource", true);
+        metadata.put("sling.mappedResources", mappedResources.toArray(new String[mappedResources.size()]));
+        return metadata;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ResourceResolver getResourceResolver() {
+        return resolver;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+        if (type == ValueMap.class) {
+            return (AdapterType) new MergedValueMap(this);
+        }
+
+        return null;
+    }
+
+
+    // ---- Object ------------------------------------------------------------
+
+    /**
+     * Merged resources are considered equal if their paths are equal,
+     * regardless of the list of mapped resources.
+     *
+     * @param o Object to compare with
+     * @return Returns <code>true</code> if the two merged resources have the
+     *         same path.
+     */
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+        if (o == this) {
+            return true;
+        }
+        if (o.getClass() != getClass()) {
+            return false;
+        }
+
+        Resource r = (Resource) o;
+        return r.getPath().equals(getPath());
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java (added)
+++ sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java Wed Jan 29 12:59:42 2014
@@ -0,0 +1,51 @@
+/*
+ * 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.resourcemerger.impl;
+
+/**
+ * Constants related to {@link MergedResource}.
+ */
+public class MergedResourceConstants {
+
+    private MergedResourceConstants() {
+        // Make sure it never gets instantiated
+    }
+
+    /**
+     * Property name containing the list of properties to hide.
+     */
+    public static final String PN_HIDE_PROPERTIES = "sling:hideProperties";
+
+    /**
+     * Property name which has to be set to <code>true</code> to hide the
+     * whole resource (and its children) of the current resource.
+     */
+    public static final String PN_HIDE_RESOURCE = "sling:hideResource";
+
+    /**
+     * Property name containing the list of child resources to hide.
+     */
+    public static final String PN_HIDE_CHILDREN = "sling:hideChildren";
+
+    /**
+     * Property name for the reordering option.
+     */
+    public static final String PN_ORDER_BEFORE = "sling:orderBefore";
+
+}

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceConstants.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java Wed Jan 29 12:59:42 2014
@@ -0,0 +1,185 @@
+/*
+ * 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.resourcemerger.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * The <code>MergedResourceProvider</code> is the resource provider providing
+ * access to {@link MergedResource} objects.
+ */
+public class MergedResourceProvider implements ResourceProvider {
+
+    private final String mergeRootPath;
+
+    public MergedResourceProvider(String mergeRootPath) {
+        this.mergeRootPath = mergeRootPath;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Resource getResource(ResourceResolver resolver, HttpServletRequest request, String path) {
+        return getResource(resolver, path);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Resource getResource(ResourceResolver resolver, String path) {
+        List<String> mappedResources = new ArrayList<String>();
+
+        if (resolver.getSearchPath() != null) {
+            String relativePath = getRelativePath(path);
+
+            // Loop over provided base paths
+            for (String basePath : resolver.getSearchPath()) {
+                // Try to get the corresponding physical resource for this base path
+                Resource baseRes = resolver.getResource(ResourceUtil.normalize(basePath + "/" + relativePath));
+                if (baseRes != null) {
+                    // Physical resource exists, add it to the list of mapped resources
+                    mappedResources.add(0, baseRes.getPath());
+                }
+            }
+
+            if (!mappedResources.isEmpty()) {
+                // Create a new merged resource based on the list of mapped physical resources
+                return new MergedResource(resolver, mergeRootPath, relativePath, mappedResources);
+            }
+        }
+
+        // Either base paths were not defined, or the resource does not exist in any of them
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<Resource> listChildren(Resource resource) {
+        if (resource instanceof MergedResource) {
+            MergedResource mergedResource = (MergedResource) resource;
+            ResourceResolver resolver = mergedResource.getResourceResolver();
+            List<Resource> children = new ArrayList<Resource>();
+
+            for (String mappedResourcePath : mergedResource.getMappedResources()) {
+                Resource mappedResource = resolver.getResource(mappedResourcePath);
+
+                // Check if the resource exists
+                if (mappedResource == null) {
+                    continue;
+                }
+
+                // Check if some previously defined children have to be ignored
+                ValueMap mappedResourceProps = mappedResource.adaptTo(ValueMap.class);
+                List<String> childrenToHide = Arrays.asList(mappedResourceProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, new String[0]));
+                if (childrenToHide.isEmpty()) {
+                    String childToHide = mappedResourceProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String.class);
+                    if (childToHide != null) {
+                        childrenToHide.add(childToHide);
+                    }
+                }
+                if (childrenToHide.contains("*")) {
+                    // Clear current children list
+                    children.clear();
+                } else {
+                    // Go through current children in order to hide them individually
+                    Iterator<Resource> it = children.iterator();
+                    while (it.hasNext()) {
+                        if (childrenToHide.contains(it.next().getName())) {
+                            it.remove();
+                        }
+                    }
+                }
+
+                // Browse children of current physical resource
+                for (Resource child : mappedResource.getChildren()) {
+                    String childRelativePath = ResourceUtil.normalize(mergedResource.getRelativePath() + "/" + child.getName());
+
+                    if (child.adaptTo(ValueMap.class).get(MergedResourceConstants.PN_HIDE_RESOURCE, Boolean.FALSE)) {
+                        // Child resource has to be hidden
+                        children.remove(new MergedResource(resolver, mergeRootPath, childRelativePath));
+
+                    } else {
+                        // Check if the child resource already exists in the children list
+                        MergedResource mergedResChild = new MergedResource(resolver, mergeRootPath, childRelativePath);
+                        int mergedResChildIndex = -1;
+                        if (children.contains(mergedResChild)) {
+                            // Get current index of the merged resource's child
+                            mergedResChildIndex = children.indexOf(mergedResChild);
+                            mergedResChild = (MergedResource) children.get(mergedResChildIndex);
+                        }
+                        // Add a new mapped resource to the merged resource
+                        mergedResChild.addMappedResource(child.getPath());
+                        boolean mergedResChildExists = mergedResChildIndex > -1;
+
+                        // Check if children need reordering
+                        int orderBeforeIndex = -1;
+                        String orderBefore = ResourceUtil.getValueMap(child).get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
+                        if (orderBefore != null && !orderBefore.equals(mergedResChild.getName())) {
+                            // Get a dummy merged resource just to know the index of that merged resource
+                            MergedResource orderBeforeRes = new MergedResource(resolver, mergeRootPath, mergedResource.getRelativePath() + "/" + orderBefore);
+                            if (children.contains(orderBeforeRes)) {
+                                orderBeforeIndex = children.indexOf(orderBeforeRes);
+                            }
+                        }
+
+                        if (orderBeforeIndex > -1) {
+                            // Add merged resource's child at the right position
+                            children.add(orderBeforeIndex, mergedResChild);
+                            if (mergedResChildExists) {
+                                children.remove(mergedResChildIndex > orderBeforeIndex ? ++mergedResChildIndex : mergedResChildIndex);
+                            }
+                        } else if (!mergedResChildExists) {
+                            // Only add the merged resource's child if it did not exist yet
+                            children.add(mergedResChild);
+                        }
+                    }
+                }
+            }
+
+            return children.iterator();
+        }
+
+        // Return null for resources that aren't a MergedResource
+        return null;
+    }
+
+    /**
+     * Gets the relative path out of merge root path
+     *
+     * @param path Absolute path
+     * @return Relative path
+     */
+    private String getRelativePath(String path) {
+        return StringUtils.removeStart(path, mergeRootPath);
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java (added)
+++ sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java Wed Jan 29 12:59:42 2014
@@ -0,0 +1,69 @@
+/*
+ * 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.resourcemerger.impl;
+
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceProviderFactory;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+
+@Component(metatype = false)
+@Service(value = ResourceProviderFactory.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS, value = {"/merge"}, propertyPrivate = true)
+})
+/**
+ * The <code>MergedResourceProviderFactory</code> creates merged resource
+ * providers.
+ */
+public class MergedResourceProviderFactory implements ResourceProviderFactory {
+
+    private String mergeRootPath;
+
+    /**
+     * {@inheritDoc}
+     */
+    public ResourceProvider getResourceProvider(Map<String, Object> stringObjectMap) throws LoginException {
+        return new MergedResourceProvider(mergeRootPath);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ResourceProvider getAdministrativeResourceProvider(Map<String, Object> stringObjectMap) throws LoginException {
+        return new MergedResourceProvider(mergeRootPath);
+    }
+
+    @Activate
+    private void configure(Map<String, ?> properties) {
+        String[] mergeRootPaths = PropertiesUtil.toStringArray(properties.get(ResourceProvider.ROOTS), new String[0]);
+        if (mergeRootPaths.length > 0) {
+            mergeRootPath = mergeRootPaths[0];
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java?rev=1562431&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java (added)
+++ sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java Wed Jan 29 12:59:42 2014
@@ -0,0 +1,166 @@
+/*
+ * 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.resourcemerger.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * A <code>MergedValueMap</code> is a {@link ValueMap} aggregated from the
+ * different resources mapped to a {@link MergedResource}.
+ */
+public class MergedValueMap implements ValueMap {
+
+    /**
+     * Set of properties to exclude from override
+     */
+    private static final Set<String> EXCLUDED_PROPERTIES = new HashSet<String>();
+
+    static {
+        EXCLUDED_PROPERTIES.add(MergedResourceConstants.PN_HIDE_PROPERTIES);
+        EXCLUDED_PROPERTIES.add(MergedResourceConstants.PN_HIDE_RESOURCE);
+        EXCLUDED_PROPERTIES.add(MergedResourceConstants.PN_HIDE_CHILDREN);
+        EXCLUDED_PROPERTIES.add(MergedResourceConstants.PN_ORDER_BEFORE);
+    }
+
+    /**
+     * Final properties
+     */
+    private Map<String, Object> properties = new LinkedHashMap<String, Object>();
+
+    /**
+     * Constructor
+     *
+     * @param resource The merged resource to get properties from
+     */
+    public MergedValueMap(MergedResource resource) {
+        // Iterate over physical resources
+        for (String r : resource.getMappedResources()) {
+            ValueMap vm = ResourceUtil.getValueMap(resource.getResourceResolver().getResource(r));
+            if (properties.isEmpty()) {
+                // Add all properties
+                properties.putAll(vm);
+            } else {
+                // Get properties to add or override
+                for (String key : vm.keySet()) {
+                    if (!isExcludedProperty(key)) {
+                        properties.put(key, vm.get(key));
+                    }
+                }
+
+                // Get properties to hide
+                String[] propertiesToHide = vm.get(MergedResourceConstants.PN_HIDE_PROPERTIES, new String[0]);
+                if (propertiesToHide.length == 0) {
+                    String propertyToHide = vm.get(MergedResourceConstants.PN_HIDE_PROPERTIES, String.class);
+                    if (propertyToHide != null) {
+                        propertiesToHide = new String[]{propertyToHide};
+                    }
+                }
+                for (String propName : propertiesToHide) {
+                    if (propName.equals("*")) {
+                        properties.clear();
+                        break;
+                    } else {
+                        properties.remove(propName);
+                    }
+                }
+            }
+
+            // Hide excluded properties
+            for (String excludedProperty : EXCLUDED_PROPERTIES) {
+                properties.remove(excludedProperty);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(String name, Class<T> type) {
+        return (T) properties.get(name);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T get(String name, T defaultValue) {
+        Object o = properties.get(name);
+        return o == null ? defaultValue : (T) o;
+    }
+
+    public int size() {
+        return properties != null ? properties.size() : 0;
+    }
+
+    public boolean isEmpty() {
+        return properties == null || properties.isEmpty();
+    }
+
+    public boolean containsKey(Object o) {
+        return properties != null && properties.containsKey(o);
+    }
+
+    public boolean containsValue(Object o) {
+        return properties != null && properties.containsValue(o);
+    }
+
+    public Object get(Object o) {
+        return properties != null ? properties.get(o) : null;
+    }
+
+    public Object put(String s, Object o) {
+        return properties != null ? properties.put(s, o) : null;
+    }
+
+    public Object remove(Object o) {
+        return properties != null ? properties.remove(o) : null;
+    }
+
+    public void putAll(Map<? extends String, ?> map) {
+        if (properties != null) {
+            properties.putAll(map);
+        }
+    }
+
+    public void clear() {
+        if (properties != null) {
+            properties.clear();
+        }
+    }
+
+    public Set<String> keySet() {
+        return properties != null ? properties.keySet() : Collections.<String>emptySet();
+    }
+
+    public Collection<Object> values() {
+        return properties != null ? properties.values() : Collections.emptyList();
+    }
+
+    public Set<Entry<String, Object>> entrySet() {
+        return properties != null ? properties.entrySet() : Collections.<Entry<String, Object>>emptySet();
+    }
+
+    private boolean isExcludedProperty(String key) {
+        return EXCLUDED_PROPERTIES.contains(key);
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/resourcemerger/src/main/java/org/apache/sling/resourcemerger/impl/MergedValueMap.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url