⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serviceprovider.java

📁 这是一个以JAVA编写的程序,本人还没有试过,是一个简单的温度控制系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package net.sf.dz.daemon.tcp.client;import java.io.IOException;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.StringTokenizer;import java.util.TreeMap;import java.util.TreeSet;import org.freehold.jukebox.logger.LogAware;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.service.RunnableService;import net.sf.dz.pnp.MulticastEvent;/** * Service provider. * * <p> * * Provides the {@link ConnectorFactory connector factory} with a way to get * a {@link DeviceConnector device connector} for a particular kind of * service. Knows how to locate multiple service provider instances and * create {@link ServiceConnector service connectors} for them. * * @author Copyright &copy; <a href="mailto:vt@freehold.crocodile.org">Vadim Tkachenko</a> 2001-2004 * @version $Id: ServiceProvider.java,v 1.3 2004/06/29 03:11:24 vtt Exp $ */public class ServiceProvider extends LogAware {    public static final LogChannel CH_SP = new LogChannel("ServiceProvider");    public static final LogChannel CH_DCP = new LogChannel("DeviceConnectorProxy");    /**     * Contains a map of known service connectors by source (to be exact,     * source address).     */    private Map serviceConnectorBySource = new HashMap();        /**     * Contains a device connector proxy map by address.     */    private Map deviceConnectorByAddress = new TreeMap();        /**     * Contains a map of known service connectors by device address.     */    private Map serviceConnectorByAddress = new TreeMap();    public synchronized DeviceConnector getConnector(String deviceAddress) {            // Do we have a connector already?                DeviceConnector dc = (DeviceConnector)deviceConnectorByAddress.get(deviceAddress);                if ( dc == null ) {                    // Create it, then                        dc = new DeviceConnectorProxy(deviceAddress);                        // And make sure everyone else knows about it                        deviceConnectorByAddress.put(deviceAddress, dc);        }                return dc;    }        /**     * Receive an endpoint advertisement.     */    public synchronized void multicastEventReceived(MulticastEvent e) {            // VT: NOTE: It is assumed that we will only get the notifications        // for the services we know how to handle            // Figure out the endpoint                Object source = e.getSource();                // If we don't have it, create it                if ( !knowAbout(source) ) {                    createServiceConnector(e);        } else {                    // If we have it, update the information about the devices that            // it provides                        update(e);        }    }        private boolean knowAbout(Object source) {            return serviceConnectorBySource.get(source) != null;    }        private synchronized void createServiceConnector(MulticastEvent e) {            complain(LOG_DEBUG, CH_SP, "Creating service connector for " + e.getSource());                // VT: FIXME: Currently, the only kind of connector we can handle is        // the TCP one. This sucks (think same-JVM endpoint, in particular,        // USB) and has to be fixed.                ServiceConnector sc = new TcpServiceConnector(this, e.getSourceAddress(), e.getPort(), e.isSecure(), "password");                if ( sc instanceof LogAware ) {                    ((LogAware)sc).setLogger(getLogger());        }                if ( sc instanceof RunnableService ) {                    // VT: FIXME: Make sure we know if startup fails                        ((RunnableService)sc).start();        }                // VT: FIXME: DOS attack and source flapping possible                // VT: NOTE: It is possible to at least partially prevent this from        // happening using PKI to sign the source advertisements and        // verifying the signatures on the receiving end.                serviceConnectorBySource.put(e.getSource(), sc);                update(e);    }        /**     * Analyze the event and figure out whether the service has changed and     * whether the devices that used to be provided by this service are     * still provided.     *     * @param e Event to analyze.     *     * @see #serviceConnectorByAddress     */    private synchronized void update(MulticastEvent e) {            ServiceConnector sc = (ServiceConnector)serviceConnectorBySource.get(e.getSource());                if ( sc == null ) {                    throw new IllegalStateException("Can't update - don't have a connector for " + e);        }                // VT: FIXME: This can be made more generic                Set newAddressSet = new TreeSet();                for ( StringTokenizer st = new StringTokenizer(e.getMessage(), " "); st.hasMoreTokens(); ) {                    newAddressSet.add(st.nextToken());        }                Set oldAddressSet = getAddressSetByServiceConnector(sc);                //complain(LOG_DEBUG, CH_SP, "Devices: " + newAddressSet);                for ( Iterator i = newAddressSet.iterator(); i.hasNext(); ) {                    String address = (String)i.next();            ServiceConnector sc2 = (ServiceConnector)serviceConnectorByAddress.get(address);                        if ( sc2 != null ) {                            if ( sc != sc2 ) {                                    // In this case, the consumer isn't even supposed to                    // notice anything                                    complain(LOG_INFO, CH_SP, address + " will be served by " + sc + " (used to be " + sc2 + ")");                    serviceConnectorByAddress.put(address, sc);                }            } else {                            // In this case, we don't send the arrival notification                // because it is assumed that the device will make itself                // known - and before that, it's as good as dead                                // VT: FIXME: Verify this assumption                             complain(LOG_INFO, CH_SP, address + " will be served by " + sc);                serviceConnectorByAddress.put(address, sc);            }        }                // Now let's figure whether the devices that used to be there are        // still there                for ( Iterator i = oldAddressSet.iterator(); i.hasNext(); ) {                    String address = i.next().toString();                        if ( !newAddressSet.contains(address) ) {                            // We may safely assume it's gone                                complain(LOG_NOTICE, CH_SP, "No more " + address);                                // VT: FIXME: This *may* cause hanging service                // connectors, but it may be a lesser evil. In any case,                // will have to check whether the service connector have                // any devices left at all and shut them down if                // necessary.                                serviceConnectorByAddress.remove(address);                DeviceConnectorProxy dcp = (DeviceConnectorProxy)deviceConnectorByAddress.get(address);                                if ( dcp != null ) {                                    // VT: NOTE: we do *not* remove the device connector                    // from the mappings. As a matter of fact, we never                    // destroy this mapping because the connector just                    // created once and then reused.                                    dcp.broadcast("Not Available");                }            }        }    }        private Set getAddressSetByServiceConnector(ServiceConnector sc) {            // VT: NOTE: This can be done just once and the mapping can be held        // permanently, but should we bother? The set we're about to produce        // is the opposite of serviceConnectorByAddress.            Set result = new TreeSet();                for ( Iterator i = serviceConnectorByAddress.keySet().iterator(); i.hasNext(); ) {                    String address = i.next().toString();                        if ( serviceConnectorByAddress.get(address).equals(sc) ) {                            result.add(address);            }        }                return result;    }    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -