/**
   * ログ取得コードをThrowableのcatch節として追加する
   *
   * @param pool Statementを含むプール
   * @param ctClass PreparedStatementを実装するクラス
   * @param behaviour behaviour
   * @throws CannotCompileException コンパイルができないときの例外
   */
  public static void convertCatch(
      final ClassPool pool, final CtClass ctClass, final CtBehavior behaviour)
      throws CannotCompileException {
    try {
      CtClass throwable = pool.get("java.lang.Throwable");

      // メソッドの定義がない場合は実行しない。
      final int MODIFIER = behaviour.getModifiers();
      if (Modifier.isAbstract(MODIFIER)) {
        return;
      }

      // JavelinLogger#writeExceptionLogの呼び出しコードを作成する。
      StringBuffer code = new StringBuffer();

      // 後処理(例外場合)
      code.append(JAVELIN_RECORDER_NAME);
      code.append(".postProcessNG(");
      code.append("$e");
      code.append(");");

      // 例外を再throwする。
      code.append("throw $e;");

      // ログ取得コードをThrowableのcatch節として追加する。
      behaviour.addCatch(code.toString(), throwable);
    } catch (NotFoundException nfe) {
      SystemLogger.getInstance().warn(nfe);
    }
  }
  /**
   * Statementのメソッドに対して計測コードを埋め込む。
   *
   * @param pool Statementを含むプール。
   * @param ctClass Statementを実装するクラス
   * @return 変換結果
   */
  public static CtClass convertConnection(final ClassPool pool, final CtClass ctClass) {
    CtClass jvnConnction;
    try {
      jvnConnction = pool.get(JdbcJavelinConnection.class.getCanonicalName());
      boolean hasInterface = hasInterface(ctClass, jvnConnction);
      if (hasInterface == false) {
        ctClass.addInterface(jvnConnction);
      }

      // すでにメソッドを追加している場合は処理を行わない
      if (hasBehavior(ctClass, "getJdbcJavelinProcessor")) {
        return ctClass;
      }

      CtField procField =
          CtField.make(
              "private " + DBProcessor.class.getCanonicalName() + " dbProcessor_;", ctClass);
      ctClass.addField(procField);
      CtMethod procGetMethod =
          CtMethod.make(
              "public "
                  + DBProcessor.class.getCanonicalName()
                  + " getJdbcJavelinProcessor(){ return dbProcessor_; }",
              ctClass);
      ctClass.addMethod(procGetMethod);
      CtMethod procSetMethod =
          CtMethod.make(
              "public void setJdbcJavelinProcessor("
                  + DBProcessor.class.getCanonicalName()
                  + " dbProcessor){ dbProcessor_ = dbProcessor; }",
              ctClass);
      ctClass.addMethod(procSetMethod);

      CtField urlField = CtField.make("private String jdbcUrl_;", ctClass);
      ctClass.addField(urlField);
      CtMethod urlMethod = CtMethod.make("public String getJdbcUrl(){ return jdbcUrl_; }", ctClass);
      ctClass.addMethod(urlMethod);
      CtMethod urlSetMethod =
          CtMethod.make(
              "public void " + "setJdbcUrl(String jdbcUrl)" + "{ jdbcUrl_ = jdbcUrl; }", ctClass);
      ctClass.addMethod(urlSetMethod);
    } catch (NotFoundException ex) {
      SystemLogger.getInstance().warn(ex);
      return null;
    } catch (CannotCompileException ex) {
      SystemLogger.getInstance().warn(ex);
      return null;
    }

    CtBehavior[] behaviors = ctClass.getDeclaredBehaviors();
    for (int index = 0; index < behaviors.length; index++) {
      CtBehavior method = behaviors[index];
      // メソッドの定義がない場合、あるいはpublicでない
      // (->インターフェースに定義されていない)場合は実行しない。
      final int MODIFIER = method.getModifiers();
      if (Modifier.isAbstract(MODIFIER) || !Modifier.isPublic(MODIFIER)) {
        continue;
      }
      // BCI対象クラス「java.sql.Connection」に対して、コード転換を行う
      String methodName = method.getName();
      try {
        if ("prepareStatement".equals(methodName)) {
          addSqlToFieldCon(ctClass, method);
        } else if ("prepareCall".equals(methodName)) {
          addSqlToFieldCon(ctClass, method);
        }
      } catch (CannotCompileException ex) {
        SystemLogger.getInstance().warn(ex);
      }
    }

    try {
      return ctClass;
    } catch (Exception ex) {
      SystemLogger.getInstance().warn(ex);
      return null;
    }
  }