/*
*
*/
package org.smartly.commons.remoting.rpc;
import org.smartly.commons.logging.Level;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.logging.util.LoggingUtils;
import org.smartly.commons.util.BeanUtils;
import org.smartly.commons.util.CollectionUtils;
import org.smartly.commons.util.StringUtils;
import org.smartly.commons.remoting.rpc.descriptor.*;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Services are registered into internal Map with a compound key ("endpoint.name")
*
* @author angelo.geminiani
*/
public class RemoteServiceRepository {
private static final String SEP = ".";
private final Map<String, ServiceDescriptor> _services;
public RemoteServiceRepository() {
_services = Collections.synchronizedMap(new HashMap<String, ServiceDescriptor>());
}
public ServiceDescriptor getService(final String endpoint,
final String serviceName) {
synchronized (_services) {
final String name = this.getName(endpoint, serviceName);
return _services.get(name);
}
}
public void registerService(final String name,
final Class<?> serviceClass)
throws Exception {
this.registerService("", name,
this.getServiceFromClass(name, serviceClass));
}
public void registerService(final String endpoint,
final String name,
final Class<?> serviceClass)
throws Exception {
this.registerService(endpoint, name,
this.getServiceFromClass(name, serviceClass));
}
public ServiceDescriptor registerService(final String endpoint,
final String serviceName,
final ServiceDescriptor service) throws Exception {
final String name = this.getName(endpoint, serviceName);
synchronized (_services) {
final ServiceDescriptor exists = _services.get(name);
if (exists != null && exists != service) {
throw new Exception("different service already registered as " + name);
}
if (exists == null) {
_services.put(name, service);
}
}
final Logger logger = this.getLogger();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE,
"registered service {0} as {1}",
new Object[]{service.getName(), name});
}
return service;
}
/**
* Unregisters a class exported with registerClass. <p/> The JSONBridge will
* unexport all static methods of the class.
*
* @param serviceName The registered name of the class to unexport static methods
* from.
*/
public void unregisterService(final String endpoint,
final String serviceName) {
synchronized (_services) {
final String name = this.getName(endpoint, serviceName);
final ServiceDescriptor service = _services.get(name);
if (service != null) {
_services.remove(name);
final Logger logger = this.getLogger();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE,
"unregistered class {0} from {1}",
new Object[]{service.getName(), name});
}
}
}
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private Logger getLogger() {
return LoggingUtils.getLogger(this);
}
private String getName(final String endpoint,
final String serviceName) {
if (StringUtils.hasText(endpoint)) {
return endpoint.concat(SEP).concat(serviceName);
} else {
return serviceName;
}
}
private ServiceDescriptor getServiceFromClass(final String name,
final Class<?> aclass) {
final ServiceDescriptor service = new ServiceDescriptor(name);
service.setServiceClass(aclass);
// methods
final Method[] methods = BeanUtils.getPublicMethods(aclass);
if (methods.length > 0) {
for (final Method method : methods) {
final String methodname = method.getName();
final Class[] types = method.getParameterTypes();
final MethodDescriptor restmethod = service.getOrCreateMethod(methodname);
if (!CollectionUtils.isEmpty(types)) {
for (int i = 0; i < types.length; i++) {
final Class ctype = types[i];
// add parameter
restmethod.addParameter(ctype);
}
}
}
}
return service;
}
// ------------------------------------------------------------------------
// S T A T I C
// ------------------------------------------------------------------------
/**
* Global bridge (for exporting to all users)
*/
private final static RemoteServiceRepository _instance = new RemoteServiceRepository();
/**
* This method retrieves the global bridge singleton. <p/> It should be used
* with care as objects should generally be registered within session specific
* bridges for security reasons.
*
* @return returns the global bridge object.
*/
public static RemoteServiceRepository getInstance() {
return _instance;
}
}