Quantcast
Channel: プログラム の個人的なメモ
Viewing all 860 articles
Browse latest View live

【Java】パーセントエンコーディングをJavaで自作する

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37109157.html
で、標準のjava.net.URLEncoder.encode() を試したが、以下のAPI
https://docs.oracle.com/javase/jp/8/docs/api/java/net/URLEncoder.html
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 * 特殊文字の「.」、「-」、「*」、および「_」は元のまま残します。
 * 空白文字「 」はプラス記号「+」に変換されます。
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
と記載されているが、本来は、
以下のようにパーセントエンコーディング(percent-encoding)を行わなければならない。
https://iwb.jp/s/ascii-url-encode-decode-list-and-convert-tool/
http://www.asahi-net.or.jp/~ax2s-kmtn/ref/uric.html
`記号
`#
エンコーディング後
1.%2E
2-%2D
3*%2A
4_%5F
5Space%20

実際、java.net.URLEncoder.encode()の値を、Basic認証があるプロキシ
https://blogs.yahoo.co.jp/dk521123/37045638.html
で、試したところ、上記のような変換が必要だったので、対応できるようにJavaで実装してみる

サンプル

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public class PercentEncoder {

  private static final String ENCODE = "UTF-8";
  private static final HashMap<String, String> MAPPER = new HashMap<String, String>() {
    private static final long serialVersionUID = 1L;
    {
      put(".", "%2E");
      put("-", "%2D");
      put("*", "%2A");
      put("_", "%5F");
      put("+", "%20");
    }
  };

  public static void main(String[] args) {

    try {
      String targetValue = " !\"#$%&'()*+,-./0123456789:;<=>?@";
      String result = PercentEncoder.encode(targetValue);
      System.out.println("Result  : " + result);
      System.out.println("Expected: %20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F0123456789%3A%3B%3C%3D%3E%3F%40");

      targetValue = "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz";
      result = PercentEncoder.encode(targetValue);
      System.out.println("Result  : " + result);
      System.out.println("Expected: ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E%5F%60abcdefghijklmnopqrstuvwxyz");

      targetValue = "{|}~";
      result = PercentEncoder.encode(targetValue);
      System.out.println("Result  : " + result);
      System.out.println("Expected: %7B%7C%7D%7E");
    } catch (UnsupportedEncodingException ex) {
      ex.printStackTrace();
    }
  }

  public static String encode(String targetValue) throws UnsupportedEncodingException {
    String returnValue = URLEncoder.encode(targetValue, PercentEncoder.ENCODE);
    for(Map.Entry<String, String> map : MAPPER.entrySet()) {
      returnValue = returnValue.replace(map.getKey(), map.getValue());
    }
    return returnValue;
  }
}

出力結果

Result  : %20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F0123456789%3A%3B%3C%3D%3E%3F%40
Expected: %20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F0123456789%3A%3B%3C%3D%3E%3F%40
Result  : ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E%5F%60abcdefghijklmnopqrstuvwxyz
Expected: ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E%5F%60abcdefghijklmnopqrstuvwxyz
Result  : %7B%7C%7D%7E
Expected: %7B%7C%7D%7E

関連記事

【Java】URLエンコーディング

https://blogs.yahoo.co.jp/dk521123/37109157.html

パッケージ管理コマンド ~ プロキシ経由でapt系コマンドを実行するには... ~

https://blogs.yahoo.co.jp/dk521123/37045638.html

プロキシサーバソフト [2] ~ Squid / Basic認証編 ~

https://blogs.yahoo.co.jp/dk521123/36962466.html

【Java】X.500 識別名(X500Principal)の文字列形式の共通処理を作成する

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37097725.html
で使用した以下のメソッド
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 + X509Certificate.getIssuerX500Principal()
 + X509Certificate.getSubjectX500Principal()
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
の戻り値 X500Principal が思った以上にメソッドが少なく、
例えば、「一般名 / CN(Common Name)」だけ個別に取得したくてもできない。

そこで、CNやOUなどの値を個別に扱えるように、自作してみた

■ サンプル

import java.text.MessageFormat;
import java.util.Map;
import java.util.TreeMap;

/**
 * 識別名(DN: Distinguished Name)タイプ.
 *
 * @see https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
 * @see http://www.atmarkit.co.jp/ait/articles/0612/23/news012.html
 * @see https://docs.oracle.com/cd/E19146-01/820-0875/geezw/index.html
 */
public enum DistinguishedNameType implements Comparable<DistinguishedNameType> {
  /** 一般名 / CN(Common Name). */
  COMMON_NAME("CN"),
  /** 部門名 / OU(Organizational Unit). */
  ORGANIZATIONAL_UNIT("OU"),
  /** 組織名 / O(Organization). */
  ORGANIZATION("O"),
  /** ストリート名 / STREET(Street). */
  STREET("STREET"),
  /** 市区町村名 / L(Locality). */
  LOCALITY("L"),
  /** 都道府県名 / ST(state Or Province Name). */
  STATE_OR_PROVINCE_NAME("ST"),
  /** 都道府県名 / S(State). */
  STATE("S"),
  /** 国名 / C(Country). */
  COUNTRY("C"),
  /** ドメイン / DC( Domain Component). */
  DOMAIN_COMPONENT("DC"),
  /** ユーザID / UID(user id). */
  USER_ID("UID"),
  /** E-mail / E(E-mail). */
  EMAIL("E"),
  /** その他. */
  OTHERS("");

  /** フォーマット. */
  private static final String FORMAT = "{0} = {1}";
  /** 改行. */
  private static final String NEW_LINE = System.getProperty("line.separator");
  /** 変換マッパー. */
  private static Map<String, DistinguishedNameType> convertMapper;
  /** コード. */
  private String code;

  static {
    convertMapper = new TreeMap<String, DistinguishedNameType>();
    for (DistinguishedNameType type : DistinguishedNameType.values()) {
      convertMapper.put(type.getCode(), type);
    }
  }

  /**
   * コンストラクタ.
   *
   * @param code
   *          コード
   */
  private DistinguishedNameType(String code) {
    this.code = code;
  }

  /**
   * コードを取得する.
   *
   * @return コード
   */
  public String getCode() {
    return this.code;
  }

  /**
   * X.500 識別名のMap化.
   * @param targetValue RFC 2253 で定義された形式で、X.500 識別名の文字列形式
   * @return  X.500 識別名のMap形式
   * @see https://docs.oracle.com/javase/jp/6/api/javax/security/auth/x500/X500Principal.html#getName()
   * @see https://www.ipa.go.jp/security/rfc/RFC2253JA.html
   */
  public static Map<DistinguishedNameType, String> parse(String targetValue) {
    if (targetValue == null) {
      return null;
    }

    Map<DistinguishedNameType, String> returnValues = new TreeMap<DistinguishedNameType, String>();

    String[] attributes = targetValue.split("(?<!\\\\),");
    for (String attribute : attributes) {
      String[] parts = attribute.split("(?<!\\\\)=");
      String type = parts[0];
      if (type == null || type.isEmpty() || !convertMapper.containsKey(type)) {
        String value = returnValues.get(DistinguishedNameType.OTHERS);
        if (value == null) {
          returnValues.put(DistinguishedNameType.OTHERS, attribute);
        } else {
          returnValues.put(DistinguishedNameType.OTHERS, value + NEW_LINE + attribute);
        }
      } else {
        DistinguishedNameType targetType = convertMapper.get(type);
        String value = parts[1];
        returnValues.put(targetType, value);
      }
    }
    return returnValues;
  }

  /**
   * 文字列化.
   * @param targetValue RFC 2253 で定義された形式で、X.500 識別名の文字列形式
   * @return テキストデータ
   * @see https://docs.oracle.com/javase/jp/6/api/javax/security/auth/x500/X500Principal.html#getName()
   * @see https://www.ipa.go.jp/security/rfc/RFC2253JA.html
   */
  public static String toString(String targetValue) {
    Map<DistinguishedNameType, String> targetMaps = DistinguishedNameType.parse(targetValue);
    return DistinguishedNameType.toString(targetMaps);
  }

  /**
   * 文字列化.
   * @param targetMaps X.500 識別名のMap形式
   * @return テキストデータ
   */
  public static String toString(Map<DistinguishedNameType, String> targetMaps) {
    if (targetMaps == null || targetMaps.isEmpty()) {
      return "";
    }

    StringBuilder returnValue = new StringBuilder();
    int index = 0;
    for (Map.Entry<DistinguishedNameType, String> map : targetMaps.entrySet()) {
      if (index != 0) {
        returnValue.append(NEW_LINE);
      }
      DistinguishedNameType targetType = map.getKey();
      if (DistinguishedNameType.OTHERS.equals(targetType)) {
        returnValue.append(map.getValue());
      } else {
        returnValue.append(MessageFormat.format(FORMAT, map.getKey().getCode(), map.getValue()));
      }
      index++;
    }
    return returnValue.toString();
  }
}


関連記事

Javaで、キーストアから証明書を追加・削除などを行う

https://blogs.yahoo.co.jp/dk521123/37097725.html

【トラブル】【Java】Webサービスに関わる例外について

$
0
0

■ プロキシ認証が実装されていない場合

エラー内容

javax.xml.ws.WebServiceException:
   ... 略 ...
Caused by: java.io.IOException: Server returned HTTP response code: 407 for URL: http://...
   ... 略 ...

解決策

 * プロキシ認証が実装する。詳細は、以下の関連記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/36966230.html
より

Authenticator.setDefault(new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("【ユーザ名】", "【パスワード】".toCharArray());
  }
});

■ 認証情報に誤りがあった場合

エラー内容

javax.xml.ws.WebServiceException:
   ... 略 ...
Caused by: java.net.ProtocolException: Server redirected too many  times (20)
   ... 略 ...

解決策

 * プロキシ認証に正しい値を設定する

参考文献

http://x68000.q-e-d.net/~68user/net/java-http-url-connection-2.html

■ タイムアウトした場合

エラー内容

com.sun.xml.internal.ws.client.ClientTransportException:
   ... 略 ...
Caused by: java.net.SocketTimeoutException: connect timed out
   ... 略 ...

解決策

 * 接続情報(ホスト名やポート)に正しい値を設定する

■ URLに誤りがある場合

エラー内容

com.sun.xml.internal.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
java.io.FileNotFoundException: http://... 略 ...

解決策

 * 正しいURL値を設定する

URL url = new URL("【WSDLのURL】");

■ URLのポートに誤りがある場合

エラー内容

javax.xml.ws.WebServiceException: 次の場所でWSDLへのアクセスに失敗しました:
   ... 略 ...
Caused by: java.io.IOException: Server returned HTTP response code: 503 for URL: http://... 略 ...

解決策

 * 正しいURLのポート値を設定する

関連記事

Javaで、プロキシサーバ経由で接続する

https://blogs.yahoo.co.jp/dk521123/36966230.html

【Docker】 Docker ~ Windows / 入門編 ~

$
0
0

Docker とは?

Docker(ドッカー)
 *

+------------------+
|                  |
+------------------+
|                  |
+------------------+
|                  |
+------------------+
|                  |
+------------------+

構築手順

ダウンロード

 * 以下のサイトから「Get Docker for Windows (Stable)」をクリックし、
   インストーラ「Docker for Windows Installer.exe」をダウンロードする
ダウンロード先
https://docs.docker.com/docker-for-windows/install/#download-docker-for-windows

【トラブル】Docker によるトラブルシューティング

$
0
0

コマンド「docker pull centos:latest」を実行後にエラー表示

エラー内容

docker: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).

解決策

 * Dockerアイコンを右クリックし、[Settings]-[Network]で
   DNS Server での設定のAutomaticを止めて、Fixedの8.8.8.8に切り替える

参考文献

http://satoyashiki.hatenablog.com/entry/2017/04/01/1756

関連記事

Docker ~ Windows / 入門編 ~

https://blogs.yahoo.co.jp/dk521123/37128692.html

【Java】ラムダ式 ~ 応用編 / サンプル集・その2 / 過去直近データを取得する ~

$
0
0

■ はじめに

 * SQLとかでよくやる過去直近をJava8から導入されたラムダ式で書いてみる。

■ 方法

他にもっといい方法がありそうだが...
 * filter と max/min で実装する。

list.stream().filter(x -> x.【日付】.compareTo(【基準日】) <= 0)
        .max((x1, x2) -> x1.【日付】.compareTo(x2.【日付】)).get();

// [1] filter で【基準日】より未来日を間引く
// [2][1]で間引いたデータから最新日付を取得する

■ サンプル

Rate.java

import java.math.BigDecimal;
import java.util.Calendar;

public class Rate {
  private String currency;
  private BigDecimal rateValue;
  private Calendar date;

  public Rate(String currency, BigDecimal rateValue, Calendar date) {
    this.currency = currency;
    this.rateValue = rateValue;
    this.date = date;
  }

  public String getCurrency() {
    return this.currency;
  }

  public void setCurrency(String currency) {
    this.currency = currency;
  }

  public BigDecimal getRateValue() {
    return this.rateValue;
  }

  public void setRateValue(BigDecimal rateValue) {
    this.rateValue = rateValue;
  }

  public Calendar getDate() {
    return this.date;
  }

  public void setDate(Calendar date) {
    this.date = date;
  }
}

Main.java

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class Main {

  public static void main(String[] args) {
    List<Rate> rates = new ArrayList<>();
    rates.add(new Rate("JPY", new BigDecimal("101.12"), createCalendar(2017, 11, 20)));
    rates.add(new Rate("JPY", new BigDecimal("120.90"), createCalendar(2018, 8, 10)));
    rates.add(new Rate("JPY", new BigDecimal("110.01"), createCalendar(2017, 7, 10)));
    rates.add(new Rate("JPY", new BigDecimal("98.96"), createCalendar(2017, 4, 10)));
    rates.add(new Rate("JPY", new BigDecimal("87.45"), createCalendar(2015, 3, 20)));

    Calendar targerDate1 = createCalendar(2017, 6, 10);
    Rate result1 = getLatetRate(rates, targerDate1);
    System.out.println("Latest Rate from 2017/5/10 : " + result1.getRateValue());

    Calendar targerDate2 = createCalendar(2018, 10, 10);
    Rate result2 = getLatetRate(rates, targerDate2);
    System.out.println("Latest Rate from 2018/9/10 : " + result2.getRateValue());

    Calendar targerDate3 = createCalendar(2017, 7, 10);
    Rate result3 = getLatetRate(rates, targerDate3);
    System.out.println("Latest Rate from 2017/6/10 : " + result3.getRateValue());
  }

  // 過去直近
  private static Rate getLatetRate(List<Rate> rates, Calendar targerDate) {
    return rates.stream().filter(rate -> rate.getDate().compareTo(targerDate) <= 0)
        .max((rate1, rate2) -> rate1.getDate().compareTo(rate2.getDate())).get();
  }

  private static Calendar createCalendar(int year, int month, int day) {
    Calendar returnValue = Calendar.getInstance();
    returnValue.set(year, month, day);
    return returnValue;
  }
}
出力結果
Latest Rate from 2017/5/10 : 98.96
Latest Rate from 2018/9/10 : 120.90
Latest Rate from 2017/6/10 : 110.01

関連記事

【Java】ラムダ式 ~入門編~

https://blogs.yahoo.co.jp/dk521123/34188394.html

【Java】ラムダ式 ~ 基本編 / Stream API ~

https://blogs.yahoo.co.jp/dk521123/34192426.html

ラムダ式 ~ 応用編 / サンプル集・その1 ~

https://blogs.yahoo.co.jp/dk521123/37093852.html

ラムダ式 ~ 応用編 / サンプル集・その2 / 過去直近データを取得する ~

https://blogs.yahoo.co.jp/dk521123/37132834.html

【MySQL】 INSERT INTO ~ ON DUPLICATE KEY UPDATE ~の使用上の注意

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/36225584.html
で扱ったInsert or Update「INSERT INTO ~ ON DUPLICATE KEY UPDATE ~」で
盲点だったことをまとめる。

■ 使用上の注意

 * AUTO_INCREMENT を使用しているテーブルで、「INSERT INTO ~ ON DUPLICATE KEY UPDATE ~」を使用した場合
   UPDATE処理が走った場合でも、インクリメントされてしまう

■ 例

CREATE TABLE

CREATE TABLE `fruit` (
  `id` INT(11) AUTO_INCREMENT NOT NULL PRIMARY KEY,
  `name` VARCHAR(100) NOT NULL UNIQUE,
  `price` INT(11) NULL DEFAULT NULL,
  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
  `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時'
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

SQL

* ここからが本番
-- 二回実行する
INSERT INTO fruit
(
  name,
  price
) VALUES (
  'Orange',
  120
) ON DUPLICATE KEY UPDATE
  name = 'Orange',
  price = 121
;

-- 三回目で実行する
INSERT INTO fruit
(
  name,
  price
) VALUES (
  'Apple',
  99
) ON DUPLICATE KEY UPDATE
  name = 'Apple',
  price = 97
;

出力結果

1回目
`name`created_at
`id
`price
updated_at 1 Orange 120 2017-09-27 23:15:20 2017-09-27 23:15:20
""
2回目
`name`created_at
`id
`price
updated_at 1 Orange 121 2017-09-27 23:15:20 2017-09-27 23:16:13
3回目 ★id=3になっている★
`name`created_at
`id
`price
updated_at 1 Orange 121 2017-09-27 23:15:20 2017-09-27 23:16:13 3 Apple 99 2017-09-27 23:17:32 2017-09-27 23:17:32

参考文献

https://qiita.com/yamikoo@github/items/b39f683626740be54c3a

関連記事

【MySQL】 データあればUPDATE、なければINSERT ~ DUPLICATE KEY ~

https://blogs.yahoo.co.jp/dk521123/36225584.html

【MySQL】MySQLの日時に関する自動初期化および更新機能

$
0
0

■ はじめに

 テーブルには、よく作成日時、更新日時を付けることが多いが
それらに付与する「自動初期化」および「更新機能」があるので取り上げる

 また、使用する際の注意点を記す。 

■ 構文(CREATE TABLE)

・・・略・・・
【作成日時】 DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
【更新日時】 DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時'
・・・略・・・

■ 使用上の注意

 * 値が変わらないと、更新日時も更新されない(以下の「サンプル」の「[2-2] 更新処理(変更なし)」を参照)

■ サンプル

CREATE TABLE

CREATE TABLE `sample` (
  `value` VARCHAR(5) NOT NULL,
  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
  `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時'
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

更新処理(実験として)

-- [1] 追加処理
INSERT INTO sample(value) VALUES ('00001');

SELECT * FROM sample;

SELECT SLEEP(2);

-- [2-1] 更新処理
UPDATE sample SET value='00002' WHERE value='00001';

SELECT * FROM sample;

SELECT SLEEP(2);

-- [2-2] 更新処理(変更なし)
UPDATE sample SET value='00002' WHERE value='00002';

SELECT * FROM sample;

SELECT SLEEP(2);

-- [2-3] 更新処理(変更なし。更新日時に値を設定する)
UPDATE sample SET value='00002', updated_at='1978-11-11 00:00:00' WHERE value='00002';

SELECT * FROM sample;

SELECT SLEEP(2);

-- [2-4] 更新処理(変更なし。更新日時に値を設定する)
UPDATE sample SET value='00002', updated_at=CURRENT_TIMESTAMP WHERE value='00002';

SELECT * FROM sample;
出力結果
-- [1] 追加処理
`created_at
`value
updated_at
000012017-09-28 22:31:502017-09-28 22:31:50

-- [2-1] 更新処理
`created_at
`value
updated_at
000022017-09-28 22:31:502017-09-28 22:31:52

-- [2-2] 更新処理(変更なし)

※ 値が変わらないと、更新日時も更新されない
`created_at
`value
updated_at
000022017-09-28 22:31:502017-09-28 22:31:52

-- [2-3] 更新処理(変更なし。更新日時に値を設定する)
`created_at
`value
updated_at
000022017-09-28 22:31:501978-11-11 00:00:00

-- [2-4] 更新処理(変更なし。更新日時に値を設定する)
`created_at
`value
updated_at
000022017-09-28 22:31:502017-09-28 22:31:59

参考文献

公式サイト

https://dev.mysql.com/doc/refman/5.6/ja/timestamp-initialization.html

【Java】 音声認識 / Google Cloud Speech API を使う

【Google Cloud】 音声認識 / Google Cloud Speech API ~ 入門編 ~

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37139755.html
で、認識率が高かった「Google Cloud Speech API」について、調べてみた

■ Google Cloud Speech API

 * Google の音声認識クラウドサービス
 * 有料だが、無料枠もあるので、開発者にやさしい

入門ガイド

https://cloud.google.com/speech/docs/how-to?hl=ja

サンプル

Java
https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/speech/

■ Google Cloud Speech APIを使用する当たって

 * 以下のクイックスタートを参考にしながらやる。
https://cloud.google.com/speech/docs/getting-started?hl=ja
[1] Google Cloud Platform の プロジェクトを設定する
 [1-1] Cloud Platform Console で、プロジェクトを作成する
 [1-2] 課金を有効にする(クレジットカードを登録とかする必要がある)
 [1-3] Google Cloud Speech API を有効にする
 [1-4] 認証情報を設定 (以下は、認証情報の種類)
  * API キー
  * OAuth クライアント ID
  * サービス アカウント キー << Googleの推奨はこっち

※以降、調査中


関連記事

日本語対応の音声認識サービス

https://blogs.yahoo.co.jp/dk521123/37139755.html

【JUnit】 AssertJ / AssertJ-DB ~ 日付 / 時間 / 日時 の比較 ~

$
0
0

比較するメソッド

 * isEqualTo
 * isAfter
 * isAfterOrEqualTo
 * isBefore
 * isBeforeOrEqualTo

関連するクラス

 * DateTimeValue
  =>  yyyy-mm-dd, yyyy-mm-ddThh:mm, yyyy-mm-ddThh:mm:ss or yyyy-mm-ddThh:mm:ss.nnnnnnnnn
http://joel-costigliola.github.io/assertj/db/1.2.x/api/org/assertj/db/type/DateTimeValue.html

関連記事

DBにまつわる単体試験 [3] ~ AssertJ / AssertJ-DB ~

http://blogs.yahoo.co.jp/dk521123/36157721.html

AssertJ / AssertJ-DB ~ 日付 / 時間 / 日時 について ~

https://blogs.yahoo.co.jp/dk521123/36164701.html

MySQL利用でAssertJ-DB を使った単体テストを行ったら日時でエラーになる

http://blogs.yahoo.co.jp/dk521123/36167284.html

【AWS】【Aurora】Aurora の ゼロダウンタイムパッチ機能 (ZDP)

$
0
0

■ はじめに

https://qiita.com/tonishy/items/542f7dd10cc43fd299ab
と、同じで、Aurora 1.14 強制アップグレード通知が来た。
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.html
によると、「更新では、データベースを再起動する必要があるため、20~30 秒間のダウンタイムが発生」
とあるので、サポートに問い合わせたら、ゼロダウンタイムパッチ機能を教えてもらったので、まとめる。

■ (一般用語として)ゼロダウンタイムパッチ

ゼロダウンタイムパッチ(ZDP:zero-downtime-patching)
 * データベースやソフトウェアにパッチを適用するときのダウンタイムを極力なくせる機能

■ Aurora の ゼロダウンタイムパッチ

 * Aurora 1.10からの機能
 * とはいえ、一時的に (5 秒ほど) 落ちる場合がある

条件

以下の状態では正常に実行されない
 * 実行時間が長いクエリが進行中である
 * 実行時間が長いトランザクションが開いている
 * バイナリログ記録が有効になっている
 * バイナリログのレプリケーションが実行中である
 * パラメータの変更が保留中である
 * 一時テーブルが使用中である
 * テーブルロックが使用中である
 * オープン SSL 接続がある

【Java】 JAXBアノテーション ~ サンプル編 ~

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/32096812.html
http://blogs.yahoo.co.jp/dk521123/36358058.html
https://blogs.yahoo.co.jp/dk521123/34971111.html
の続き。

JAXB(Java Architecture for XML Binding)アノテーションのサンプルを記す。

■ サンプル

Person.java

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="person")
public class Person implements Serializable {
  private static final long serialVersionUID = 1L;

  @XmlElement(name = "name", nillable = false)
  private String name;
  @XmlElement(name = "age")
  private int age;
  @XmlElement(name = "woman")
  private boolean isWoman;

  public Person() {
    this(null, -1, false);
  }
  public Person(String name, int age, boolean isWoman) {
    this.name = name;
    this.age = age;
    this.isWoman = isWoman;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return this.age;
  }

  public void setAge(int age) {
    this.age = age;
  }
  public boolean isWoman() {
    return this.isWoman;
  }
  public void setWoman(boolean isWoman) {
    this.isWoman = isWoman;
  }
}

XmlSerializer.java

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class XmlSerializer {
  // 実験用
  public static void main(String[] args) {
    // Case1 : 単一
    Person person = new Person("Isabella", 3, true);
    String fileName1 = "person.xml";
    XmlSerializer.save(fileName1, person);

    Person newPerson = XmlSerializer.loadValue(fileName1, Person.class);

    // 出力
    System.out.println("Case1 : 単一");
    System.out.println(newPerson.getName() + "(" + newPerson.getAge() + ") is Woman? : " + newPerson.isWoman());
    System.out.println("");

    // Case2 : リスト
    List<Person> people = new ArrayList<>();
    Person person1 = new Person("Ken", 62, true);
    people.add(person1);

    Person person2 = new Person("Coco", 10, false);
    people.add(person2);

    String fileName = "people.xml";
    XmlSerializer.save(fileName, people);

    List<Person> newPeople = XmlSerializer.loadValues(fileName, Person.class);

    // 出力
    System.out.println("Case2 : リスト");
    for (Person newPersonInList : newPeople) {
      System.out.println(
          newPersonInList.getName() + "(" + newPersonInList.getAge() + ") is Woman? : " + newPersonInList.isWoman());
    }
    System.out.println("");

    System.out.println("Done");
  }

  // 共通化

  public static <T> void save(String fileName, T objectToSave) {
    try (XMLEncoder xMLEncoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(fileName)));) {
      xMLEncoder.writeObject(objectToSave);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  public static <T> T loadValue(String fileName, Class<T> clazz) {
    Object value = XmlSerializer.load(fileName);
    if (value == null || value.getClass() != clazz) {
      return null;
    }
    return clazz.cast(value);
  }

  @SuppressWarnings("unchecked")
  public static <T> List<T> loadValues(String fileName, Class<T> clazz) {
    Object value = XmlSerializer.load(fileName);
    if (value == null || !(value instanceof List<?>)) {
      Collections.emptyList();
    }
    List<Object> values = (List<Object>) value;
    if (values.isEmpty() || !values.get(0).getClass().isAssignableFrom(clazz)) {
      return Collections.emptyList();
    }

    return (List<T>) values;
  }

  private static Object load(String fileName) {
    try (XMLDecoder xMLDecoder = new XMLDecoder(new BufferedInputStream(new FileInputStream(fileName)));) {
      return xMLDecoder.readObject();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    return null;
  }
}

出力結果

コンソール画面
Case1 : 単一
Isabella(3) is Woman? : true

Case2 : リスト
Ken(62) is Woman? : true
Coco(10) is Woman? : false

Done
person.xml
<?xml version="1.0" encoding="UTF-8"?><java version="1.8.0_144" class="java.beans.XMLDecoder"><object class="com.sample.xml.Person"><void property="age"><int>3</int></void><void property="name"><string>Isabella</string></void><void property="woman"><boolean>true</boolean></void></object></java>
person.xml
<?xml version="1.0" encoding="UTF-8"?><java version="1.8.0_144" class="java.beans.XMLDecoder"><object class="java.util.ArrayList"><void method="add"><object class="com.sample.xml.Person"><void property="age"><int>62</int></void><void property="name"><string>Ken</string></void><void property="woman"><boolean>true</boolean></void></object></void><void method="add"><object class="com.sample.xml.Person"><void property="age"><int>10</int></void><void property="name"><string>Coco</string></void></object></void></object></java>


関連記事

JavaオブジェクトのXMLへの読み出し・書き出し

https://blogs.yahoo.co.jp/dk521123/32096812.html

XMLシリアライズ / デシリアライズ

http://blogs.yahoo.co.jp/dk521123/36358058.html

JAXB アノテーション ~ 入門編 ~

https://blogs.yahoo.co.jp/dk521123/34971111.html

【Raspberry PI】Raspberry PI ~ 初期構築編 ~

$
0
0

■ はじめに

 * 購入からOSインストールまで行う

■ 購入

 * ネット(Amazonとか)でも買えるが、秋葉原へ。
 * 以下のサイトを参考に回る。結局、「秋月電子通商 秋葉原店」でスターターキットを買う。
https://liginc.co.jp/250796

スターターキット内容

 * Raspberry PI 3 Model B
 * ディスプレイ (Raspberry Pi 7' Touchscreen Display)
 * ケース
 * 電源ケーブル
 * マイクロSDカード(16GB)
他に用意したもの
 * USBマウス
 * USBキーボード
 * ネット環境(Wifi)

■ OS

 * 対応OSは、以下の「Raspberry PI 対応OS」を参照
  => 今回は、「[1] Raspbian」

Raspberry PI 対応OS

[1] Raspbian (ラズビアン。Debianベース)
[2] Windows 10 IoT Core
[3] Moebius (Debianベース)
[4] RetroPie
[5] OSMC (Open Source Media Center)
[6] Ubuntu MATE(マテ)

etc...

OS導入方法

 * NOOBS(ヌーブス。New Out Of the Box Software)という仕組みを使って
   Raspberry PiにOSをインストールする
以下のサイトが参考になった
https://okuzawats.com/raspberry-pi-os-install-20140904/
[1] NOOBSをPC上からダウンロードする(以下の「ダウンロード先」を参照)
 => 今回は「NOOBS_v2_4_4.zip」
[2] ダウンロードしたNOOBSを解凍し、手持ちのマイクロSDカードに書き込む
 => 直下にデータを置くこと
  ※ 直下に、フォルダ「NOOBS_v2_4_4」を置いていたので、
     以降で行うRaspberry PI 3本体に電源入れても画面にインストールが表示されなかった
[3] Raspberry PI 3本体に、マイクロSDカードを差し込む

ダウンロード先

 * 本当は、「公式サイト」から落としたいのだが時間がかかり過ぎてネットワークエラーになる
   => そのため、日本のミラーサイトから落とす
公式サイト
https://www.raspberrypi.org/downloads/
ミラーサイト (NOOBS)
http://ftp.jaist.ac.jp/pub/raspberrypi/NOOBS/images/

補足:NOOBS と NOOBS Lite との違い

NOOBS
 * NOOBS ダウンロード時に、OSもダウンロードされる
NOOBS Lite
 * OSインストール時に、OSのダウンロードが行われる

■ 組み立て及びOSインストール

この時にマウスがあると便利
[1] 以下のサイトを参考に、ディスプレイとRaspberry PI 3本体を接続する
https://studio.beatnix.co.jp/kids-it/hardware/raspberry_pi/7inch-touch-screen-display/
https://raspberry-pi.ksyic.com/page/page/pgp.id/4
トラブルシューティング
http://yuseinishiyama.com/posts/2013/08/31/setup-raspberrypi/
http://sh1k1ya.hatenablog.com/entry/2015/09/20/Raspberry_Pi%E3%81%AE%E3%82%BF%E3%83%83%E3%83%81%E3%83%87%E3%82%A3%E3%82%B9%E3%83%97%E3%83%AC%E3%82%A4%EF%BC%88%E8%B2%A1%E5%9B%A3%E5%85%AC%E5%BC%8F%EF%BC%89%E3%81%A8%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0
[2] 以下を選択し、左上の「Install」を選択
 + Raspbian
 + Language:日本語
  => しばらくすると、インストール完了ウィンドウが出るので、OK押下
  => 再起動され、OS画面が表示される

【Raspberry PI】Raspberry PI ~ OS環境設定編 ~

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37155840.html
の続き。

 このままでは、ネットはつながってないし、時計も狂ったまま等
色々な基本的な設定をしていく。

■ OS環境設定

[1] ネット環境
[2] 文字コードの設定
[3] タイムゾーンの変更
[4] パスワード変更

[1] ネット環境

 * 右上の2本線のアイコンから、無線LANを探してインターネットに接続

[2] 文字コードの設定

 * 左上のラズパイアイコンから、[アクセサリ]-[LXTerminal]を選択し、
   以下の「コマンド例」を入力する
コマンド例
sudo apt-get update
sudo apt-get upgrade

sudo apt-get install -y jfbterm
sudo apt-get install -y ibus-anthy
sudo apt-get install -y fonts-ipaexfont

[3] タイムゾーンの変更

 * 左上のラズパイアイコンから、[設定]-[Raspberry Pi 設定]-[Localisation]を選択し、
   Set Timezoneを選択し、Area設定をJapanで選択


関連記事

Raspberry PI ~ 初期構築編 ~

https://blogs.yahoo.co.jp/dk521123/37155840.html

【Tomcat】Tomcat の readonlyパラメータについて

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37059239.html
で、Tomcat 脆弱性「CVE-2017-12617」(「CVE-2017-12615」「CVE-2017-12616」も同じ原因)に触れた。
その脆弱性と、それに関わるTomcat の readonlyパラメータについて、調べてみた

■ Tomcat 脆弱性「CVE-2017-12617」

http://jvn.jp/vu/JVNVU99259676/ (CVE-2017-12615, CVE-2017-12616, CVE-2017-12617)
http://jvn.jp/vu/JVNVU99259676/index.html (CVE-2017-12615, CVE-2017-12617)
上記に関するニュース
http://www.security-next.com/086349
http://internet.watch.impress.co.jp/docs/news/1082834.html
https://oss.sios.com/security/tomcat-security-vulnerabiltiy-20170920
http://gihyo.jp/admin/serial/01/infrasec/0038

影響範囲

 * readonlyパラメータが「false」に設定され、HTTP PUTメソッドが有効になっている場合

起こりうる影響

 * 特定の条件下で JSP ファイルをアップロードされる
 * 情報漏えい
 * 遠隔からの任意のコード実行

対応策

 * 最新版のTomcatをインストールする
できない場合は...
 * readonlyパラメータを「true」にし、HTTP PUTリクエストを受け付けないよう設定する
  => ただし、CVE-2017-12616(Apache Tomcat 7.0.0 ~ 7.0.80)については
     readonlyパラメータがtrueであっても発現する

■ readonlyパラメータ

 * 「読み込み専用」かどうかを設定。
  => PUT / DELETE といった HTTP コマンドを拒否するかどうかを示す
 * デフォルトは「true」
 * readonlyパラメータを true にすることで、ファイルのアップロードを可能にする

$CATALINA_HOME/conf/web.xml

<servlet><init-param><param-name>readonly</param-name><param-value>true</param-value></init-param>
   ... 略 ...


関連記事

Tomcat 脆弱性について

https://blogs.yahoo.co.jp/dk521123/37059239.html

【Raspberry PI】Raspberry PI ~ カメラを取り付ける ~

$
0
0

■ 動作環境

 * Raspberry PI : Raspberry PI 3 Model B
 * OS           : Raspbian 8 Jessie
 * カメラ       : Raspberry PI赤外線カメラモジュール (Raspberry Pi PiNoir Camera V2)

■ 設定手順

カメラを有効にする

[1] [メニュー(ラズパイアイコン)]-[設定]-[Raspberry Piの設定]-[インターフェイス]を選択し、
    「カメラ」欄の「有効」に選択する
[2] OS再起動する

# 「sudo raspi-config」からでもできる。

カメラ動作確認

[1] 以下のコマンドを実行する(「sample.jpg」で静止画が取れているか確認)

raspistill -o sample.jpg


関連記事

Raspberry PI ~ 初期構築編 ~

https://blogs.yahoo.co.jp/dk521123/37155840.html

Raspberry PI ~ OS環境設定編 ~

https://blogs.yahoo.co.jp/dk521123/37157434.html

【Windows】【Linux】外部サイトに繋がらなかった場合のトラブルシュート

$
0
0

■ 簡単にできるチェック

 * 繋がらない対象サイト以外のサイトでも同じ現象になるか?
  => 例えば、www.yahoo.co.jp が繋がらない場合、 www.google.co.jp や www.msn.com に繋がるか試す
  => 繋がれば、その対象サイトの問題に絞り込める

 * 別ブラウザでも同じ現象か?
  => もし、繋がるようなら、ブラウザの問題(もしくはブラウザの設定に起因する問題)に絞り込める。

 * 周りにいる他の人がPCを使っている場合、その人たちのPCから外部に繋がるか試してもらう
  => 周りがつながる場合、同じセグメントのネットワークかを確認。
     (同じ場合は自分のPCやLANケーブルの問題の可能性が高いので、その周辺を確かめる)

 * イントラネット環境(例えば、社内共有サーバなど)がある場合、そこに繋がるか試す
  => 繋がる場合は、外部サイトに出るデフォルトゲートウェイ(ルータ)~外部サイトに問題がある可能性が高い

■ 原因を探るためのコマンド

 * ping
 * tracert(Linuxではtraceroute)
 * route
 * nslookup

デフォルトゲートウェイのIP/Hostが分かっている場合

コマンド「ping」を利用する
ping [デフォルトゲートウェイのIP/Host]

 => これにより、ちゃんと到達できていれば、デフォルトゲートウェイ(ルータ)~外部サイトに問題がある可能性が高い

ネットワークの経路を調査して原因を絞り込む

コマンド「tracert(Linuxではtraceroute)」を利用する
 * どこでタイムアウトするかを確認

名前解決できているか確認する

コマンド「nslookup」を利用する
nslookup [対象URL]

 => 解決できなければ、DNSサーバの問題?
 => DNSキャッシュをクリアして、再度、試す(Windowsなら「ipconfig /flushdns」。「ipconfig /displaydns」で確認)

【Raspberry PI】Raspberry PI で、ssh 接続するには...

$
0
0

ssh接続を有効にする

 *  [メニュー(ラズパイアイコン)]-[設定]-[Raspberry Piの設定]-[インターフェイス]を選択し、
    「ssh」欄の「有効」に選択する

RSA鍵認証

 * セキュリティ強化のため、

コマンド

ssh-keygen -t rsa
# パスフレーズを入力する

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

sudo sed -t -e 's/#AuthorizedKeysFile/AuthorizedKeysFile/' /etc/ssh/sshd_config

sudo sed -t -e 's/#PasswordAuthentication_yes/PasswordAuthentication/no/' /etc/ssh/sshd_config

sudo systemctl restart ssh

【MySQL】MySQL Utilities ~ mysqldiff / mysqldbcompare etc... ~

$
0
0

■ MySQL Utilities とは?

 * Python言語により作成された便利なコマンドラインツール群

mysqlserverclone

 * 動作中のMySQLを元に別インスタンスを開始
* 注意点
 * クローン元からデータベースオブジェクト(表、ビュー、プロシジャ、トランザクション、等)は引き継がない
 * my.cnfは引き継がない

mysqldbcopy

 * サーバー間でのデータベースのコピー

mysqldiff

 * データベースオブジェクト定義の比較

mysqldbcompare

 * データベース比較

■ インストール

sudo yum install -y mysql-utilities

# 確認の意味を込めて...
mysqldbcopy --version
# MySQL Utilities mysqldbcopy version X.X.X ... とバージョン表示

■ MySQL Utilitiesの記法

--server=ユーザ名:パスワード@ホスト名:ポート番号

■ コマンド例

mysqldiff

# --force : 最後まで実行する
# --skip-table-options : テーブルのオプションに差分があっても無視する
mysqldiff  --server1=root:passowrd@127.0.0.1:3306 --server2=root:passowrd@127.0.0.1:3306 sampledb0.user:sampledb1.user --force --skip-table-options

mysqldbcompare

mysqldbcompare --server1=root:passowrd@127.0.0.1:3306 --server2=root:passowrd@127.0.0.1:3306 sampledb0:sampledb1

Viewing all 860 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>