2013-03-30 3 views
0

У меня возникли странные проблемы при попытке выполнить блок кода (в частности, класс ProcessBuilder в Java)ProcessBuilder - потенциальная ошибка

код, который работает:

package modules.user.verify; 

import java.io.*; 
import java.util.*; 
import java.net.*; 

public class VerifyUser { 
public static void main(String[] args) { 
    boolean listening = true; 

    try { 
     ServerSocket server = new ServerSocket(20002); 

     while(listening) { 
      Socket client = server.accept(); 

      PrintWriter out = new PrintWriter(client.getOutputStream(), true); 
      BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); 

      String input, store = "", request = ""; 

      // For all input received, write it to the request buffer. 
      while((input = in.readLine()) != null) { 
       request += input; 
      } // end while loop 

      BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml")); 

      while((input = reader.readLine()) != null) { 
       store += input; 
      } // end while loop 

      String acl2 = "(include-book \"modules/user/verify/verify-user\")" + 
           "(in-package \"ACL2\")" + 
         "(set-state-ok t)" + 
           "(set-guard-checking :none)" + 
          "(testUser \"" + request + "\" \"" + store + "\" state)"; 

      System.out.println("Executing ACL2 runtime..."); 
      ProcessBuilder processBuilder = new ProcessBuilder("acl2"); 
      File log = new File("logs/user/verify/acl2_log.txt"); 
      processBuilder.redirectErrorStream(true); 
      processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log)); 
      Process process = processBuilder.start(); 
      PrintWriter procIn = new PrintWriter(process.getOutputStream()); 

      // Write the ACL2 to the process, exit ACL2 and close the socket 
      procIn.println(acl2); 
      procIn.println("(good-bye)"); 
      procIn.flush(); 
      procIn.close(); 
      out.close(); 
      in.close(); 
      client.close(); 
     } // end while loop 

     server.close(); 
     System.exit(0); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } // end try/catch 
} // end function main 
} // end class VerifyUser 

Код, который Безразлично» т:

package modules.user.register; 

import java.io.*; 
import java.util.*; 
import java.net.*; 

public class RegisterUser { 
public static void main(String[] args) { 
    boolean listening = true; 

    try { 
     // Acquire the listening port for connection to client. 
     ServerSocket server = new ServerSocket(20001); 

     while(listening) { 
      // Wait until the client connects 
      Socket client = server.accept(); 

      // Handles for input and output streams relating to the socket connection 
      PrintWriter out = new PrintWriter(client.getOutputStream(), true); 
      BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); 

      // Buffers 
      String input, store="", request=""; 

      // Read the input from the connection 
      while((input = in.readLine()) != null) { 
       request += input; 
      } // end while 

      // Read the contents of the address-book currently stored 
      BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml")); 
      while((input = reader.readLine()) != null) { 
       store += input; 
      } // end while 

      // The ACL2 code to execute. 
      String acl2 = "(include-book \"register-user\")" + 
          "(in-package \"ACL2\")"   + 
          "(registerUser \"" + request + "\" \"" + store + "\" state)"; 

      // Initialize ACL2 and dump its output to the log 
      System.out.println("Executing ACL2 runtime for RegisterUser..."); 
      ProcessBuilder processBuilder = new ProcessBuilder("acl2"); 
      File log = new File("logs/user/register/acl2_log.txt"); 
      processBuilder.redirectErrorStream(true); 
      processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log)); 

      Process process = processBuilder.start(); 
      PrintWriter procIn = new PrintWriter(process.getOutputStream()); 

      // Write the ACL2 to the process, close ACL2 
      //procIn.println(acl2); 
      //procIn.println("(good-bye)"); 
      //procIn.flush(); 
      //procIn.close(); 

      // Old store is old address-book file and new store is newly generated 
      File oldStore = new File("store/address-book/address-book.xml"); 
      File newStore = new File("store/address-book/temp_address-book.xml"); 

      // Response header information 
      String response = "<?xml version='1.0'?>"      + 
           "<!DOCTYPE response SYSTEM 'dtd/reponse.dtd'>" + 
           "<response>"; 

      // Determine if there was a change. 
      // If entry was added, the length > that old length. 
      if(oldStore.length() < newStore.length()) { 
       // Replace old file with new file 
       oldStore.delete(); 
       newStore.renameTo(oldStore); 

       // Extract data from request XML 
       String name = request.substring(request.indexOf("<name>")+6, request.indexOf("</name>")-7); 
       String domain = request.substring(request.indexOf("<domain>")+8, request.indexOf("</domain>")-9); 

       // Create the store directory for the user's emails 
       File storeDirectory = new File("store/email/" + domain + "/" + name + "/"); 
       storeDirectory.mkdirs(); 

       response += "<message>ACCEPT</message>"; 
      } else { 
       // Remove new file as it is pointless 
       newStore.delete(); 
       response += "<message>REJECT</message>"; 
      } // end if-else 

      response += "</response>"; 

      // Writeback the response to the client 
      out.print(response); 
      out.flush(); 

      // Close all streams 
      out.close(); 
      in.close(); 
      client.close(); 
     } // end while 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } // end try/catch 
} // end function main 
} // end class RegisterUser 

Как вы можете видеть, я не передаю никаких аргументов программе. когда я повторяю% PATH% на моей Windows DOS-оболочке, он показывает, что C: \ ACL2 находится в моих ENV-vars (это папка acl2.exe). Я попытался изменить acl2 на C: \ ACL2 \ acl2.exe только для получения тех же результатов.

Что меня поразило, так это то, почему первый работает отлично, а второй (с почти таким же точным кодом - точный точный код ProcessBuilder) не работает.

Оказывается, этот блок кода, где моя проблема:

 System.out.println("Executing ACL2 runtime..."); 
     ProcessBuilder processBuilder = new ProcessBuilder("acl2"); 
     File log = new File("logs/user/register/acl2_log.txt"); 
     processBuilder.redirectErrorStream(true); 
     processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log)); 
     Process process = processBuilder.start(); 
     PrintWriter procIn = new PrintWriter(process.getOutputStream()); 

Ошибка:

Executing ACL2 runtime for RegisterUser... 
java.io.IOException: Cannot run program "acl2": The system cannot find the path specified 
     at java.lang.ProcessBuilder.start(Unknown Source) 
    at modules.user.register.RegisterUser.main(RegisterUser.java:74) 
Caused by: java.io.IOException: The system cannot find the path specified 
    at java.lang.ProcessImpl.openForAtomicAppend(Native Method) 
    at java.lang.ProcessImpl.newFileOutputStream(Unknown Source) 
    at java.lang.ProcessImpl.start(Unknown Source) 
    ... 2 more 

Что должно произойти, является то, что процесс, который запускается это среда ACL2 , код отправляется на него, который выполняется, а затем процесс убивается (через команду прощания в ACL2). После этого код должен выйти после небольшого количества Java, который не связан с процессом ACL2, где возникает ошибка.

Программа VerifyUser вызывает ACL2, пишет ответ на файл «server-response.xml» и изящно выходит без инцидентов.

Программа RegisterUser должна вызывать ACL2, написать ответ и выйти изящно, а небольшой код java создает каталог для пользователя и удаляет файл хранилища и переименовывает вновь созданный для регистрации пользователя.

+1

Трудно легко увидеть различия между двумя длинными примерами кода. Не могли бы вы упростить, чтобы сделать простейший возможный код, который показывает вашу проблему? Или, если вы не знаете, как это сделать, возможно, вы можете описать словами разницу в ожидаемой функциональности двух модулей кода и определить, какие части имеют отношение к проблеме? –

+0

System.out.println («Выполнение ACL2 runtime ...»); ProcessBuilder processBuilder = новый ProcessBuilder ("acl2"); Файл log = новый файл («logs/user/verify/acl2_log.txt»); processBuilder.redirectErrorStream (true); processBuilder.redirectOutput (ProcessBuilder.Redirect.appendTo (log)); Процесс process = processBuilder.start(); PrintWriter procIn = новый PrintWriter (process.getOutputStream()); – Treston

+1

@Treston: Нет, не публикуйте код в комментарии.Измените свой вопрос, так что это действительно ясно. –

ответ

2

Поскольку исключение в

at java.lang.ProcessImpl.openForAtomicAppend(Native Method) 

И используются два различных пути:

File log = new File("logs/user/verify/acl2_log.txt"); 
File log = new File("logs/user/register/acl2_log.txt"); 

можно было бы, что команда acl найдена, но что перенаправление не может быть выполнено. В этом случае сообщение об ошибке не очень полезно, но - если вы читаете между строками - также не ошибаетесь.

+0

Я прокомментировал это и, похоже, не решил проблему. Эти две программы не запускаются одновременно, поэтому я предположил, что между ними не будет проблем. – Treston

+0

@ Treston Huh? Я не думаю, что комментирование решает проблему. Просто убедитесь, что оба каталога существуют. –

+0

@Treston: И просто для тестирования: убедитесь, что оба файла существуют заранее (конечно, конечно). –