/* * Copyright (C) 2012 Red Hat, Inc. and/or its affiliates. * * 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.jboss.errai.bus.server.io; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.jboss.errai.bus.client.api.base.MessageDeliveryFailure; import org.jboss.errai.bus.client.api.messaging.Message; import org.jboss.errai.bus.client.api.messaging.MessageCallback; public class CommandBindingsCallback extends MethodBindingCallback { private final Map<String, MethodDispatcher> methodDispatchers; private final MessageCallback defaultCallback; private final boolean defaultAction; public CommandBindingsCallback(final Map<String, Method> commandBindings, final Object delegate) { this.methodDispatchers = new HashMap<String, MethodDispatcher>(commandBindings.size() * 2); this.defaultAction = delegate instanceof MessageCallback; this.defaultCallback = defaultAction ? (MessageCallback) delegate : null; for (final Map.Entry<String, Method> entry : commandBindings.entrySet()) { final Method method = entry.getValue(); final Class<?>[] parmTypes = method.getParameterTypes(); verifyMethodSignature(method); method.setAccessible(true); methodDispatchers.put(entry.getKey(), parmTypes.length == 0 ? new NoParamMethodDispatcher(delegate, method) : new DefaultMethodDispatcher(delegate, method)); } } public void callback(final Message message) { final MethodDispatcher method = methodDispatchers.get(message.getCommandType()); try { if (method == null) { if (defaultAction) { defaultCallback.callback(message); } else { throw new MessageDeliveryFailure(String.format("Unrecognized command, %s, in service %s", message.getCommandType(), message.getSubject())); } } else { method.dispatch(message); } } catch (MessageDeliveryFailure e) { throw e; } catch (Exception e) { maybeUnwrapAndThrowError(e); } } private abstract class MethodDispatcher { protected Object delegate; protected Method method; protected MethodDispatcher(final Object delegate, final Method method) { this.delegate = delegate; this.method = method; } abstract void dispatch(Message m) throws Exception; } private class NoParamMethodDispatcher extends MethodDispatcher { NoParamMethodDispatcher(final Object delegate, final Method method) { super(delegate, method); } @Override void dispatch(final Message m) throws Exception { method.invoke(delegate); } } private class DefaultMethodDispatcher extends MethodDispatcher { DefaultMethodDispatcher(final Object delegate, final Method method) { super(delegate, method); } @Override void dispatch(final Message m) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { method.invoke(delegate, m); } } }