com.flexive.ejb.mbeans.FxCache.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.ejb.mbeans.FxCache.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.ejb.mbeans;

import com.flexive.core.stream.BinaryDownloadProtocol;
import com.flexive.core.stream.BinaryUploadProtocol;
import com.flexive.core.structure.StructureLoader;
import com.flexive.shared.CacheAdmin;
import com.flexive.shared.cache.FxBackingCache;
import com.flexive.shared.cache.FxBackingCacheProvider;
import com.flexive.shared.cache.FxBackingCacheProviderFactory;
import com.flexive.shared.cache.FxCacheException;
import com.flexive.shared.mbeans.FxCacheMBean;
import com.flexive.shared.mbeans.FxCacheProxy;
import com.flexive.shared.mbeans.MBeanHelper;
import com.flexive.shared.stream.FxStreamUtils;
import com.flexive.stream.ServerLocation;
import com.flexive.stream.StreamServer;
import com.google.common.collect.Lists;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.Cache;

import javax.management.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * FxCache MBean
 * TODO: implement missing skeletons ...
 *
 * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 */
//@Service(objectName = CacheAdmin.CACHE_SERVICE_NAME)
public class FxCache implements FxCacheMBean, DynamicMBean {
    private static final Log LOG = LogFactory.getLog(FxCache.class);

    private StreamServer server;
    private ServerLocation serverLocation;
    private long nodeStartupTime = -1;

    private FxBackingCacheProvider cacheProvider = null;

    /**
     * Get the backing cache
     *
     * @return FxBackingCache
     * @throws FxCacheException on errors
     */
    private FxBackingCache getBackingCache() throws FxCacheException {
        if (cacheProvider == null) {
            //start the cache
            cacheProvider = FxBackingCacheProviderFactory.createNew();
            LOG.info("Starting backing Cache {" + cacheProvider.getDescription() + "}");
            cacheProvider.init();
            if (cacheProvider.getInstance().get("/" + this.getClass().getName(), SYSTEM_UP_KEY) == null) {
                cacheProvider.getInstance().put("/" + this.getClass().getName(), SYSTEM_UP_KEY,
                        System.currentTimeMillis());
            }
            nodeStartupTime = System.currentTimeMillis();
        }
        return cacheProvider.getInstance();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressWarnings("unchecked")
    public synchronized void create() throws Exception {
        if (server != null)
            return;

        //switch to UTF-8 encoding
        if (!"UTF-8".equals(System.getProperty("file.encoding"))) {
            // set default charset to UTF-8
            LOG.warn("Changing system character encoding from " + System.getProperty("file.encoding")
                    + " to UTF-8.");
            System.setProperty("file.encoding", "UTF-8");
        }
        //start streamserver
        try {
            int port = DEFAULT_STREAMING_PORT;
            if (System.getProperty(STREAMING_PORT_PROPERTY) != null) {
                String _port = System.getProperty(STREAMING_PORT_PROPERTY);
                try {
                    port = Integer.parseInt(_port);
                } catch (NumberFormatException e) {
                    //ignore port
                    LOG.error("Invalid streaming server port provided: [" + _port + "], using default port [" + port
                            + "]");
                }
            }
            server = new StreamServer(FxStreamUtils.probeNetworkInterfaces(), port);
            server.addProtocol(new BinaryUploadProtocol());
            server.addProtocol(new BinaryDownloadProtocol());
            server.start();

            // update streaming server list in shared cache.
            // NOTE! Since we are operating directly on the backing cache, we have to do the actions
            // provided by FxCacheProxy (mapping paths, serializing values) manually

            final List<ServerLocation> servers = getCachedServerList();
            serverLocation = new ServerLocation(server.getAddress().getAddress(), server.getPort());
            if ((serverLocation.getAddress().isLinkLocalAddress() || serverLocation.getAddress().isAnyLocalAddress()
                    || serverLocation.getAddress().isLoopbackAddress()))
                FxStreamUtils.addLocalServer(serverLocation);
            else if (!servers.contains(serverLocation)) //only add if not contained already and not bound to a local address
                servers.add(serverLocation);
            updateCachedServerList(servers);

            LOG.info("Added " + serverLocation + " to available StreamServers (" + servers.size()
                    + " total) for cache " + getBackingCache().toString());
        } catch (Exception e) {
            LOG.error("Failed to start StreamServer. Error: " + e.getMessage(), e);
        }
    }

    private List<ServerLocation> getCachedServerList() throws FxCacheException {
        final String configPath = FxCacheProxy.globalDivisionEncodePath(CacheAdmin.STREAMSERVER_BASE);
        if (globalExists(configPath, CacheAdmin.STREAMSERVER_EJB_KEY)) {
            return Lists.newArrayList((List<ServerLocation>) FxCacheProxy
                    .unmarshal(globalGet(configPath, CacheAdmin.STREAMSERVER_EJB_KEY)));
        }
        return new ArrayList<ServerLocation>(5);
    }

    private void updateCachedServerList(List<ServerLocation> servers) throws FxCacheException {
        globalPut(FxCacheProxy.globalDivisionEncodePath(CacheAdmin.STREAMSERVER_BASE),
                CacheAdmin.STREAMSERVER_EJB_KEY, FxCacheProxy.marshal((Serializable) servers));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void destroy() throws Exception {
        //System.out.println("about to uninstall timer");
        //EJBLookup.getTimerServiceInterface().uninstall();
        //System.out.println("timers uninstalled");
        stopLocalStreamServers();
        try {
            if (cacheProvider != null) {
                cleanupAfterRequest();
                cacheProvider.shutdown();
                cacheProvider = null;
            }
        } catch (FxCacheException e) {
            LOG.error(e, e);
        }
    }

    private void stopLocalStreamServers() {
        if (server != null) {
            try {
                LOG.info("Shutting down StreamServer {" + server.getDescription() + "}");
                try {
                    server.stop();
                } catch (Exception e) {
                    LOG.error(e, e);
                }
                server = null;
                if (serverLocation != null) {
                    final List<ServerLocation> servers = getCachedServerList();
                    servers.remove(serverLocation);
                    updateCachedServerList(servers);
                    serverLocation = null;
                }
            } catch (FxCacheException ex) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Failed to stop local stream server: " + ex.getMessage(), ex);
                }
            }
        }
    }

    //TODO: finish me!
    private static MBeanInfo info = new MBeanInfo(FxCache.class.getCanonicalName(), "[fleXive] Cache MBean",
            new MBeanAttributeInfo[] {
                    new MBeanAttributeInfo("FxCache", FxCache.class.getCanonicalName(), "", true, false, false) },
            new MBeanConstructorInfo[] {},
            new MBeanOperationInfo[] {
                    new MBeanOperationInfo("get", "",
                            new MBeanParameterInfo[] { new MBeanParameterInfo("path", "java.lang.String", ""),
                                    new MBeanParameterInfo("key", "java.lang.Object", "") },
                            "java.lang.Object", MBeanOperationInfo.INFO),
                    new MBeanOperationInfo("put", "",
                            new MBeanParameterInfo[] { new MBeanParameterInfo("path", "java.lang.String", ""),
                                    new MBeanParameterInfo("key", "java.lang.Object", ""),
                                    new MBeanParameterInfo("value", "java.lang.Object", "") },
                            "void", MBeanOperationInfo.ACTION) },
            new MBeanNotificationInfo[] {});

    /**
     * {@inheritDoc}
     */
    @Override
    public String getDeploymentId() {
        return MBeanHelper.DEPLOYMENT_ID;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Cache<Object, Object> getCache() throws FxCacheException {
        return getBackingCache().getCache();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object get(String path, Object key) throws FxCacheException {
        return getBackingCache().get(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object globalGet(String path, Object key) throws FxCacheException {
        return getBackingCache().get(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean globalExists(String path, Object key) throws FxCacheException {
        return getBackingCache().exists(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void put(String path, Object key, Object value) throws FxCacheException {
        getBackingCache().put(path, key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean exists(String path, Object key) throws FxCacheException {
        return getBackingCache().exists(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void globalPut(String path, Object key, Object value) throws FxCacheException {
        getBackingCache().put(path, key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void remove(String path) throws FxCacheException {
        getBackingCache().remove(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void globalRemove(String path) throws FxCacheException {
        getBackingCache().remove(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getKeys(String path) throws FxCacheException {
        return getBackingCache().getKeys(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set globalGetKeys(String path) throws FxCacheException {
        return getBackingCache().getKeys(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getChildrenNames(String path) throws FxCacheException {
        return getBackingCache().getChildrenNames(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void remove(String path, Object key) throws FxCacheException {
        getBackingCache().remove(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void globalRemove(String path, Object key) throws FxCacheException {
        getBackingCache().remove(path, key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void reloadEnvironment(Integer divisionId) throws Exception {
        StructureLoader.load(divisionId, true, null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setEvictionStrategy(Integer divisionId, String path, Integer maxContents, Integer timeToIdle,
            Integer timeToLive) throws FxCacheException {
        setEvictionStrategy(divisionId, path, maxContents, timeToIdle, timeToLive, true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setEvictionStrategy(Integer divisionId, String path, Integer maxContents, Integer timeToIdle,
            Integer timeToLive, Boolean overwrite) throws FxCacheException {
        cacheProvider.setEvictionStrategy("/Division" + divisionId + (path.charAt(0) == '/' ? path : '/' + path),
                maxContents, timeToIdle, timeToLive, overwrite);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getSystemStartTime() {
        try {
            return (Long) getBackingCache().get("/" + this.getClass().getName(), SYSTEM_UP_KEY);
        } catch (Exception exc) {
            return -1;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getNodeStartTime() {
        return nodeStartupTime;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getAttribute(String attribute)
            throws AttributeNotFoundException, MBeanException, ReflectionException {
        /*if ("FxCache".equals(attribute))
        return getCache();
        else*/
        if ("DeploymentId".equals(attribute))
            return getDeploymentId();
        else if ("SystemStartTime".equals(attribute))
            return getSystemStartTime();
        else if ("NodeStartTime".equals(attribute))
            return getNodeStartTime();
        return null; //To change body of implemented methods use File | Settings | File Templates.
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setAttribute(Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        //TODO: code me!
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeList getAttributes(String[] attributes) {
        //TODO: code me!
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        //TODO: code me!
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void cleanupAfterRequest() throws FxCacheException {
        getBackingCache().getCache().setInvocationContext(null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isPathLockedInTx(String path) throws FxCacheException {
        return getBackingCache().isPathLockedInTx(path);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object invoke(String actionName, Object params[], String signature[])
            throws MBeanException, ReflectionException {
        try {
            if ("get".equals(actionName)) {
                return get((String) params[0], params[1]);
            } else if ("put".equals(actionName)) {
                put((String) params[0], params[1], params[2]);
            } else if ("remove".equals(actionName) && params.length == 1) {
                remove((String) params[0]);
            } else if ("remove".equals(actionName) && params.length == 2) {
                remove((String) params[0], params[1]);
            } else if ("exists".equals(actionName) && params.length == 2) {
                return exists((String) params[0], params[1]);
            } else if ("getKeys".equals(actionName)) {
                return getKeys((String) params[0]);
            } else if ("globalGet".equals(actionName)) {
                return globalGet((String) params[0], params[1]);
            } else if ("globalPut".equals(actionName)) {
                globalPut((String) params[0], params[1], params[2]);
            } else if ("globalRemove".equals(actionName) && params.length == 1) {
                globalRemove((String) params[0]);
            } else if ("globalRemove".equals(actionName) && params.length == 2) {
                globalRemove((String) params[0], params[1]);
            } else if ("globalExists".equals(actionName) && params.length == 2) {
                return globalExists((String) params[0], params[1]);
            } else if ("globalGetKeys".equals(actionName) && params.length == 1) {
                return globalGetKeys((String) params[0]);
            } else if ("getChildrenNames".equals(actionName)) {
                return getChildrenNames((String) params[0]);
            } else if ("reloadEnvironment".equals(actionName)) {
                reloadEnvironment((Integer) params[0]);
            } else if ("create".equals(actionName)) {
                create();
            } else if ("destroy".equals(actionName)) {
                destroy();
            } else if ("setEvictionStrategy".equals(actionName) && params.length == 5) {
                setEvictionStrategy((Integer) params[0], (String) params[1], (Integer) params[2],
                        (Integer) params[3], (Integer) params[4]);
            } else if ("setEvictionStrategy".equals(actionName) && params.length == 6) {
                setEvictionStrategy((Integer) params[0], (String) params[1], (Integer) params[2],
                        (Integer) params[3], (Integer) params[4], (Boolean) params[5]);
            } else if ("cleanupAfterRequest".equals(actionName)) {
                cleanupAfterRequest();
            } else if ("isPathLockedInTx".equals(actionName)) {
                return isPathLockedInTx((String) params[0]);
            } else {
                LOG.warn("Tried to call [" + actionName + "] which is not implemented!");
            }
        } catch (Exception e) {
            LOG.error("Failed to invoke MBean op: " + e.getMessage());
            throw new MBeanException(e);
        }
        return null; //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        return info;
    }
}