Java tutorial
/* * RED5 Open Source Flash Server - https://github.com/Red5/ * * Copyright 2006-2016 by respective authors (see below). All rights reserved. * * Licensed 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.red5.server.util; import java.lang.reflect.Field; import java.util.Arrays; import org.red5.server.api.IContext; import org.red5.server.api.persistence.IPersistable; import org.red5.server.api.scope.IBasicScope; import org.red5.server.api.scope.IScope; import org.red5.server.api.scope.IScopeHandler; import org.red5.server.api.scope.IScopeService; import org.red5.server.api.scope.ScopeType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; /** * Collection of utilities for working with scopes */ public class ScopeUtils { private static final Logger log = LoggerFactory.getLogger(ScopeUtils.class); 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) { log.debug("resolveScope from: {} path: {}", from.getName(), 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); } log.trace("Current: {}", current); String[] parts = path.split(SLASH); if (log.isTraceEnabled()) { log.trace("Parts: {}", Arrays.toString(parts)); } for (String part : parts) { log.trace("Part: {}", part); 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); log.trace("Current: {}", current); } 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 * * <pre> * isApp * </pre> * * 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.getType().equals(ScopeType.APPLICATION)) { current = current.getParent(); } return current; } /** * Check whether one scope is an ancestor of another * * @param from * Scope * @param ancestor * Scope to check * @return <pre> * true * </pre> * * if ancestor scope is really an ancestor of scope passed as from parameter, * * <pre> * false * </pre> * * 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 <pre> * true * </pre> * * if scope is root scope (top level scope), * * <pre> * false * </pre> * * 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 <pre> * true * </pre> * * if scope is the global scope, * * <pre> * false * </pre> * * otherwise. */ public static boolean isGlobal(IBasicScope scope) { return scope.getType().equals(ScopeType.GLOBAL); } /** * Check whether scope is an application scope (level 1 leaf in scope tree) or not * * @param scope * Scope to check * @return <pre> * true * </pre> * * if scope is an application scope, * * <pre> * false * </pre> * * otherwise. */ public static boolean isApp(IBasicScope scope) { return scope.getType().equals(ScopeType.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 <pre> * true * </pre> * * if scope is a room scope, * * <pre> * false * </pre> * * otherwise. */ public static boolean isRoom(IBasicScope scope) { return scope.getType().equals(ScopeType.ROOM); } /** * Returns scope service by bean name. See overloaded method for details. * * @param scope * scope * @param name * name * @return object */ 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) { 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; } return null; } /** * 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(); String attr = IPersistable.TRANSIENT_PREFIX + SERVICE_CACHE_PREFIX + intf.getCanonicalName(); if (scope.hasAttribute(attr)) { // return cached service return scope.getAttribute(attr); } 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've 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) { handler = getScopeService(scope, (String) serviceName, defaultClass); } } catch (Exception e) { log.debug("No string field 'BEAN_NAME' in that interface"); } } if (handler == null && defaultClass != null) { try { handler = defaultClass.newInstance(); } catch (Exception e) { log.error("", e); } } // cache service scope.setAttribute(attr, handler); return handler; } }