/****************************************************************************
* Copyright (C) 2012 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
* This file is part of the Open eCard App.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License version 3.0 as published by the Free Software Foundation
* and appearing in the file LICENSE.GPL included in the packaging of
* this file. Please review the following information to ensure the
* GNU General Public License version 3.0 requirements will be met:
* http://www.gnu.org/copyleft/gpl.html.
*
* Other Usage
* Alternatively, this file may be used in accordance with the terms
* and conditions contained in a signed written agreement between
* you and ecsec GmbH.
*
***************************************************************************/
package org.openecard.transport.dispatcher;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;
import org.openecard.common.interfaces.DispatcherException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service class encapsulating one webservice for the {@link MessageDispatcher}.
* This class takes care of the actual interface analysis and reflection part.
*
* @author Tobias Wich <tobias.wich@ecsec.de>
*/
class Service {
private static final Logger logger = LoggerFactory.getLogger(Service.class);
private final Class iface;
private final ArrayList<Class> requestClasses;
private final TreeMap<String, Method> requestMethods;
/**
* Creates a new Service instance and initializes it with the given webservice interface class.
*
* @param iface The webservice interface class.
*/
public Service(Class iface) {
this.iface = iface;
requestClasses = new ArrayList<Class>();
requestMethods = new TreeMap<String, Method>();
Method[] methods = iface.getDeclaredMethods();
for (Method m : methods) {
if (isReqParam(m)) {
Class reqClass = getReqParamClass(m);
if (requestMethods.containsKey(reqClass.getName())) {
String msg = "Omitting method {} in service interface {}, because its parameter type is already ";
msg += "associated with another method.";
logger.warn(msg, m.getName(), iface.getName());
} else {
requestClasses.add(reqClass);
requestMethods.put(reqClass.getName(), m);
}
}
}
}
/**
* Gets the webservice interface class this instance is initialized with.
*
* @return The webservice interface belonging to this instance.
*/
public Class getServiceInterface() {
return iface;
}
/**
* Invokes the webservice method related to the request object in the given webservice class instance.
*
* @param ifaceImpl The instance implementing the webservice interface this instance is responsible for.
* @param req The request object to dispatch.
* @return The result of the method invocation.
* @throws DispatcherException In case an error happens in the reflections part of the dispatcher.
* @throws InvocationTargetException In case the dispatched method throws en exception.
*/
public Object invoke(Object ifaceImpl, Object req) throws DispatcherException, InvocationTargetException {
try {
Class reqClass = req.getClass();
Method m = getMethod(reqClass.getName());
// invoke method
return m.invoke(ifaceImpl, req);
} catch (IllegalAccessException ex) {
throw new DispatcherException(ex);
} catch (NoSuchMethodException ex) {
throw new DispatcherException(ex);
} catch (IllegalArgumentException ex) {
throw new DispatcherException(ex);
}
}
private Class getReqParamClass(Method m) {
// get parameters of this method
Class[] params = m.getParameterTypes();
// methods must have exactly one parameter
if (params.length != 1) {
return null;
}
// TODO: add other checks
return params[0];
}
private boolean isReqParam(Method m) {
return getReqParamClass(m) != null;
}
public List<Class> getRequestClasses() {
return Collections.unmodifiableList(requestClasses);
}
private Method getMethod(String paramClass) throws NoSuchMethodException {
Method m = requestMethods.get(paramClass);
if (m == null) {
String msg = "Method containing parameter with class '" + paramClass + "' does not exist in interface '";
msg += iface.getName() + "'.";
throw new NoSuchMethodException(msg);
}
return m;
}
}