package org.jboss.remoting.detection.jndi;
import org.jboss.logging.Logger;
import org.jboss.remoting.InvokerLocator;
import org.jboss.remoting.InvokerRegistry;
import org.jboss.remoting.detection.AbstractDetector;
import org.jboss.remoting.detection.Detection;
import org.jboss.remoting.ident.Identity;
import org.jnp.interfaces.NamingContextFactory;
import org.jnp.server.Main;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import java.util.Properties;
public class JNDIDetector extends AbstractDetector implements JNDIDetectorMBean
{
private int port;
private String host;
private String contextFactory = NamingContextFactory.class.getName();;
private String urlPackage = "org.jboss.naming:org.jnp.interfaces";;
private Identity id;
private Context context;
private int cleanDetectionCount = 0;
public static final String DETECTION_SUBCONTEXT_NAME = "detection";
private int detectionNumber = 5;
protected final Logger log = Logger.getLogger(getClass());
public int getPort()
{
return port;
}
public void setPort(int port)
{
this.port = port;
}
public String getHost()
{
return host;
}
public void setHost(String host)
{
this.host = host;
}
public String getContextFactory()
{
return contextFactory;
}
public void setContextFactory(String contextFactory)
{
this.contextFactory = contextFactory;
}
public String getURLPackage()
{
return urlPackage;
}
public void setURLPackage(String urlPackage)
{
this.urlPackage = urlPackage;
}
public void start() throws Exception
{
createContext();
id = Identity.get(mbeanserver);
super.start();
}
protected void heartbeat()
{
try
{
if(context == null)
{
createContext();
}
checkRemoteDetectionMsg();
}
catch(NamingException nex)
{
log.error("Can not connect to JNDI server to register local connectors.", nex);
}
}
public int getCleanDetectionNumber()
{
return detectionNumber;
}
public void setCleanDetectionNumber(int cleanDetectionNumber)
{
detectionNumber = cleanDetectionNumber;
}
private void checkRemoteDetectionMsg()
{
try
{
boolean localFound = false;
cleanDetectionCount++;
boolean cleanDetect = cleanDetectionCount > detectionNumber;
String bindName = "";
NamingEnumeration enum = context.listBindings(bindName);
while(enum.hasMore())
{
Binding binding = (Binding) enum.next();
Detection regMsg = (Detection) binding.getObject();
if(isRemoteDetection(regMsg))
{
if(log.isDebugEnabled())
{
log.debug("Detected id: " + regMsg.getIdentity().getInstanceId() + ", message: " + regMsg);
}
if(cleanDetect)
{
if(log.isDebugEnabled())
{
log.debug("Doing clean detection.");
}
ClassLoader cl = JNDIDetector.this.getClass().getClassLoader();
if(!checkInvokerServer(regMsg, cl))
{
unregisterDetection(regMsg.getIdentity().getInstanceId());
}
}
else
{
detect(regMsg);
}
}
else
{
if(!verifyLocalDetectionMsg(regMsg))
{
addLocalDetectionMsg();
}
localFound = true;
}
}
if(cleanDetect)
{
cleanDetectionCount = 0;
}
if(!localFound)
{
addLocalDetectionMsg();
}
}
catch(NamingException e)
{
log.error("Exception getting detection messages from JNDI server.", e);
}
}
private boolean verifyLocalDetectionMsg(Detection regMsg) throws NamingException
{
boolean verified = false;
InvokerLocator[] locators = InvokerRegistry.getRegisteredServerLocators();
Detection msg = new Detection(id, locators);
String sId = id.getInstanceId();
InvokerLocator[] invokers = regMsg.getLocators();
if(sId.equals(regMsg.getIdentity().getInstanceId()))
{
boolean changed = false;
if(locators.length != invokers.length)
{
changed = true;
}
else
{
boolean found = false; for(int i = 0; i < locators.length; i++)
{
found = false;
for(int x = 0; x < invokers.length; x++)
{
if(locators[i].equals(invokers[x]))
{
found = true;
break;
}
}
if(!found)
{
break;
}
}
if(!found)
{
changed = true;
}
}
if(changed)
{
registerDetectionMsg(sId, msg);
}
verified = true;
}
return verified;
}
private void addLocalDetectionMsg() throws NamingException
{
InvokerLocator[] locators = InvokerRegistry.getRegisteredServerLocators();
Detection msg = new Detection(id, locators);
String sId = id.getInstanceId();
registerDetectionMsg(sId, msg);
}
private void registerDetectionMsg(String sId, Detection msg) throws NamingException
{
try
{
context.bind(sId, msg);
log.info("Added " + sId + " to registry.");
}
catch(NameAlreadyBoundException nabex)
{
if(log.isDebugEnabled())
{
log.debug(sId + " already bound to server.");
}
}
}
private void verifyJNDIServer()
{
if(host == null || host.length() == 0)
{
log.info("JNDI Server configuration information not present so will create a local server.");
port = 1088;
host = "localhost";
try
{
Main server = new Main();
server.setPort(port);
server.setBindAddress(host);
server.start();
contextFactory = NamingContextFactory.class.getName();
urlPackage = "org.jboss.naming:org.jnp.interfaces";
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
private void createContext() throws NamingException
{
verifyJNDIServer();
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
env.put(Context.PROVIDER_URL, host + ":" + port);
env.put(Context.URL_PKG_PREFIXES, urlPackage);
InitialContext initialContext = new InitialContext(env);
try
{
context = (Context)initialContext.lookup(DETECTION_SUBCONTEXT_NAME);
}
catch(NamingException e)
{
context = initialContext.createSubcontext(DETECTION_SUBCONTEXT_NAME);
}
}
public void stop() throws Exception
{
try
{
super.stop();
}
finally {
String sId = id.getInstanceId();
try
{
unregisterDetection(sId);
}
catch(NamingException e)
{
log.warn("Could not unregister " + sId + " before shutdown. " +
"Root cause is " + e.getMessage());
}
}
}
private void unregisterDetection(String sId) throws NamingException
{
if(log.isDebugEnabled())
{
log.debug("unregistering detector " + sId);
}
context.unbind(sId);
}
}