com.adobe.acs.commons.httpcache.store.jcr.impl.visitor.mock.RootNodeMockFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.acs.commons.httpcache.store.jcr.impl.visitor.mock.RootNodeMockFactory.java

Source

/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2017 Adobe
 * %%
 * Licensed 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.
 * #L%
 */
package com.adobe.acs.commons.httpcache.store.jcr.impl.visitor.mock;

import static org.mockito.Matchers.any;
import static org.powermock.api.mockito.PowerMockito.doAnswer;
import static org.powermock.api.mockito.PowerMockito.doCallRealMethod;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;

import javax.jcr.Binary;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.commons.collections.IteratorUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.commons.AbstractNode;
import org.apache.jackrabbit.value.BinaryImpl;
import org.apache.sling.commons.testing.jcr.MockNodeIterator;
import org.apache.sling.commons.testing.jcr.MockProperty;
import org.apache.sling.commons.testing.jcr.MockPropertyIterator;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import com.adobe.acs.commons.httpcache.store.jcr.impl.JCRHttpCacheStoreConstants;

public class RootNodeMockFactory {
    public static final String ROOT_PATH = "/etc/acs-commons/httpcache/root";

    private static final String TEST_FILE_PATH = "com.adobe.acs.commons.httpcache.store.jcr.impl.visitor/cachecontent.html";

    private final Settings settings;

    private final Session session = mock(Session.class);

    public RootNodeMockFactory(final Settings settings) {
        this.settings = settings;
    }

    public Node build() throws RepositoryException, IOException {
        final Node rootNode = mockStandardNode("rootnode");

        when(rootNode.getPath()).thenReturn(ROOT_PATH);
        Node[] bucketNodeChain = generateBucketNodeChain(rootNode, false);

        Node parentNode = bucketNodeChain[bucketNodeChain.length - 1];
        final NodeIterator entryNodes = generateEntryNodes(parentNode);
        when(parentNode.getNodes()).thenReturn(entryNodes);

        Node[] level1nodes = new Node[1 + settings.emptyBucketNodeChainCount];
        level1nodes[0] = bucketNodeChain[0];

        for (int i = 0; i < settings.emptyBucketNodeChainCount; i++) {
            Node[] emptyBucketNodeChain = generateBucketNodeChain(rootNode, true);
            when(emptyBucketNodeChain[emptyBucketNodeChain.length - 1].getNodes())
                    .thenReturn(new MockNodeIterator());
            level1nodes[i + 1] = emptyBucketNodeChain[0];
        }

        when(rootNode.getNodes()).thenReturn(new MockNodeIterator(level1nodes));
        when(rootNode.getProperties()).thenReturn(new MockPropertyIterator(IteratorUtils.EMPTY_ITERATOR));

        return rootNode;
    }

    private Node[] generateBucketNodeChain(Node rootNode, boolean isEmpty) throws RepositoryException {
        final Node[] bucketNodeChain = new Node[settings.bucketDepth];
        Node currentParentNode = rootNode;
        for (int i = 0; i < settings.bucketDepth; i++) {
            final Node node = mockStandardNode("bucketnode" + (isEmpty ? "-empty" : "") + "-level-" + (i + 1));
            bucketNodeChain[i] = node;

            when(node.getParent()).thenReturn(currentParentNode);
            when(node.getProperties()).thenReturn(new MockPropertyIterator(IteratorUtils.EMPTY_ITERATOR));
            when(node.hasProperty(JCRHttpCacheStoreConstants.PN_ISCACHEENTRYNODE)).thenReturn(false);
            when(node.hasProperty(JCRHttpCacheStoreConstants.PN_ISBUCKETNODE)).thenReturn(true);

            currentParentNode = node;
        }

        for (int i = 0; i < settings.bucketDepth; i++) {
            if (i < settings.bucketDepth) {
                final Node node = bucketNodeChain[i];
                final Node childNode = bucketNodeChain[i];
                final AtomicInteger deleteCounter = new AtomicInteger();

                doAnswer(new Answer<Object>() {
                    @Override
                    public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
                        deleteCounter.getAndIncrement();
                        return null;
                    }
                }).when(node).remove();

                when(node.getParent().getNodes()).thenAnswer(new Answer<NodeIterator>() {
                    @Override
                    public NodeIterator answer(InvocationOnMock invocationOnMock) throws Throwable {
                        if (deleteCounter.get() > 0) {
                            return new MockNodeIterator();
                        } else {
                            return new MockNodeIterator(new Node[] { childNode });
                        }
                    }
                });

            }
        }

        return bucketNodeChain;
    }

    private NodeIterator generateEntryNodes(final Node parentNode) throws RepositoryException, IOException {
        int totalNodeCount = settings.entryNodeCount + settings.expiredEntryNodeCount;
        final Node[] nodes = new AbstractNode[totalNodeCount];

        int i = 0;
        for (; i < settings.entryNodeCount; i++) {
            final Node randomNode = mockEntryNode(parentNode, i, false);
            nodes[i] = randomNode;
        }

        for (; i < totalNodeCount; i++) {
            final Node randomNode = mockEntryNode(parentNode, i, true);
            nodes[i] = randomNode;
        }

        return new MockNodeIterator(nodes);
    }

    private Node mockEntryNode(Node parentNode, int i, boolean isExpired) throws RepositoryException, IOException {

        final String nodeName = (isExpired) ? "expired-entrynode-" : "entrynode-";
        final Node entryNode = mockStandardNode(nodeName + (i + 1));

        if (settings.enableCacheEntryBinaryContent) {
            mockEntryContentNode(entryNode);
        }

        when(entryNode.hasProperty(JCRHttpCacheStoreConstants.PN_ISCACHEENTRYNODE)).thenReturn(true);
        when(entryNode.hasProperty(JCRHttpCacheStoreConstants.PN_ISBUCKETNODE)).thenReturn(false);
        when(entryNode.hasProperty(JCRHttpCacheStoreConstants.PN_EXPIRES_ON)).thenReturn(true);
        when(entryNode.getNodes()).thenReturn(new MockNodeIterator());
        when(entryNode.getProperties()).thenReturn(new MockPropertyIterator(IteratorUtils.EMPTY_ITERATOR));
        when(entryNode.getParent()).thenReturn(parentNode);

        final MockProperty expiresMockProperty = new MockProperty(JCRHttpCacheStoreConstants.PN_EXPIRES_ON);

        int seconds;
        if (isExpired) {
            seconds = -9000;
        } else {
            seconds = 9000;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, seconds);
        expiresMockProperty.setValue(calendar);

        when(entryNode.getProperty(JCRHttpCacheStoreConstants.PN_EXPIRES_ON)).thenReturn(expiresMockProperty);
        return entryNode;
    }

    private void mockEntryContentNode(Node entryNode) throws RepositoryException, IOException {
        final Node contentNode = mock(Node.class);
        final Node jcrContentNode = mock(Node.class);
        final Property dataProperty = mock(Property.class);

        InputStream cacheTestStream = getClass().getClassLoader().getResourceAsStream(TEST_FILE_PATH);

        final Binary binary = new BinaryImpl(cacheTestStream);

        when(dataProperty.getBinary()).thenReturn(binary);

        when(jcrContentNode.getProperty(JcrConstants.JCR_DATA)).thenReturn(dataProperty);
        when(jcrContentNode.hasProperty(JcrConstants.JCR_DATA)).thenReturn(true);
        when(contentNode.getNode(JcrConstants.JCR_CONTENT)).thenReturn(jcrContentNode);
        when(contentNode.hasNode(JcrConstants.JCR_CONTENT)).thenReturn(true);
        when(entryNode.getNode(JCRHttpCacheStoreConstants.PATH_CONTENTS)).thenReturn(contentNode);
        when(entryNode.hasNode(JCRHttpCacheStoreConstants.PATH_CONTENTS)).thenReturn(true);
    }

    private Node mockStandardNode(String name) throws RepositoryException {
        final Node node = mock(AbstractNode.class);
        when(node.getSession()).thenReturn(session);
        when(node.toString()).thenReturn(name);
        when(node.getName()).thenReturn(name);
        doCallRealMethod().when(node).accept(any(ItemVisitor.class));

        when(node.hasNodes()).thenAnswer(new Answer<Boolean>() {
            @Override
            public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable {
                return node.getNodes().getSize() > 0;
            }
        });

        return node;
    }

    public static class Settings {
        private int entryNodeCount = 10;
        private int bucketDepth = 10;
        private int expiredEntryNodeCount = 0;
        private int emptyBucketNodeChainCount = 0;
        private boolean enableCacheEntryBinaryContent = false;

        public void setEntryNodeCount(int entryNodeCount) {
            this.entryNodeCount = entryNodeCount;
        }

        public void setBucketDepth(int bucketDepth) {
            this.bucketDepth = bucketDepth;
        }

        public void setExpiredEntryNodeCount(int expiredEntryNodeCount) {
            this.expiredEntryNodeCount = expiredEntryNodeCount;
        }

        public void setEmptyBucketNodeChainCount(int emptyBucketNodeChainCount) {
            this.emptyBucketNodeChainCount = emptyBucketNodeChainCount;
        }

        public void setEnableCacheEntryBinaryContent(boolean enableCacheEntryBinaryContent) {
            this.enableCacheEntryBinaryContent = enableCacheEntryBinaryContent;
        }
    }
}