网络会议openmeetings下的openmeetings-util文件分析4

2021SC@SDUSC

上篇文章主要对模块openmeetins-util下src/main/mail文件下的三个类进行了分析,分别是ByteArrayDataSourse、IcalHandler、MailUtil类来实现创建数据源、对会议日历的处理、以及判断地址是否有效。接下来将继续分析util文件下的其他类。该篇文章将分析src/main下的process文件夹下的类。

目录

process

ProcessHelper类

ProcessResultList类

ProcessHelper类

总结


process

首先看process文件下有哪些类:

总共有三个类:分别是ProcessHelper、ProcessResult、ProcessResultList类,ProcessResult定义了一个实体类,ProcessHelper类获取并执行进程返回结果res,ProcessResultList类收集所有转换job的结果。

ProcessHelper类

//每个转换步骤创建的对象,每个调用的转换步骤和外部工具(如ImageMagick)都是一个//ConverterProcessMessage

public class ProcessResult {
   public static final Integer ZERO = new Integer(0);

   private String process;
   private String command;
   private String exception;
   private String error;
   private Integer exitCode;
   private String out;
   private boolean optional = false;

   public ProcessResult() {
      this(null, null, null);
   }

   public ProcessResult(String error) {
      this(null, error, null);
   }

   public ProcessResult(String process, String error, Exception ex) {
      setProcess(process);
      setException(ex == null ? null : ex.toString());
      setError(error);
      setExitCode(-1);
   }
   public boolean isOk() {
      return optional || !isWarn();
   }
   public boolean isWarn() {
      return !ZERO.equals(exitCode);
   }
   public String buildLogMessage() {
      return new StringBuilder()
         .append("process: ").append(process).append("\r\n")
         .append("command: ").append(command).append("\r\n")
         .append("exception: ").append(exception).append("\r\n")
         .append("error: ").append(error).append("\r\n")
         .append("exitValue: ").append(exitCode).append("\r\n")
         .append("optional: ").append(optional).append("\r\n")
         .append("out: ").append(out).append("\r\n").toString();
   }
}
(后面的方法为属性的get和set方法,就没有粘贴了)

定义了一个进程结果类,其中包括属性process(字符串类型)进程名,command(字符串类型)进程命令,exception(字符串类型)异常,error(字符串类型)错误,Integer类型变量exitCode(退出的时候会返回一个数字,一般是-1即表示退出异常,0表示退出正常),字符串类型变量out,以及布尔型变量optional。然后定义了几个构造方法来分别构造ProcessResult对象。

之后的方法为属性的get和set方法便没有粘贴了,isWarn()方法用来判断exitCode是否为0,如果不为0则退出异常发生了错误,返回布尔变量值true。然后isOk()方法通过判断optional或者调用isWarn()取非,来判断是否执行成功,成功返回true。最后的buildLogMessage()返回字符串将该类的属性打印出来供使用者方便读取。

ProcessResultList类

//Collects all results of conversion jobs

public class ProcessResultList {
   private List<ProcessResult> jobs = new ArrayList<>();

   public void add(ProcessResult res) {
      jobs.add(res);
   }
   public boolean hasError() {
      for (ProcessResult res : jobs) {
         if (!res.isOk()) {
            return true;
         }
      }
      return false;
   }
   public String getLogMessage() {
      StringBuilder logMessage = new StringBuilder();
      for (ProcessResult res : jobs) {
         logMessage.append("key: ");
         logMessage.append(res.getProcess());
         logMessage.append("\r\n");
         logMessage.append(res.buildLogMessage());
      }
      return logMessage.toString();
   }
   public int size() {
      return jobs.size();
   }
   public List<ProcessResult> getJobs() {
      return jobs;
   }
}

定义了一个List类变量jobs,里面存放的节点是ProcessResult类对象。

add(ProcessResult res)方法即在jobs对象里添加一个节点为参数res。

hasError()方法,调用每个job的isOk()方法,如果有一个exitValue为“-1”的job,返回true。

getLogMessage()方法,通过调用每个job的buildLogMessage()方法,将所有job结果转换为人类可读的格式。

size()方法返回jobs的数量大小。

getJobs()方法即返回jobs这个List。

ProcessHelper类

public class ProcessHelper {
   public static final Logger log = Red5LoggerFactory.getLogger(ProcessHelper.class, OpenmeetingsVariables.getWebAppRootKey());

   // This is necessary to prevent 'buffer overflow'
   // https://stackoverflow.com/questions/9885643/ffmpeg-executed-from-javas-processbuilder-does-not-return-under-windows-7
   private static class StreamWatcher extends Thread {
      public final StringBuilder output = new StringBuilder();
      private final InputStream is;
      private boolean run = true;

      private StreamWatcher(final InputStream is) {
         this.is = is;
      }

      @Override
      public void run() {
         try (BufferedReader br = new BufferedReader(new InputStreamReader(is, UTF_8));) {
            String line = br.readLine();
            while (run && line != null) {
               output.append(line).append('\n');
               line = br.readLine();
            }
         } catch (IOException ioexception) {
            return;
         }
      }

      public void finish() {
         run = false;
      }

      @Override
      public String toString() {
         return output.toString();
      }
   }

   private ProcessHelper() {}

   private static String getCommand(String[] argv) {
      StringBuilder tString = new StringBuilder();
      for (int i = 0; i < argv.length; i++) {
         tString.append(argv[i]).append(" ");
      }
      return tString.toString();
   }

   private static void debugCommandStart(String desc, String[] argv) {
      if (log.isDebugEnabled()) {
         log.debug("START {} ################# ", desc);
         log.debug(getCommand(argv));
      }
   }

   private static void debugCommandEnd(String desc) {
      if (log.isDebugEnabled()) {
         log.debug("END {} ################# ", desc);
      }
   }

   public static ProcessResult executeScript(String process, String[] argv) {
      return executeScript(process, argv, false);
   }

   public static ProcessResult executeScript(String process, String[] argv, boolean optional) {
      Map<String, String> env = new HashMap<>();
      return executeScript(process, argv, env, optional);
   }

   private static ProcessResult executeScript(String process, String[] argv, Map<? extends String, ? extends String> env, boolean optional) {
      ProcessResult res = new ProcessResult()
            .setProcess(process)
            .setOptional(optional);
      debugCommandStart(process, argv);

      Process proc = null;
      StreamWatcher errorWatcher = null;
      StreamWatcher inputWatcher = null;
      final long start = System.currentTimeMillis();
      try {
         res.setCommand(getCommand(argv)).setOut("");

         ProcessBuilder pb = new ProcessBuilder(argv);
         pb.environment().putAll(env);

         proc = pb.start();
         errorWatcher = new StreamWatcher(proc.getErrorStream());
         inputWatcher = new StreamWatcher(proc.getInputStream());
         errorWatcher.start();
         inputWatcher.start();

         proc.waitFor(getExtProcessTtl(), TimeUnit.MINUTES);

         res.setExitCode(proc.exitValue())
            .setOut(inputWatcher.toString())
            .setError(errorWatcher.toString());
      } catch (Throwable t) {
         log.error("executeScript", t);
         res.setExitCode(-1)
            .setError(String.format("Exception after %s of work; %s", formatMillis(System.currentTimeMillis() - start), t.getMessage()))
            .setException(t.toString());
      } finally {
         if (proc != null) {
            errorWatcher.finish();
            inputWatcher.finish();
            proc.destroy();
         }
      }

      debugCommandEnd(process);
      return res;
   }
}

ProcessHelper类首先定义一个Logger日志对象来记录打印,方便调试。

定义了一个内部静态类StreamWatch类继承了线程类Thread,这对于防止“缓冲区溢出”是必要的,内部类定义了StringBuilder类对象output,InputStream类对象is,继承并改写了run方法,利用while循环通过BufferReader类对象调用readLine()方法读取输入的内容,然后output调用append()方法添加到缓冲区中。

后面的getCommand(String[] argv)方法即获取所有的命令参数,返回字符串类型。

然后debugCommandStart()和debugCommandEnd()方法即打印在调试过程中打印开始,调用getCommand方法和打印结束。

之后executeScript(String process, String[] argv, Map<? extends String, ? extends String> env, boolean optional)方法,通过传进来的参数创建一个ProcessResult对象res,调用debugCommandStart()方法,然后通过使用流程Builder,我们可以修改环境变量,方便地设置变量以便在eclipse中运行它,命令执行超时20分钟录音的FFMPEG转换可能需要很长时间才能完成,如果发生了错误则将exitCode设为-1,并且设置错误信息和exception信息,最后调用finish()方法完成该进程。然后调用debugCommandEnd()方法打印该进程调试结束告诉使用者。返回ProcessResult类对象res。

总结

该篇文章将分析src/main下的process文件夹下的类。总共三个类,分别是ProcessResult类、ProcessHelper类和ProcessResultList类,均已分析完毕。后面的文章将继续对main文件下的类进行分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值