Package org.red5.server.util

Source Code of org.red5.server.util.ScopeUtils

/*
* RED5 Open Source Flash Server - http://code.google.com/p/red5/
*
* Copyright 2006-2014 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 <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.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 <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.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 <code>true</code> if scope is an application scope,
   *         <code>false</code> 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 <code>true</code> if scope is a room scope, <code>false</code>
   *         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;
  }

}
TOP

Related Classes of org.red5.server.util.ScopeUtils

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.