package com.jotuntech.sketcher.server; import java.awt.AlphaComposite; import java.awt.Image; import java.awt.image.ImageObserver; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.util.Properties; import java.util.Map.Entry; import javax.imageio.ImageIO; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.jotuntech.sketcher.common.Canvas; import com.jotuntech.sketcher.common.Layer; import com.jotuntech.sketcher.common.TwoWayHashMap; import com.jotuntech.sketcher.common.User; public class Service { boolean canvasModified = false; long motdLastModified = 0; public static void main(String[] args) throws Throwable { new Service().run(args); } private void run(String[] args) throws Throwable { System.setProperty("java.net.preferIPv4Stack", "true"); BufferedReader pbr = new BufferedReader(new FileReader(args[0])); String propertiesPath = pbr.readLine(); pbr.close(); Properties properties = new Properties(); properties.load(new FileInputStream(new File(propertiesPath))); String serverName = properties.getProperty("server.name", "Rental"); int port = Integer.valueOf(properties.getProperty("server.port", "10000")); final File talkFile = new File(properties.getProperty("server.talk", "talk.txt")); final File userFile = new File(properties.getProperty("server.user", "user.txt")); String motdFilename = properties.getProperty("server.motd", null); final File motdFile = motdFilename == null ? null : new File(motdFilename); String captureFilename = properties.getProperty("server.capture", "capture.jpg"); final File captureFile = new File(captureFilename); final File captureTempFile = new File(captureFilename + ".tmp"); final File saveFile = new File(properties.getProperty("server.save", "save.canvas")); final File secretFolder = new File(properties.getProperty("server.secret", "secret/")); final File flagsFile = new File(properties.getProperty("server.flags", "server.flags")); AccessController ac = new AccessController() { public boolean isKickAllowed(Server server, User source, User target) { try { BufferedReader br = new BufferedReader(new FileReader(flagsFile)); String flags = br.readLine(); br.close(); if(flags.indexOf('k') >= 0) { return true; } } catch (IOException e) { } return false; } public boolean isLayerActionAllowed(Server server, User source) { try { BufferedReader br = new BufferedReader(new FileReader(flagsFile)); String flags = br.readLine(); br.close(); if(flags.indexOf('l') >= 0) { return true; } } catch (IOException e) { } return false; } public boolean isLoginAllowed(Server server, String login, String password) { try { File secretFile = new File(secretFolder, login); BufferedReader br = new BufferedReader(new FileReader(secretFile)); String hash = br.readLine(); br.close(); secretFile.delete(); secretFile.createNewFile(); if(password.equals(hash)) { return true; } } catch (IOException e) { } return false; } public boolean isMessageAllowed(Server server, User source, String message) { return true; } public boolean isViewer(Server server, User source) { return false; } }; ImageObserver io = new ImageObserver() { public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { canvasModified = true; return true; } }; final Server server = new Server(serverName, port, 2048, 1536); server.setAccessController(ac); server.getCanvas().addImageObserver(io); if(saveFile.exists()) { FileInputStream fis = new FileInputStream(saveFile); ObjectInputStream ois = new ObjectInputStream(fis); Canvas c = server.getCanvas(); TwoWayHashMap layerMap = c.getLayerMap(); synchronized(layerMap) { layerMap.clear(); layerMap.setNextKey(ois.readInt()); while(ois.available() > 0) { int k = ois.readInt(); Layer l = (Layer) ois.readObject(); if(l.getAlphaRule() == 0) { l.setAlphaRule(AlphaComposite.SRC_OVER); } layerMap.put(k, l); } } c.imageUpdate(null, ImageObserver.ALLBITS, 0, 0, c.getWidth(), c.getHeight()); ois.close(); } server.getConnectionMap().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { try { PrintWriter pw = new PrintWriter(new FileWriter(userFile)); for(User u : server.getUsers()) { pw.println(u.getName()); } pw.close(); } catch(Throwable e2) { e2.printStackTrace(); } } }); server.start(); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { FileOutputStream fos = new FileOutputStream(saveFile); ObjectOutputStream oos = new ObjectOutputStream(fos); TwoWayHashMap layerMap = server.getCanvas().getLayerMap(); oos.writeInt(layerMap.getNextKey()); for(Entry e : layerMap.entrySet()) { int k = e.getKey(); Layer l = e.getValue(); oos.writeInt(k); oos.writeObject(l); } oos.close(); } catch(Throwable e) { e.printStackTrace(); } } }); if(!talkFile.exists()) { talkFile.createNewFile(); } int captureCounter = 0; for(;;) { if(canvasModified && captureCounter % 60 == 0) { ImageIO.write(server.getImage(), "PNG", captureTempFile); captureFile.delete(); captureTempFile.renameTo(captureFile); canvasModified = false; } if(talkFile.length() > 0) { BufferedReader br = new BufferedReader(new FileReader(talkFile)); String line = br.readLine(); if(line != null) { if(line.startsWith("kick ")) { server.kick(line.substring(5), "by room owner"); } else { server.announce(line); } } br.close(); talkFile.delete(); talkFile.createNewFile(); } if(motdFile != null && motdFile.lastModified() > motdLastModified) { motdLastModified = motdFile.lastModified(); StringBuffer buffer = new StringBuffer(1024); char[] charBuffer = new char[1024]; FileReader fr = new FileReader(motdFile); int charsRead = fr.read(charBuffer); if(charsRead > 0) { do { buffer.append(charBuffer, 0, charsRead); charsRead = fr.read(charBuffer); } while(charsRead > 0); server.setMOTD(buffer.toString()); } fr.close(); } Thread.sleep(5000); ++captureCounter; } } }