📄 clientdaemon.java
字号:
package net.sf.dz.view.tcp.client;import java.awt.Container;import java.awt.GridLayout;import java.awt.Window;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.io.StringReader;import java.net.Socket;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.StringTokenizer;import java.util.TreeMap;import javax.net.ssl.SSLException;import javax.swing.JScrollPane;import javax.swing.JTabbedPane;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.conf.ConfigurationFactory;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.logger.Logger;import org.freehold.jukebox.service.ActiveService;import net.sf.dz.util.SSLContextFactory;public class ClientDaemon extends ActiveService { public static final LogChannel CH_CD = new LogChannel("Daemon"); /** * Panel to use. */ private ClientPanel display; /** * Remote host to connect to. */ private String remoteHost; /** * Port on the remote host to connect to. */ private int remotePort; /** * Is connection requested to be secure. */ private boolean secure; /** * Password for the key store. * * VT: Don't tell me it's insecure, just fix the implementation to be * more secure, all right? */ private String password; private Socket socket; private BufferedReader br; private PrintWriter pw; private Configuration cf; private JTabbedPane view; private PreferencesPanel preferencesPanel; private Map unit2panel = new TreeMap(); public ClientDaemon(Logger logger, ClientPanel display, String remoteHost, int remotePort, boolean secure, String password) { super(logger, null); this.display = display; this.remoteHost = remoteHost; this.remotePort = remotePort; this.secure = secure; this.password = password; } protected void startup() throws Throwable { // Connect to the remote complain(LOG_INFO, CH_CD, "Connecting to " + remoteHost + ":" + remotePort + "..."); if ( secure ) { complain(LOG_NOTICE, CH_CD, "Secure connection requested"); try { socket = SSLContextFactory.createContext(password).getSocketFactory().createSocket(remoteHost, remotePort); } catch ( SSLException sslex ) { complain(LOG_WARNING, CH_CD, "Can't establish a secure connection to " + remoteHost + ":" + remotePort, sslex); complain(LOG_WARNING, CH_CD, "Reverting to insecure connection"); } } if ( socket == null ) { socket = new Socket(remoteHost, remotePort); } br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw = new PrintWriter(socket.getOutputStream()); if ( !secure ) { // In case we're talking to a secure socket implementation, // we'll get stuck reading the input stream - they won't // tell us anything, nor would they break away (well, maybe // after a really long timeout). Therefore, we'll have to // give them a kick so they kick us out and we'll get a // visible indication of a failure. pw.println(""); pw.println(""); pw.println(""); pw.println(""); pw.println(""); pw.println(""); pw.flush(); // If they're secure, and we're not, we'll get kicked out // right here... } // Read the XML reflection readReflection(); // Instantiate the local view createView(); // At this point we can be reasonably sure that the remote gave us // the information we can use. complain(LOG_INFO, CH_CD, "Connected"); // Replace the display content with the local view JScrollPane scroller = new JScrollPane(view); display.setLayout(new GridLayout(1, 1)); display.add(scroller); Container parent = display; while ( !(parent instanceof Window) && parent != null) { parent.invalidate(); parent = parent.getParent(); } if ( parent != null ) { ((Window)parent).pack(); } } private void readReflection() throws IOException { StringBuffer sb = new StringBuffer(); while ( true ) { String line = br.readLine(); if ( line == null ) { throw new IOException("EOF before end of header"); } if ( "".equals(line) ) { // We're done break; } sb.append(line).append("\n"); } String reflection = sb.toString(); complain(LOG_DEBUG, CH_CD, "Reflection:\n" + reflection); StringReader sr = new StringReader(reflection); cf = (new ConfigurationFactory()).getConfiguration(sr); complain(LOG_DEBUG, CH_CD, "got reflection"); } private void createView() throws Throwable { // This view will contain the unit containers. Since they are quite // few, usually 1, rarely 2, VERY rarely more, we can just leave the // layout manager as is - FlowLayout. It is also possible to just // add the tabs for unit other than first to the same tabbed pane - // there'll be two tabs, one for the status display and the other // for the schedule. view = new JTabbedPane(); List unitNames = cf.getList("model.unit"); if ( unitNames.isEmpty() ) { throw new IllegalStateException("Server reported no units - huh?"); } complain(LOG_INFO, CH_CD, "Units: " + unitNames); for ( Iterator i = unitNames.iterator(); i.hasNext(); ) { String unitName = i.next().toString(); UnitPanel unitPanel = new UnitPanel(this, unitName); unit2panel.put(unitName, unitPanel); unitPanel.setLogger(getLogger()); unitPanel.configure("model.unit." + unitName, cf); view.addTab("Unit: " + unitName, unitPanel.getPanel()); } // VT: FIXME: This is not yet implemented. The schedule will reside // on the main tab. if ( false ) for ( Iterator i = unitNames.iterator(); i.hasNext(); ) { String unitName = i.next().toString(); // VT: FIXME view.addTab("Schedule: " + unitName , new javax.swing.JPanel()); } preferencesPanel = new PreferencesPanel(this); view.addTab("Preferences", preferencesPanel.getPanel()); // VT: FIXME: This is not yet implemented //view.addTab("Status", new javax.swing.JPanel()); //view.addTab("Log", new javax.swing.JPanel()); } protected void execute() throws Throwable { // Read the data and pass it to the model proxy while ( isEnabled() ) { String line = br.readLine(); if ( line == null ) { complain(LOG_NOTICE, CH_CD, "Control connection closed, shutting down"); break; } complain(LOG_DEBUG, CH_CD, "Command received: '" + line + "'"); try { parse(line); } catch ( Throwable t ) { // We applied our best efforts to handle the input, so // there's a problem with the line being parsed, or the // implementation. Let's see what caused it: complain(LOG_WARNING, CH_CD, "Parse failure, command '" + line + "', cause:", t); } } } public void parse(String command) throws Throwable { // VT: FIXME: public access required because of an initial oversight // with the HVAC mode StringTokenizer st = new StringTokenizer(command, ":"); String commandType = st.nextToken(); if ( "status".equals(commandType) ) { String target = st.nextToken(); if ( "unit".equals(target) ) { String unitName = st.nextToken(); UnitPanel unitPanel = (UnitPanel)unit2panel.get(unitName); if ( unitPanel == null ) { complain(LOG_WARNING, CH_CD, "Non-existent unit: '" + unitName + "': " + command); return; } unitPanel.parse(st); } else if ( "preferences".equals(target) ) { preferencesPanel.parse(st); } else { complain(LOG_WARNING, CH_CD, "Unknown target: '" + target + "': " + command); return; } } else { complain(LOG_WARNING, CH_CD, "Unsupported command type '" + commandType + "': " + command); return; } } protected void shutdown(Throwable cause) throws Throwable { } public synchronized void send(String command) { pw.println(command); pw.flush(); } public Set getUnitNames() { return unit2panel.keySet(); } public void setHvacGraph(boolean enabled) { for ( Iterator i = getUnitNames().iterator(); i.hasNext(); ) { Object name = i.next(); UnitPanel up = (UnitPanel)unit2panel.get(name); up.setHvacGraph(enabled); } } public void setZoneGraph(boolean enabled) { for ( Iterator i = getUnitNames().iterator(); i.hasNext(); ) { Object name = i.next(); UnitPanel up = (UnitPanel)unit2panel.get(name); up.setZoneGraph(enabled); } } public void setPConGraph(boolean enabled) { for ( Iterator i = getUnitNames().iterator(); i.hasNext(); ) { Object name = i.next(); UnitPanel up = (UnitPanel)unit2panel.get(name); up.setPConGraph(enabled); } } public void setDamperGraph(boolean enabled) { for ( Iterator i = getUnitNames().iterator(); i.hasNext(); ) { Object name = i.next(); UnitPanel up = (UnitPanel)unit2panel.get(name); up.setDamperGraph(enabled); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -