package org.oddjob.jmx;
import org.oddjob.arooa.reflect.ArooaPropertyException;
import org.oddjob.arooa.registry.Address;
import org.oddjob.arooa.registry.BeanDirectory;
import org.oddjob.arooa.registry.BeanDirectoryOwner;
import org.oddjob.arooa.registry.Path;
import org.oddjob.arooa.registry.ServerId;
public class RemoteRegistryCrawler {
private final BeanDirectory registry;
public RemoteRegistryCrawler(BeanDirectory registry) {
this.registry = registry;
}
/**
* Helper function to convert a path for a different server into the
* path to that servers client from this registery.
*
* @param selected The current path being built up in this recursive call.
* @param serverId The server id for this current path.
*
* @return The path relative to the other server or null if the other server
* is not accessible.
*/
public BeanDirectory registryForServer(ServerId serverId) {
if (registry instanceof RemoteDirectory) {
if (((RemoteDirectory) registry).getServerId().equals(serverId)) {
return (RemoteDirectory) registry;
}
if (ServerId.local().equals(serverId)) {
return null;
}
}
else {
if (ServerId.local().equals(serverId)) {
return registry;
}
}
// go round all the child registries recursing down until we find a
// registry for the server.
for (BeanDirectoryOwner owner : registry.getAllByType(BeanDirectoryOwner.class)) {
BeanDirectory child = owner.provideBeanDirectory();
if (child == null) {
continue;
}
RemoteRegistryCrawler next = new RemoteRegistryCrawler(child);
BeanDirectory result = next.registryForServer(serverId);
if (result != null) {
return result;
}
}
return null;
}
/**
* Find the object from the possible addresses that could identify it. If
* there are several paths to the object (which can happen if the original object
* is accessible via several servers), the object with the shortest path is
* returned.
*
* @param addresses The possible addresses of the component.
* @return The component or null if none of the addresses are accessible.
*
* @throws ArooaPropertyException
*/
public Object objectForAddress(Address address) throws ArooaPropertyException {
if (address == null) {
return null;
}
BeanDirectory registry = registryForServer(address.getServerId());
if (registry == null) {
return null;
}
return registry.lookup(address.getPath().toString());
}
Address addressFor(Object component, Path path) {
if (registry instanceof RemoteDirectory) {
return null;
}
String id = registry.getIdFor(component);
if (id != null) {
return new Address(ServerId.local(), path.addId(id));
}
for (BeanDirectoryOwner owner: registry.getAllByType(BeanDirectoryOwner.class)) {
String childId = registry.getIdFor(owner);
if (childId == null) {
continue;
}
BeanDirectory child = owner.provideBeanDirectory();
if (child == null) {
continue;
}
Address result = new RemoteRegistryCrawler(
child).addressFor(component, path);
if (result != null) {
return result;
}
}
return null;
}
public Address addressFor(Object component) {
if (component instanceof RemoteOddjobBean) {
return ((RemoteOddjobBean) component).serverInfo().getAddress();
}
return addressFor(component, new Path());
}
}