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.
*/
public class CacheImpl implements Cache {

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

    private static final long serialVersionUID = 1L;

    private List<Class<?>> levels;
    private List<Map<String, String>> levelParameters;

    private final String name;

    private CacheLevel root;

    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

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

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

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

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

        lock.writeLock().lock();
        try {
            levels = new ArrayList<Class<?>>();
            levelParameters = 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
            root = createCacheLevel(0);
        } finally {
            lock.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!");
        }

        levels.add(clazz);

        // process parameters
        if (parameters == null) {
            levelParameters.add(null);
        } else {
            Map<String, String> parameterMap = new HashMap<String, String>();
            levelParameters.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 (levels.size() != keys.length) {
            throw new IllegalArgumentException("Wrong number of keys!");
        }

        Object result = null;

        lock.readLock().lock();
        try {
            CacheLevel cacheLevel = root;

            // 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 {
            lock.readLock().unlock();
        }

        return result;
    }

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

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

        lock.writeLock().lock();
        try {
            CacheLevel cacheLevel = root;

            // 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.isTraceEnabled()) {
                log.trace(name + ": put [" + getFormattedKeys(keys) + "] = " + value);
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

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

        lock.writeLock().lock();
        try {
            CacheLevel cacheLevel = root;

            // 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.isTraceEnabled()) {
                log.trace(name + ": removed [" + getFormattedKeys(keys) + "]");
            }
        } finally {
            lock.writeLock().unlock();
        }
    }

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

        lock.readLock().lock();
        try {
            CacheLevel cacheLevel = root;

            // 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 {
            lock.readLock().unlock();
        }

        return keys.length;
    }

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

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

    // ---- internal ----

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

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

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

        return cacheLevel;
    }

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

    // ---- internal ----

    private static 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.