Package org.apache.chemistry.opencmis.client.bindings.cache.impl

Source Code of org.apache.chemistry.opencmis.client.bindings.cache.impl.CacheImpl

/*
* 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.chemistry.opencmis.client.bindings.cache.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.chemistry.opencmis.client.bindings.cache.Cache;
import org.apache.chemistry.opencmis.client.bindings.cache.CacheLevel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Default cache implementation.
*
* @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
*
*/
public class CacheImpl implements Cache {

    private static Log log = LogFactory.getLog(CacheImpl.class);

    private static final long serialVersionUID = 1L;

    private List<Class<?>> fLevels;
    private List<Map<String, String>> fLevelParameters;

    private String fName;

    private CacheLevel fRoot;

    private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();

    /**
     * Constructor.
     */
    public CacheImpl() {
        fName = "Cache";
    }

    /**
     * Constructor.
     */
    public CacheImpl(String name) {
        fName = name;
    }

    public void initialize(String[] cacheLevelConfig) {
        if (fLevels != null) {
            throw new IllegalStateException("Cache already initialize!");
        }

        if ((cacheLevelConfig == null) || (cacheLevelConfig.length == 0)) {
            throw new IllegalArgumentException("Cache config must not be empty!");
        }

        fLock.writeLock().lock();
        try {
            fLevels = new ArrayList<Class<?>>();
            fLevelParameters = new ArrayList<Map<String, String>>();

            // build level lists
            for (String config : cacheLevelConfig) {
                int x = config.indexOf(' ');
                if (x == -1) {
                    addLevel(config, null);
                } else {
                    addLevel(config.substring(0, x), config.substring(x + 1));
                }
            }

            // create root
            fRoot = createCacheLevel(0);
        } finally {
            fLock.writeLock().unlock();
        }
    }

    private void addLevel(String className, String parameters) {
        // get the class
        Class<?> clazz;
        try {
            clazz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Class '" + className + "' not found!", e);
        }

        // check the class
        if (!CacheLevel.class.isAssignableFrom(clazz)) {
            throw new IllegalArgumentException("Class '" + className + "' does not implement the CacheLevel interface!");
        }

        fLevels.add(clazz);

        // process parameters
        if (parameters == null) {
            fLevelParameters.add(null);
        } else {
            Map<String, String> parameterMap = new HashMap<String, String>();
            fLevelParameters.add(parameterMap);

            for (String pair : parameters.split(",")) {
                String[] keyValue = pair.split("=");
                if (keyValue.length == 1) {
                    parameterMap.put(keyValue[0], "");
                } else {
                    parameterMap.put(keyValue[0], keyValue[1]);
                }
            }
        }
    }

    public Object get(String... keys) {
        // check keys
        if (keys == null) {
            return null;
        }

        // check level depth
        if (fLevels.size() != keys.length) {
            throw new IllegalArgumentException("Wrong number of keys!");
        }

        Object result = null;

        fLock.readLock().lock();
        try {
            CacheLevel cacheLevel = fRoot;

            // follow the branch
            for (int i = 0; i < keys.length - 1; i++) {
                Object level = cacheLevel.get(keys[i]);

                // does the branch exist?
                if (level == null) {
                    return null;
                }

                // next level
                cacheLevel = (CacheLevel) level;
            }

            // get the value
            result = cacheLevel.get(keys[keys.length - 1]);
        } finally {
            fLock.readLock().unlock();
        }

        return result;
    }

    public void put(Object value, String... keys) {
        // check keys
        if (keys == null) {
            return;
        }

        // check level depth
        if (fLevels.size() != keys.length) {
            throw new IllegalArgumentException("Wrong number of keys!");
        }

        fLock.writeLock().lock();
        try {
            CacheLevel cacheLevel = fRoot;

            // follow the branch
            for (int i = 0; i < keys.length - 1; i++) {
                Object level = cacheLevel.get(keys[i]);

                // does the branch exist?
                if (level == null) {
                    level = createCacheLevel(i + 1);
                    cacheLevel.put(level, keys[i]);
                }

                // next level
                cacheLevel = (CacheLevel) level;
            }

            cacheLevel.put(value, keys[keys.length - 1]);

            if (log.isDebugEnabled()) {
                log.debug(fName + ": put [" + getFormattedKeys(keys) + "] = " + value);
            }
        } finally {
            fLock.writeLock().unlock();
        }
    }

    public void remove(String... keys) {
        if (keys == null) {
            return;
        }

        fLock.writeLock().lock();
        try {
            CacheLevel cacheLevel = fRoot;

            // follow the branch
            for (int i = 0; i < keys.length - 1; i++) {
                Object level = cacheLevel.get(keys[i]);

                // does the branch exist?
                if (level == null) {
                    return;
                }

                // next level
                cacheLevel = (CacheLevel) level;
            }

            cacheLevel.remove(keys[keys.length - 1]);

            if (log.isDebugEnabled()) {
                log.debug(fName + ": removed [" + getFormattedKeys(keys) + "]");
            }
        } finally {
            fLock.writeLock().unlock();
        }
    }

    public int check(String... keys) {
        if (keys == null) {
            return -1;
        }

        fLock.readLock().lock();
        try {
            CacheLevel cacheLevel = fRoot;

            // follow the branch
            for (int i = 0; i < keys.length - 1; i++) {
                Object level = cacheLevel.get(keys[i]);

                // does the branch exist?
                if (level == null) {
                    return i;
                }

                // next level
                cacheLevel = (CacheLevel) level;
            }
        } finally {
            fLock.readLock().unlock();
        }

        return keys.length;
    }

    public void writeLock() {
        fLock.writeLock().lock();
    }

    public void writeUnlock() {
        fLock.writeLock().unlock();
    }

    // ---- internal ----

    /**
     * Creates a cache level object.
     */
    private CacheLevel createCacheLevel(int level) {
        if ((level < 0) || (level >= fLevels.size())) {
            throw new IllegalArgumentException("Cache level doesn't fit the configuration!");
        }

        // get the class and create an instance
        Class<?> clazz = fLevels.get(level);
        CacheLevel cacheLevel = null;
        try {
            cacheLevel = (CacheLevel) clazz.newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException("Cache level problem?!", e);
        }

        // initialize it
        cacheLevel.initialize(fLevelParameters.get(level));

        return cacheLevel;
    }

    @Override
    public String toString() {
        return (fRoot == null ? "(no cache root)" : fRoot.toString());
    }

    // ---- internal ----

    private String getFormattedKeys(String[] keys) {
        StringBuilder sb = new StringBuilder();
        for (String k : keys) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(k);
        }

        return sb.toString();
    }
}
TOP

Related Classes of org.apache.chemistry.opencmis.client.bindings.cache.impl.CacheImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.