private void initParams(JsonRecord rec) {
   for (Iterator iter = rec.iterator(); iter.hasNext(); ) {
     Entry tmp = (Entry) iter.next();
     if (tmp.getKey().equals(CMD)) {
       cmd = (JsonValue) tmp.getValue();
     } else if (tmp.getKey().equals(WRITEOPTS)) {
       writeOpts = (JsonValue) tmp.getValue();
     } else if (tmp.getKey().equals(READOPTS)) {
       readOpts = (JsonValue) tmp.getValue();
     }
   }
   if (cmd == null) throw new IllegalArgumentException("cmd cannot be null in externalfn()");
   try {
     if (writeOpts == null) {
       String in = "{outoptions: {adapter: 'com.ibm.jaql.io.stream.StreamOutputAdapter',";
       if (mode.equals(new JsonString("push")))
         in += "format: 'com.ibm.jaql.io.stream.converter.ArgumentsOutputStream'}}";
       else in += "format: 'com.ibm.jaql.io.stream.converter.LineTextOutputStream'}}";
       writeOpts = new JsonParser().parse(in);
     }
     if (readOpts == null) {
       String out =
           "{inoptions: {adapter: 'com.ibm.jaql.io.stream.StreamInputAdapter',"
               + "format: 'com.ibm.jaql.io.stream.converter.LineTextInputStream'}}";
       readOpts = new JsonParser().parse(out);
     }
   } catch (ParseException e) {
     e.printStackTrace();
   }
 }
  @Override
  public JsonIterator iter(Context context) throws Exception {
    try {
      initProcess(context);

      if (mode.equals(new JsonString("push"))) {
        args = exprs[0].eval(context);
        writer.write(args);
        writer.flush();
        return reader;
      } else if (mode.equals(new JsonString("streaming"))) {
        data = exprs[0].iter(context);

        return new ClosableJsonIterator() {
          boolean firsttime = true;
          InputHelper helper = new InputHelper();

          @Override
          public boolean moveNext() throws Exception {
            if (firsttime) {
              helper.start();
              firsttime = false;
            } else {
              helper.stop = false;
            }
            if (reader.moveNext()) {
              helper.stop = true;
              currentValue = reader.current();
              return true;
            }
            return false;
          }

          class InputHelper extends Thread {
            public boolean stop = false;

            public void run() {

              try {
                while (!stop) {
                  if (data.moveNext()) {
                    writer.write(data.current());
                  } else {
                    stop = true;
                    writer.close();
                    writer = null;
                  }
                }
              } catch (Throwable e) {
                e.printStackTrace(); // TODO: move to log
                if (error == null) {
                  error = e;
                }
              }
            }
          }
        };
      } else {
        throw new RuntimeException("unsupported mode: " + mode);
      }
    } catch (Throwable e) {
      if (error == null) {
        error = e;
      }
      if (stdin != null) {
        try {
          stdin.close();
        } catch (Throwable t) { // FIXME: More lost exceptions!
        }
        stdin = null;
      }
      if (process != null) {
        try {
          process.destroy();
        } catch (Throwable t) {
        }
        process = null;
      }
      if (stdout != null) {
        try {
          stdout.close();
        } catch (Throwable t) {
        }
        stdout = null;
      }
      if (error instanceof Exception) {
        throw (Exception) error;
      }
      throw new UndeclaredThrowableException(error);
    }
  }