1 37 38 package net.sourceforge.cruisecontrol.distributed.util; 39 40 import java.io.IOException ; 41 import java.rmi.RemoteException ; 42 import java.util.Arrays ; 43 44 import net.jini.core.lookup.ServiceTemplate; 45 import net.jini.core.lookup.ServiceItem; 46 import net.jini.core.lookup.ServiceRegistrar; 47 import net.jini.core.discovery.LookupLocator; 48 import net.jini.core.entry.Entry; 49 import net.jini.lease.LeaseRenewalManager; 50 import net.jini.discovery.LookupDiscovery; 51 import net.jini.discovery.LookupDiscoveryManager; 52 import net.jini.lookup.ServiceDiscoveryManager; 53 import net.jini.lookup.LookupCache; 54 import net.jini.lookup.ServiceDiscoveryEvent; 55 import net.jini.lookup.ServiceDiscoveryListener; 56 import net.jini.lookup.ServiceItemFilter; 57 import net.sourceforge.cruisecontrol.distributed.BuildAgentService; 58 import net.sourceforge.cruisecontrol.distributed.PropertyEntry; 59 60 import org.apache.log4j.Logger; 61 62 public class MulticastDiscovery { 63 64 private static final Logger LOG = Logger.getLogger(MulticastDiscovery.class); 65 66 private final ServiceTemplate serviceTemplate; 67 private final ServiceDiscoveryManager clientMgr; 68 private final LookupCache lookupCache; 69 70 public MulticastDiscovery(final Entry[] entries) { 71 this(LookupDiscovery.ALL_GROUPS, null, BuildAgentService.class, entries); 72 } 73 74 public MulticastDiscovery(final String [] lookupGroups, final LookupLocator[] unicastLocaters, 75 final Class klass, final Entry[] entries) { 76 LOG.debug("Starting multicast discovery for groups: " + lookupGroups); 77 ReggieUtil.setupRMISecurityManager(); 78 79 try { 80 81 final LookupDiscoveryManager discoverMgr = new LookupDiscoveryManager( 82 lookupGroups, unicastLocaters, null); 83 84 clientMgr = new ServiceDiscoveryManager(discoverMgr, new LeaseRenewalManager()); 85 } catch (IOException e) { 86 final String message = "Error starting discovery"; 87 LOG.debug(message, e); 88 throw new RuntimeException (message, e); 89 } 90 91 final Class [] classes = new Class [] {klass}; 93 serviceTemplate = new ServiceTemplate(null, classes, entries); 94 try { 95 lookupCache = getClientManager().createLookupCache( 96 getServiceTemplate(), null, new ServiceDiscListener(this)); 97 } catch (RemoteException e) { 98 final String message = "Error creating _service cache"; 99 LOG.debug(message, e); 100 throw new RuntimeException (message, e); 101 } 102 103 111 } 112 113 114 public ServiceRegistrar[] getRegistrars() { 115 return getClientManager().getDiscoveryManager().getRegistrars(); 117 } 118 119 120 private ServiceTemplate getServiceTemplate() { 121 return serviceTemplate; 122 } 123 124 private ServiceDiscoveryManager getClientManager() { 125 return clientMgr; 126 } 127 128 129 LookupCache getLookupCache() { 130 return lookupCache; 131 } 132 133 public ServiceItem findMatchingService() throws RemoteException { 134 return findMatchingService(true); 135 } 136 public ServiceItem findMatchingService(final boolean doClaim) throws RemoteException { 137 final ServiceItem result = getLookupCache().lookup(FLTR_AVAILABLE); 138 if (doClaim && result != null) { 139 ((BuildAgentService) result.service).claim(); 140 } 141 return result; 142 } 143 144 static final BuildAgentFilter FLTR_AVAILABLE = new BuildAgentFilter(true); 145 static final BuildAgentFilter FLTR_ANY = new BuildAgentFilter(false); 146 147 static final class BuildAgentFilter implements ServiceItemFilter { 148 private final boolean findOnlyNonBusy; 149 150 private BuildAgentFilter(final boolean onlyNonBusy) { 151 findOnlyNonBusy = onlyNonBusy; 152 } 153 154 public boolean check(final ServiceItem item) { 155 156 LOG.debug("Service Filter: item.service: " + item.service); 157 if (!(item.service instanceof BuildAgentService)) { 158 return false; 159 } 160 161 final BuildAgentService agent = (BuildAgentService) item.service; 162 final String agentMachine; 164 try { 165 agentMachine = agent.getMachineName(); 166 } catch (RemoteException e) { 167 final String msg = "Error reading agent machine name. Filtering out agent."; 168 LOG.debug(msg, e); 169 return false; } 171 172 if (!findOnlyNonBusy) { 173 return true; } 175 176 try { 177 return !agent.isBusy(); 178 } catch (RemoteException e) { 179 final String msg = "Error checking agent busy status. Filtering out agent on machine: " 180 + agentMachine; 181 LOG.debug(msg, e); 182 return false; } 184 } 185 } 186 187 public void terminate() { 188 if (getClientManager() != null) { 189 getClientManager().terminate(); 190 } 191 } 192 193 194 195 private boolean isDiscovered; 196 private synchronized void setDiscovered(final boolean discovered) { 197 isDiscovered = discovered; 198 } 199 public synchronized boolean isDiscovered() { 200 return isDiscovered; 201 } 202 203 public final class ServiceDiscListener implements ServiceDiscoveryListener { 204 private final MulticastDiscovery discovery; 205 206 private ServiceDiscListener(final MulticastDiscovery discovery) { 207 this.discovery = discovery; 208 } 209 210 private String buildDiscoveryMsg(final ServiceDiscoveryEvent event, final String actionName) { 211 String msg = "\nService " + actionName + ": "; 212 213 final ServiceItem postItem = event.getPostEventServiceItem(); 214 if (postItem != null) { 215 msg = toStringServiceItem(postItem, msg + "PostEvent: "); 216 } else { 217 final ServiceItem preItem = event.getPreEventServiceItem(); 218 if (preItem != null) { 219 msg = toStringServiceItem(preItem, msg + "PreEvent: "); 220 } else { 221 msg += "NOT SURE WHAT THIS EVENT IS!!!"; 222 } 223 } 224 return msg; 225 } 226 227 public void serviceAdded(final ServiceDiscoveryEvent event) { 228 discovery.setDiscovered(true); 229 LOG.info(buildDiscoveryMsg(event, "Added")); 230 } 231 232 public void serviceRemoved(final ServiceDiscoveryEvent event) { 233 discovery.setDiscovered(false); 234 LOG.info(buildDiscoveryMsg(event, "Removed")); 235 } 236 237 public void serviceChanged(final ServiceDiscoveryEvent event) { 238 LOG.info(buildDiscoveryMsg(event, "Changed")); 239 } 240 } 241 242 243 public static String toStringServiceItem(final ServiceItem serviceItem, String msgPrefix) { 244 msgPrefix += serviceItem.service.getClass().toString() + "; ID:" + serviceItem.serviceID 245 + toStringEntries(serviceItem.attributeSets); 246 return msgPrefix; 247 } 248 249 public static String toStringEntries(final Entry[] entries) { 250 return "\n\tEntries:\n\t" 251 + Arrays.asList(entries).toString().replaceAll("\\), ", "\\), \n\t") 252 .replaceAll(PropertyEntry.class.getName(), "") 253 + "\n"; 254 } 255 } 256 | Popular Tags |