/**
  * ジョブ開始時、終了時、失敗時の処理を埋め込む。
  *
  * @param ctMethod 埋め込み対象のメソッド
  * @throws CannotCompileException
  */
 private void insertProcessesForJob(final CtBehavior ctMethod) throws CannotCompileException {
   ctMethod.insertBefore(MapReduceTaskMonitor.class.getName() + ".preProcess(this);");
   ctMethod.insertAfter(MapReduceTaskMonitor.class.getName() + ".postProcess(this);");
   ctMethod.addCatch(
       "{"
           + MapReduceTaskMonitor.class.getName()
           + ".postProcessNG(this, $e); $e.printStackTrace(); throw $e;}",
       throwableClass_);
 }
  /**
   * PreparedStatement#close用にコードを埋め込む
   *
   * @param ctClass PreparedStatementを実装するクラス
   * @param method closeメソッド
   * @throws CannotCompileException コード埋め込みに失敗した場合
   */
  public static void convertPreparedMethodClose(final CtClass ctClass, final CtBehavior method)
      throws CannotCompileException {
    String className = ctClass.getName();
    className = className.substring(className.lastIndexOf('.') + 1);

    // 前処理を埋め込む
    String key = "javelin.jdbc.instrument.JdbcJavelinConverter.ModifiedMethodLabel";
    String message = JdbcJavelinMessages.getMessage(key, className, method.getName());
    SystemLogger.getInstance().info(message);
    method.insertAfter(BCI_METHOD_PLANFORPREPARED_CLOSE);
  }
  /**
   * PreparedStatementのexecuteメソッドに、 バインド引数保存用ArrayList初期化処理を追加する。
   *
   * @param ctClass 変換対象のクラス。
   * @param method メソッド。
   * @throws CannotCompileException javassistがコンパイルに失敗した場合。
   */
  private static void convertExecuteMethod(final CtClass ctClass, final CtBehavior method)
      throws CannotCompileException {
    String className = ctClass.getName();
    className = className.substring(className.lastIndexOf('.') + 1);

    // 前処理を埋め込む
    String key = "javelin.jdbc.instrument.JdbcJavelinConverter.ModifiedMethodLabel";
    String message = JdbcJavelinMessages.getMessage(key, className, method.getName());
    SystemLogger.getInstance().info(message);
    method.insertAfter(
        "this.jdbcJavelinBindValIndex_ = 0;" + "this.flagForPlanStmt_ = false;", true);
  }
  /**
   * フィールドからSQLを削除する
   *
   * @param ctClass クラス
   * @param method メソッド
   * @throws CannotCompileException コンパイル不可時のエラー
   */
  public static void delSqlFromField(final CtClass ctClass, final CtBehavior method)
      throws CannotCompileException {
    // 実行しているSQL文を追加する用コードを追加する(Statementの方)
    String addSqlCode = "if(this != null) this.jdbcJavelinSql_.clear();";
    method.insertAfter(addSqlCode);

    if (SystemLogger.getInstance().isDebugEnabled()) {
      String tagKey = "javelin.jdbc.instrument.JdbcJavelinConverter.JDBCJavelinTag";
      String jdbcJavelinTag = JdbcJavelinMessages.getMessage(tagKey);
      String messageKey = "javelin.jdbc.instrument.JdbcJavelinConverter.SQLDeletedLabel3";
      String logMessage = JdbcJavelinMessages.getMessage(messageKey, method.getName());
      SystemLogger.getInstance().debug(jdbcJavelinTag + logMessage);
    }
  }
 private static void addSqlToFieldCon(final CtClass ctClass, final CtBehavior method)
     throws CannotCompileException {
   String addSqlCode =
       JdbcJavelinRecorder.class.getName()
           + ".postPrepareStatement($0, $1, $_, \""
           + method.getName()
           + "\");";
   method.insertAfter(addSqlCode);
   String key = "javelin.jdbc.instrument.JdbcJavelinConverter.ModifiedMethodLabel";
   String message = JdbcJavelinMessages.getMessage(key, ctClass.getName(), method.getName());
   SystemLogger.getInstance().info(message);
   if (SystemLogger.getInstance().isDebugEnabled()) {
     String tegKey = "javelin.jdbc.instrument.JdbcJavelinConverter.JDBCJavelinTag";
     String jdbcJavelinTag = JdbcJavelinMessages.getMessage(tegKey);
     String messageKey = "javelin.jdbc.instrument.JdbcJavelinConverter.SQLAddedLabel1";
     String logMessage = JdbcJavelinMessages.getMessage(messageKey, method.getName());
     SystemLogger.getInstance().debug(jdbcJavelinTag + logMessage);
   }
 }
  /**
   * StatsJavelinによる計測コードを埋め込む。
   *
   * @param ctClass クラス
   * @param method メソッド
   * @throws CannotCompileException メソッドの開始位置と終了位置にコードを埋め込めなかった場合
   */
  public static void addRecordCode(final CtClass ctClass, final CtBehavior method)
      throws CannotCompileException {
    // 前処理ログコードを作る
    StringBuffer callPreProcessCodeBuffer = new StringBuffer();
    callPreProcessCodeBuffer.append(JAVELIN_RECORDER_NAME);
    CtClass[] parameterTypes = null;
    boolean paramZero = false;
    try {
      parameterTypes = method.getParameterTypes();
    } catch (NotFoundException ex) {
      SystemLogger.getInstance().warn("", ex);
    }
    if (parameterTypes != null && (parameterTypes.length > 0)) {
      callPreProcessCodeBuffer.append(".preProcessParam(");
      callPreProcessCodeBuffer.append("$0");
      callPreProcessCodeBuffer.append(", $args);");
    } else {
      callPreProcessCodeBuffer.append(".preProcessSQLArgs(");
      callPreProcessCodeBuffer.append("$0");
      callPreProcessCodeBuffer.append(", this.getJdbcJavelinSql().toArray());");
      paramZero = true;
    }
    String callPreProcessCode;
    callPreProcessCode = callPreProcessCodeBuffer.toString();

    // 後処理ログコードを作る
    StringBuffer callPostProcessCodeBuffer = new StringBuffer();
    callPostProcessCodeBuffer.append(JAVELIN_RECORDER_NAME);
    // Recorderにて実行計画取得にStatemen、クラス名、メソッド名が必要
    callPostProcessCodeBuffer.append(".postProcessOK($0");
    if (paramZero == false) { // 引数の数をpostProcessOKに渡す
      callPostProcessCodeBuffer.append(", 1"); // 引数1以上
    } else {
      callPostProcessCodeBuffer.append(", 0"); // 引数0
    }

    callPostProcessCodeBuffer.append(");");
    String returnPostProcessCode = callPostProcessCodeBuffer.toString();
    //		JavelinErrorLogger.getInstance().log("modified class:" + className);
    method.insertBefore(callPreProcessCode);
    method.insertAfter(returnPostProcessCode);
  }
  private static void addSqlToFieldStat(final CtClass ctClass, final CtBehavior method)
      throws CannotCompileException {
    try {
      CtClass[] parameterTypes = method.getParameterTypes();
      if (!(parameterTypes == null) && (parameterTypes.length > 0)) {
        // 実行しているSQL文を追加する用コードを追加する(StatementのaddBatchメソッド用)
        String addSqlCode = "if(this != null) this.jdbcJavelinSql_.add($1);";
        method.insertAfter(addSqlCode);

        if (SystemLogger.getInstance().isDebugEnabled()) {
          String tagKey = "javelin.jdbc.instrument.JdbcJavelinConverter.JDBCJavelinTag";
          String jdbcJavelinTag = JdbcJavelinMessages.getMessage(tagKey);
          String messageKey = "javelin.jdbc.instrument.JdbcJavelinConverter.SQLAddedLabel2";
          String logMessage = JdbcJavelinMessages.getMessage(messageKey, method.getName());
          SystemLogger.getInstance().debug(jdbcJavelinTag + logMessage);
        }
      }
    } catch (NotFoundException e) {
      SystemLogger.getInstance().warn("", e);
    }
  }