org.red5.server.api.ScopeUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.red5.server.api.ScopeUtils.java

Source

package org.red5.server.api;

/*
 * RED5 Open Source Flash Server - http://www.osflash.org/red5
 *
 * Copyright (c) 2006-2007 by respective authors (see below). All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any later
 * version.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

import java.lang.reflect.Field;

import org.apache.log4j.Logger;
import org.red5.server.api.persistence.IPersistable;
import org.springframework.context.ApplicationContext;

/**
 * Collection of utils for working with scopes
 */
public class ScopeUtils {

    private static final Logger log = Logger.getLogger(ScopeUtils.class);

    private static final int GLOBAL = 0x00;

    private static final int APPLICATION = 0x01;

    private static final int ROOM = 0x02;

    private static final String SERVICE_CACHE_PREFIX = "__service_cache:";

    /**
     * Constant for slash symbol
     */
    private static final String SLASH = "/";

    /**
     * Resolves scope for specified scope and path.
     *
     * @param from
     *            Scope to use as context (to start from)
     * @param path
     *            Path to resolve
     * @return   Resolved scope
     */
    public static IScope resolveScope(IScope from, String path) {
        IScope current = from;
        if (path.startsWith(SLASH)) {
            current = ScopeUtils.findRoot(current);
            path = path.substring(1, path.length());
        }
        if (path.endsWith(SLASH)) {
            path = path.substring(0, path.length() - 1);
        }
        String[] parts = path.split(SLASH);
        for (String part : parts) {
            if (part.equals(".")) {
                continue;
            }
            if (part.equals("..")) {
                if (!current.hasParent()) {
                    return null;
                }
                current = current.getParent();
                continue;
            }
            if (!current.hasChildScope(part)) {
                return null;
            }
            current = current.getScope(part);
        }
        return current;
    }

    /**
     * Finds root scope for specified scope object. Root scope is the top level
     * scope among scope's parents.
     *
     * @param from
     *            Scope to find root for
     * @return   Root scope object
     */
    public static IScope findRoot(IScope from) {
        IScope current = from;
        while (current.hasParent()) {
            current = current.getParent();
        }
        return current;
    }

    /**
     * Returns the application scope for specified scope. Application scope has
     * depth of 1 and has no parent.
     *
     * See <code>isApp</code> method for details.
     *
     * @param from
     *            Scope to find application for
     * @return      Application scope.
     */
    public static IScope findApplication(IScope from) {
        IScope current = from;
        while (current.hasParent() && current.getDepth() != APPLICATION) {
            current = current.getParent();
        }
        return current;
    }

    /**
     * Check whether one scope is an ancestor of another
     *
     * @param from
     *            Scope
     * @param ancestor
     *            Scope to check
     * @return <code>true</code> if ancestor scope is really an ancestor of
     *         scope passed as from parameter, <code>false</code> otherwise.
     */
    public static boolean isAncestor(IBasicScope from, IBasicScope ancestor) {
        IBasicScope current = from;
        while (current.hasParent()) {
            current = current.getParent();
            if (current.equals(ancestor)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks whether scope is root or not
     *
     * @param scope
     *            Scope to check
     * @return <code>true</code> if scope is root scope (top level scope),
     *         <code>false</code> otherwise.
     */
    public static boolean isRoot(IBasicScope scope) {
        return !scope.hasParent();
    }

    /**
     * Check whether scope is the global scope (level 0 leaf in scope tree) or
     * not
     *
     * When user connects the following URL: rtmp://localhost/myapp/foo/bar then /
     * is the global level scope, myapp is app level, foo is room level and bar
     * is room level as well (but with higher depth level)
     *
     * @param scope
     *            Scope to check
     * @return <code>true</code> if scope is the global scope,
     *         <code>false</code> otherwise.
     */
    public static boolean isGlobal(IBasicScope scope) {
        return scope.getDepth() == GLOBAL;
    }

    /**
     * Check whether scope is an application scope (level 1 leaf in scope tree)
     * or not
     *
     * @param scope
     *            Scope to check
     * @return <code>true</code> if scope is an application scope,
     *         <code>false</code> otherwise.
     */
    public static boolean isApp(IBasicScope scope) {
        return scope.getDepth() == APPLICATION;
    }

    /**
     * Check whether scope is a room scope (level 2 leaf in scope tree or lower,
     * e.g. 3, 4, ...) or not
     *
     * @param scope
     *            Scope to check
     * @return <code>true</code> if scope is a room scope, <code>false</code>
     *         otherwise.
     */
    public static boolean isRoom(IBasicScope scope) {
        return scope.getDepth() >= ROOM;
    }

    /**
     * Returns scope service by bean name. See overloaded method for details.
     *
     * @param scope
     * @param name
     * @return
     */
    protected static Object getScopeService(IScope scope, String name) {
        return getScopeService(scope, name, null);
    }

    /**
     * Returns scope services (e.g. SharedObject, etc) for the scope. Method
     * uses either bean name passes as a string or class object.
     *
     * @param scope
     *            The scope service belongs to
     * @param name
     *            Bean name
     * @param defaultClass
     *            Class of service
     * @return            Service object
     */
    protected static Object getScopeService(IScope scope, String name, Class defaultClass) {
        if (scope == null) {
            return null;
        }

        final IContext context = scope.getContext();
        ApplicationContext appCtx = context.getApplicationContext();
        Object result;
        if (!appCtx.containsBean(name)) {
            if (defaultClass == null) {
                return null;
            }

            try {
                result = defaultClass.newInstance();
            } catch (Exception e) {
                log.error(e);
                return null;
            }
        } else {
            result = appCtx.getBean(name);
        }

        return result;
    }

    /**
     * Returns scope service that implements a given interface.
     *
     * @param scope
     *            The scope service belongs to
     * @param intf
     *            The interface the service must implement
     * @return Service object
     */
    public static Object getScopeService(IScope scope, Class intf) {
        return getScopeService(scope, intf, null);
    }

    public static Object getScopeService(IScope scope, Class intf, boolean checkHandler) {
        return getScopeService(scope, intf, null, checkHandler);
    }

    /**
     * Returns scope service that implements a given interface.
     *
     * @param scope
     *            The scope service belongs to
     * @param intf
     *            The interface the service must implement
     * @param defaultClass
     *            Class that should be used to create a new service if no service was found.
     * @return Service object
     */
    public static Object getScopeService(IScope scope, Class intf, Class defaultClass) {
        return getScopeService(scope, intf, defaultClass, true);
    }

    public static Object getScopeService(IScope scope, Class intf, Class defaultClass, boolean checkHandler) {
        if (scope == null || intf == null) {
            return null;
        }
        // We expect an interface
        assert intf.isInterface();

        if (scope.hasAttribute(IPersistable.TRANSIENT_PREFIX + SERVICE_CACHE_PREFIX + intf.getCanonicalName())) {
            // Return cached service
            return scope
                    .getAttribute(IPersistable.TRANSIENT_PREFIX + SERVICE_CACHE_PREFIX + intf.getCanonicalName());
        }

        Object handler = null;
        if (checkHandler) {
            IScope current = scope;
            while (current != null) {
                IScopeHandler scopeHandler = current.getHandler();
                if (intf.isInstance(scopeHandler)) {
                    handler = scopeHandler;
                    break;
                }

                if (!current.hasParent())
                    break;

                current = current.getParent();
            }
        }

        if (handler == null && IScopeService.class.isAssignableFrom(intf)) {
            // We got an IScopeService, try to lookup bean
            Field key = null;
            Object serviceName = null;
            try {
                key = intf.getField("BEAN_NAME");
                serviceName = key.get(null);
                if (!(serviceName instanceof String))
                    serviceName = null;
            } catch (Exception e) {
                log.debug("No string field 'BEAN_NAME' in that interface");
            }

            if (serviceName != null)
                handler = getScopeService(scope, (String) serviceName, defaultClass);
        }

        if (handler == null && defaultClass != null) {
            try {
                handler = defaultClass.newInstance();
            } catch (Exception e) {
                log.error(e);
            }
        }

        // Cache service
        scope.setAttribute(IPersistable.TRANSIENT_PREFIX + SERVICE_CACHE_PREFIX + intf.getCanonicalName(), handler);
        return handler;
    }

}