Java tutorial
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; } }