Java tutorial
package org.red5.server.service; /* * 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.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.red5.server.api.IConnection; import org.red5.server.api.IScope; import org.red5.server.api.Red5; import org.red5.server.api.service.IPendingServiceCall; import org.red5.server.api.service.IServiceCall; import org.red5.server.api.service.IServiceInvoker; /** * Makes remote calls, invoking services, resolves service handlers * * @author The Red5 Project (red5@osflash.org) * @author Luke Hubbard, Codegent Ltd (luke@codegent.com) */ public class ServiceInvoker implements IServiceInvoker { /** * Logger */ private static final Log log = LogFactory.getLog(ServiceInvoker.class); /** * Service name */ public static final String SERVICE_NAME = "serviceInvoker"; /** * Service resolvers set */ private Set<IServiceResolver> serviceResolvers = new HashSet<IServiceResolver>(); /** * Setter for service resolvers. * * @param resolvers Service resolvers */ public void setServiceResolvers(Set<IServiceResolver> resolvers) { serviceResolvers = resolvers; } /** * Lookup a handler for the passed service name in the given scope. * * @param scope Scope * @param serviceName Service name * @return Service handler */ private Object getServiceHandler(IScope scope, String serviceName) { // Get application scope handler first Object service = scope.getHandler(); if (serviceName == null || serviceName.equals("")) { // No service requested, return application scope handler return service; } // Search service resolver that knows about service name for (IServiceResolver resolver : serviceResolvers) { service = resolver.resolveService(scope, serviceName); if (service != null) { return service; } } // Requested service does not exist. return null; } /** {@inheritDoc} */ public boolean invoke(IServiceCall call, IScope scope) { String serviceName = call.getServiceName(); if (log.isDebugEnabled()) { log.debug("Service name " + serviceName); } Object service = getServiceHandler(scope, serviceName); if (service == null) { // Exception must be thrown if service was not found call.setException(new ServiceNotFoundException(serviceName)); // Set call status call.setStatus(Call.STATUS_SERVICE_NOT_FOUND); log.warn("Service not found: " + serviceName); return false; } else { if (log.isDebugEnabled()) { log.debug("Service found: " + serviceName); } } // Invoke if everything is ok return invoke(call, service); } /** {@inheritDoc} */ public boolean invoke(IServiceCall call, Object service) { IConnection conn = Red5.getConnectionLocal(); String methodName = call.getServiceMethodName(); Object[] args = call.getArguments(); Object[] argsWithConnection; if (args != null) { argsWithConnection = new Object[args.length + 1]; argsWithConnection[0] = conn; for (int i = 0; i < args.length; i++) { if (log.isDebugEnabled()) { log.debug(" " + i + " => " + args[i]); } argsWithConnection[i + 1] = args[i]; } } else { argsWithConnection = new Object[] { conn }; } Object[] methodResult = null; // First, search for method with the connection as first parameter. methodResult = ServiceUtils.findMethodWithExactParameters(service, methodName, argsWithConnection); if (methodResult.length == 0 || methodResult[0] == null) { // Second, search for method without the connection as first // parameter. methodResult = ServiceUtils.findMethodWithExactParameters(service, methodName, args); if (methodResult.length == 0 || methodResult[0] == null) { // Third, search for method with the connection as first // parameter in a list argument. methodResult = ServiceUtils.findMethodWithListParameters(service, methodName, argsWithConnection); if (methodResult.length == 0 || methodResult[0] == null) { // Fourth, search for method without the connection as first // parameter in a list argument. methodResult = ServiceUtils.findMethodWithListParameters(service, methodName, args); if (methodResult.length == 0 || methodResult[0] == null) { log.error("Method " + methodName + " not found in " + service); call.setStatus(Call.STATUS_METHOD_NOT_FOUND); call.setException(new MethodNotFoundException(methodName)); return false; } } } } Object result = null; Method method = (Method) methodResult[0]; Object[] params = (Object[]) methodResult[1]; try { if (log.isDebugEnabled()) { log.debug("Invoking method: " + method.toString()); } if (method.getReturnType() == Void.class) { method.invoke(service, params); call.setStatus(Call.STATUS_SUCCESS_VOID); } else { result = method.invoke(service, params); if (log.isDebugEnabled()) { log.debug("result: " + result); } call.setStatus(result == null ? Call.STATUS_SUCCESS_NULL : Call.STATUS_SUCCESS_RESULT); } if (call instanceof IPendingServiceCall) { ((IPendingServiceCall) call).setResult(result); } } catch (IllegalAccessException accessEx) { call.setException(accessEx); call.setStatus(Call.STATUS_ACCESS_DENIED); log.error("Error executing call: " + call); log.error("Service invocation error", accessEx); return false; } catch (InvocationTargetException invocationEx) { call.setException(invocationEx); call.setStatus(Call.STATUS_INVOCATION_EXCEPTION); log.error("Error executing call: " + call); log.error("Service invocation error", invocationEx); return false; } catch (Exception ex) { call.setException(ex); call.setStatus(Call.STATUS_GENERAL_EXCEPTION); log.error("Error executing call: " + call); log.error("Service invocation error", ex); return false; } return true; } }