
org.smallmind.phalanx.wire.WireInvocationCircuit Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of smallmind-phalanx Show documentation
Show all versions of smallmind-phalanx Show documentation
Clustering and Coordination Frameworks
/*
* Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 David Berkman
*
* This file is part of the SmallMind Code Project.
*
* The SmallMind Code Project is free software, you can redistribute
* it and/or modify it under either, at your discretion...
*
* 1) The terms of GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* ...or...
*
* 2) The terms of the Apache License, Version 2.0.
*
* The SmallMind Code Project 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
* General Public License or Apache License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and the Apache License along with the SmallMind Code Project. If not, see
* or .
*
* Additional permission under the GNU Affero GPL version 3 section 7
* ------------------------------------------------------------------
* If you modify this Program, or any covered work, by linking or
* combining it with other code, such other code is not for that reason
* alone subject to any of the requirements of the GNU Affero GPL
* version 3.
*/
package org.smallmind.phalanx.wire;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.smallmind.scribe.pen.LoggerManager;
import org.smallmind.web.jersey.fault.Fault;
import org.smallmind.web.jersey.fault.FaultElement;
import org.smallmind.web.jersey.fault.FaultWrappingException;
public class WireInvocationCircuit {
private final ConcurrentHashMap invokerMap = new ConcurrentHashMap<>();
public void register (Class> serviceInterface, WiredService targetService)
throws NoSuchMethodException, ServiceDefinitionException {
invokerMap.putIfAbsent(new ServiceKey(targetService.getVersion(), targetService.getServiceName()), new MethodInvoker(targetService, serviceInterface));
}
public void handle (ResponseTransport transport, SignalCodec signalCodec, String callerId, String messageId, InvocationSignal invocationSignal) {
MethodInvoker methodInvoker;
Object result = null;
String nativeType = null;
boolean error = false;
try {
try {
Function invocationFunction;
Methodology methodology;
Object[] arguments;
if ((methodInvoker = invokerMap.get(new ServiceKey(invocationSignal.getAddress().getVersion(), invocationSignal.getAddress().getService()))) == null) {
throw new ServiceDefinitionException("Unregistered service(version = %d, name = %s)", invocationSignal.getAddress().getVersion(), invocationSignal.getAddress().getService());
}
if ((invocationFunction = invocationSignal.getAddress().getFunction()).isPartial()) {
Function completeFunction;
if ((completeFunction = methodInvoker.match(invocationFunction)) == null) {
throw new MissingInvocationException("Unable to locate the proper method for the partial function(%s) of service(%s)", invocationFunction.getName(), invocationSignal.getAddress().getService());
}
invocationFunction = completeFunction;
}
methodology = methodInvoker.getMethodology(invocationFunction);
arguments = new Object[invocationFunction.getSignature().length];
if (invocationSignal.getArguments() != null) {
for (Map.Entry argumentEntry : invocationSignal.getArguments().entrySet()) {
ArgumentInfo argumentInfo;
if ((argumentInfo = methodology.getArgumentInfo(argumentEntry.getKey())) == null) {
throw new MismatchedArgumentException("Invocation argument(%s) on method(%s) of service(%s) can't be matched by name", argumentEntry.getKey(), invocationFunction.getName(), invocationSignal.getAddress().getService());
}
if (argumentInfo.getIndex() >= arguments.length) {
throw new MismatchedArgumentException("Invocation argument(%s) on method(%s) of service(%s) maps to a non-existent argument index(%d)", argumentEntry.getKey(), invocationFunction.getName(), invocationSignal.getAddress().getService(), argumentInfo.getIndex());
}
arguments[argumentInfo.getIndex()] = signalCodec.extractObject(argumentEntry.getValue(), argumentInfo.getParameterType());
}
}
nativeType = invocationFunction.getNativeType();
result = methodInvoker.remoteInvocation(invocationSignal.getContexts(), invocationFunction, arguments);
if ((result != null) && (!(result instanceof Serializable))) {
throw new TransportException("The result(%s) of this call is not Serializable", result.getClass().getName());
}
} catch (Exception exception) {
if (!invocationSignal.isInOnly()) {
error = true;
result = (exception instanceof FaultWrappingException) ? ((FaultWrappingException)exception).getFault() : new Fault(new FaultElement(invocationSignal.getAddress().getService(), invocationSignal.getAddress().getFunction().getName()), exception);
}
}
if (!invocationSignal.isInOnly()) {
transport.transmit(callerId, messageId, error, nativeType, result);
}
} catch (Throwable throwable) {
LoggerManager.getLogger(WireInvocationCircuit.class).error(throwable);
}
}
private static class ServiceKey {
private String service;
private int version;
private ServiceKey (int version, String service) {
this.version = version;
this.service = service;
}
public String getService () {
return service;
}
public int getVersion () {
return version;
}
@Override
public int hashCode () {
return service.hashCode() ^ version;
}
@Override
public boolean equals (Object obj) {
return (obj instanceof ServiceKey) && ((ServiceKey)obj).getService().equals(service) && (((ServiceKey)obj).getVersion() == version);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy