package com.intellij.flex.compiler; import com.intellij.CommonBundle; import com.intellij.flex.compiler.flex3.Flex3Handler; import com.intellij.flex.compiler.flex4.Flex4Handler; import flex2.tools.VersionInfo; import java.io.*; import java.net.InetAddress; import java.net.Socket; public class FlexCompiler implements MessageSender { private static final String CONNECTION_SUCCESSFUL = "Connection successful"; private static final String FINISH_COMMAND = "Finish"; public static final String CANCEL_COMMAND = "Cancel"; public static final String COMPILATION_FINISHED = "Compilation finished"; public static String SDK_MAJOR_VERSION = VersionInfo.FLEX_MAJOR_VERSION; public static String SDK_MINOR_VERSION = VersionInfo.FLEX_MINOR_VERSION; public static String SDK_REVISION_VERSION = VersionInfo.FLEX_NANO_VERSION; private DataInputStream myDataInputStream; private DataOutputStream myDataOutputStream; private void openSocket(int port) throws IOException { final int maxAttempts = 10; Socket socket; for (int i = 0; i < maxAttempts; i++) { try { socket = new Socket(InetAddress.getLocalHost(), port); myDataInputStream = new DataInputStream(socket.getInputStream()); myDataOutputStream = new DataOutputStream(socket.getOutputStream()); System.out.println(CONNECTION_SUCCESSFUL); break; } catch (IOException e) { if (i == maxAttempts - 1) { throw e; } else { try { Thread.sleep(100); } catch (InterruptedException ignore2) {/**/} } } } } public static void main(String[] args) { if (args.length != 1) { System.out.println("Missing port parameter"); } final int port; try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.out.println("Incorrect port parameter"); return; } try { final FlexCompiler flexCompiler = new FlexCompiler(); flexCompiler.openSocket(port); flexCompiler.processInput(); } catch (IOException e) { e.printStackTrace(); } } public synchronized void sendMessage(final String message) { try { //System.out.println("OUT: [" + message + "]"); myDataOutputStream.writeUTF(message.replace('\n', ' ').replace('\r', ' ').trim() + "\n"); } catch (IOException e) { e.printStackTrace(); } } private void processInput() throws IOException { final StringBuilder buffer = new StringBuilder(); while (true) { final String line = myDataInputStream.readUTF(); //System.out.println("IN: [" + line + "]"); buffer.append(line); final boolean finish = processCommands(buffer); if (finish) { return; } } } private boolean processCommands(final StringBuilder buffer) { int index; while ((index = buffer.indexOf("\n")) > -1) { final String command = buffer.substring(0, index); buffer.delete(0, index + 1); if (CANCEL_COMMAND.equals(command)) { cancelAllCompilations(); } else if (FINISH_COMMAND.equals(command)) { exit(); return true; } else { startCompilationThread(command); } } return false; } private void startCompilationThread(final String command) { final int colonPos = command.indexOf(":"); if (colonPos <= 0) { sendMessage("Error: Incorrect command: [" + command + "]"); sendMessage(COMPILATION_FINISHED); return; } final String commandNumberStr = command.substring(0, colonPos); try { Integer.parseInt(commandNumberStr); } catch (NumberFormatException e) { sendMessage("Error: Incorrect command number: [" + commandNumberStr + "]"); sendMessage(COMPILATION_FINISHED); return; } final String compilationCommand = command.substring(colonPos + 1); final boolean isSwf = compilationCommand.startsWith("mxmlc "); if (!isSwf && !compilationCommand.startsWith("compc")) { sendMessage("Error: Incorrect compilation command: [" + compilationCommand + "]"); sendMessage(COMPILATION_FINISHED); return; } final String logMessagePrefix = commandNumberStr + ":"; final OutputLogger logger = new OutputLogger(this, logMessagePrefix); final SdkSpecificHandler sdkSpecificHandler = getSdkSpecificHandler(); if (sdkSpecificHandler == null) { logger.log( "Error: Flex SDK " + SDK_MAJOR_VERSION + '.' + SDK_MINOR_VERSION + '.' + SDK_REVISION_VERSION + " is not supported by built-in compiler shell. Please change compiler at " + CommonBundle.settingsActionPath() + " | Compiler | Flex Compiler."); logger.log(COMPILATION_FINISHED); return; } final CompilationThread compilationThread = new CompilationThread(isSwf, sdkSpecificHandler, getParams(compilationCommand), logger); compilationThread.setPriority(Thread.MAX_PRIORITY); compilationThread.setDaemon(true); compilationThread.start(); } private SdkSpecificHandler getSdkSpecificHandler() { if ("3".equals(SDK_MAJOR_VERSION)) { return new Flex3Handler(); } else if ("4".equals(SDK_MAJOR_VERSION)) { return new Flex4Handler(); } return null; } private static String[] getParams(final String command) { final CommandLineArgumentsTokenizer tokenizer = new CommandLineArgumentsTokenizer(command); tokenizer.nextToken(); // mxmlc or compc final String[] params = new String[tokenizer.countTokens()]; int i = 0; while (tokenizer.hasMoreTokens()) { params[i++] = tokenizer.nextToken(); } return params; } private void exit() { cancelAllCompilations(); try { myDataInputStream.close(); } catch (IOException ignored) { } } private void cancelAllCompilations() { // todo implement } }