Symfoware

Symfowareについての考察blog

JLHTTPでお手軽にpure javaなwebサーバーを起動する

軽量なPure Java HttpServerを探していると、ここを見つけました。
simple HTTP server in Java using only Java SE API


紹介されている中で、「JLHTTP」というのが目に止まったので調べてみます。



JLHTTP



JLHTTP - Java Lightweight HTTP Server (Web Server)

「JLHTTP 2.3」をダウンロードしました。
解凍したフォルダのlibに「jlhttp-2.3.jar」があります。
なんと53.9kb。

webサーバーとして起動するには以下のコマンドを実行。


$ java -jar jlhttp-2.3.jar <directory> [port]




実行したコマンドは以下の通り。


$ java -jar jlhttp-2.3.jar ./ 8080




これでwebサーバーが起動します。

826_01.png


これは軽量&便利。




アプリケーションから起動



Javaアプリケーションからの呼び出しは、ソースファイルやFAQが参考になります。
JLHTTP FAQ

webサーバーとして起動する最低限のソースはこちら。


  1. import java.io.File;
  2. import net.freeutils.httpserver.HTTPServer;
  3. import net.freeutils.httpserver.HTTPServer.VirtualHost;
  4. import net.freeutils.httpserver.HTTPServer.FileContextHandler;
  5. public class MainProcess {
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         HTTPServer server = new HTTPServer(8080);
  9.         
  10.         // デフォルトホスト
  11.         VirtualHost host = server.getVirtualHost(null);
  12.         
  13.         // ディレクトリの表示を許可
  14.         host.setAllowGeneratedIndex(true);
  15.         
  16.         // 「/」アクセスで、カレントディレクトリ表示
  17.         host.addContext("/", new FileContextHandler(new File("")));
  18.         
  19.         // サーバー起動
  20.         server.start();
  21.         
  22.         
  23.     }
  24. }






プログラムの実行



/helloにアクセスしたら、プログラムで文字列を出力してみます。


  1. import java.io.File;
  2. import java.io.IOException;
  3. import net.freeutils.httpserver.HTTPServer;
  4. import net.freeutils.httpserver.HTTPServer.VirtualHost;
  5. import net.freeutils.httpserver.HTTPServer.ContextHandler;
  6. import net.freeutils.httpserver.HTTPServer.FileContextHandler;
  7. import net.freeutils.httpserver.HTTPServer.Request;
  8. import net.freeutils.httpserver.HTTPServer.Response;
  9. public class MainProcess {
  10.     public static void main(String... args) throws Exception {
  11.         
  12.         HTTPServer server = new HTTPServer(8080);
  13.         
  14.         // デフォルトホスト
  15.         VirtualHost host = server.getVirtualHost(null);
  16.         
  17.         // ディレクトリの表示を許可
  18.         host.setAllowGeneratedIndex(true);
  19.         
  20.         // 「/」アクセスで、カレントディレクトリ表示
  21.         host.addContext("/", new FileContextHandler(new File("")));
  22.         
  23.         // 「/hello」アクセスで、プログラム実行
  24.         host.addContext("/hello", new ContextHandler() {
  25.             @Override
  26.             public int serve(Request req, Response resp) throws IOException {
  27.                 resp.getHeaders().add("Content-Type", "text/plain");
  28.                 resp.send(200, "Symfoware");
  29.                 return 0;
  30.             }
  31.         });
  32.         
  33.         // サーバー起動
  34.         server.start();
  35.         
  36.         
  37.     }
  38. }




「/」アクセスでディレクトリ表示。

826_02.png


「/hello」アクセスで文字列を表示。

826_03.png


これは、独自のアプリケーションサーバーが作れそうです。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/02/03(土) 18:55:06|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

winstoneでお手軽にpure javaなwebサーバーを起動する

RiotなどJavaScriptのプログラムを試して見るとき、手元で簡単に起動できる
webサーバーが欲しくなります。

例えばこういうサンプル。
Riot js 書籍ビューワー風なサンプルプログラム

今はPythonやPHPのデバッグサーバーを使用しています。

・Python


$ python3 -m http.server




・PHP


$ php -S localhost:8000




PythonやPHPはインストールされていないが、Javaはインストールされている環境で
同様のことが行えないか悩んでいる時、ふとwinstoneを思い出しました。

http://winstone.sourceforge.net/




winstone.jar



こちらを参考に、Maven リポジトリからjarファイルを取得します。
Winstone、最近、更新無い・・・


winstone-4.1.jarをダウンロードしました。
http://repo.jenkins-ci.org/public/org/jenkins-ci/winstone/

2.1MBと軽量です。



起動



とりあえずwinstone-4.1.jarを配置したディレクトリをそのまま公開するには、


$ java -jar winstone-4.1.jar --webroot=




--webroot=に値を設定せずに実行すると、カレントディレクトリがwebrootになります。

825_01.png


これは便利。



Javaプログラムから起動



コマンドではなくJavaプログラムから起動したい場合のサンプルです。


  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import winstone.Launcher;
  4. public class MainProcess {
  5.     public static void main(String... args) throws Exception {
  6.         Map<String, String> prop = new HashMap<String, String>();
  7.         prop.put("webroot", "");
  8.         prop.put("httpPort", "8080");
  9.         final Launcher winstone = new Launcher(prop);
  10.         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
  11.             public void run() {
  12.                 winstone.shutdown();
  13.             }
  14.         }));
  15.     }
  16. }



Launcherを使用することで、お手軽にwebサーバーが起動できます。



【参考URL】

http://winstone.sourceforge.net/
Winstone、最近、更新無い・・・
軽量サーブレットコンテナ winstone を開発用にサクッと使う
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/02/03(土) 17:44:09|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Java 同梱のScriptEngineを利用したJSON文字列のエンコード、デコード

Javaでライブラリを使わずに簡単なJSON文字列のエンコード、デコードが出来ないか。
ScriptEngineを使って実現可能か試してみます。

OpenJDK 1.8で動作を確認しています。



デコード



JSON文字列からJavaオブジェクトへの変換を試してみます。


  1. import java.util.Map;
  2. import javax.script.ScriptEngine;
  3. import javax.script.ScriptEngineManager;
  4. import jdk.nashorn.api.scripting.ScriptObjectMirror;
  5. public class MainProcess {
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         ScriptEngineManager manager = new ScriptEngineManager();
  9.         ScriptEngine engine = manager.getEngineByName("javascript");
  10.         
  11.         // デコードするjson文字列
  12.         String json = "{\"result\":true, \"count\":42, \"name\":\"Symfoware\", \"list\":[1,2,3], \"map\":{\"key\":\"value\"}}";
  13.         
  14.         // JSON.parseの実行結果を得る
  15.         Object result = engine.eval("JSON.parse('" + json + "')");
  16.         
  17.         if (!(result instanceof Map)) {
  18.             System.out.println("not map");
  19.             return;
  20.         }
  21.         
  22.         // mapに変換
  23.         Map<?, ?> m = (Map<?, ?>)result;
  24.         
  25.         // Boolean
  26.         System.out.println(m.get("result"));
  27.         if (m.get("result") instanceof Boolean) {
  28.             System.out.println("result is Boolean");
  29.         }
  30.         
  31.         // Integer
  32.         System.out.println("-----");
  33.         System.out.println(m.get("count"));
  34.         if (m.get("count") instanceof Integer) {
  35.             System.out.println("count is Integer");
  36.         }
  37.         
  38.         // String
  39.         System.out.println("-----");
  40.         System.out.println(m.get("name"));
  41.         if (m.get("name") instanceof String) {
  42.             System.out.println("name is String");
  43.         }
  44.         
  45.         // Array
  46.         System.out.println("-----");
  47.         ScriptObjectMirror mirror = (ScriptObjectMirror)m.get("list");
  48.         System.out.println(mirror.isArray());
  49.         Integer[] list = mirror.to(Integer[].class);
  50.         for(Integer v : list) {
  51.             System.out.println(v);
  52.         }
  53.         
  54.         
  55.         // Map
  56.         System.out.println("-----");
  57.         ScriptObjectMirror mirror2 = (ScriptObjectMirror)m.get("map");
  58.         System.out.println(mirror2.isArray());
  59.         Map<?, ?> map = (Map<?, ?>)m.get("map");
  60.         for(Map.Entry<?, ?> entry : map.entrySet()) {
  61.             System.out.println(entry.getKey());
  62.             System.out.println(entry.getValue());
  63.         }
  64.     }
  65.     
  66.     
  67. }




実行結果


true
result is Boolean
-----
42
count is Integer
-----
Symfoware
name is String
-----
true
1
2
3
-----
false
key
value




データ型も判定で来てるし、いい感です。
リストを変換する時がちょっと癖があって
ScriptObjectMirrorのtoを使用してやります。

ScriptObjectMirror mirror = (ScriptObjectMirror)m.get("list");
Integer[] list = mirror.to(Integer[].class);




callMember



https://codereview.stackexchange.com/questions/91184/java-json-stringifier-with-the-nashorn-api
JavaScriptの関数をcallMemberでJavaの世界に持ってこれるようです。

こちらのほうがすっきりしていますね。


  1. import java.util.Map;
  2. import javax.script.ScriptEngine;
  3. import javax.script.ScriptEngineManager;
  4. import jdk.nashorn.api.scripting.ScriptObjectMirror;
  5. public class MainProcess {
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         ScriptEngineManager manager = new ScriptEngineManager();
  9.         ScriptEngine engine = manager.getEngineByName("javascript");
  10.         
  11.         // デコードするjson文字列
  12.         String jsonString = "{\"result\":true, \"count\":42, \"name\":\"Symfoware\", \"list\":[1,2,3], \"map\":{\"key\":\"value\"}}";
  13.         
  14.         // JSON.parseの実行結果を得る
  15.         ScriptObjectMirror json = (ScriptObjectMirror) engine.eval("JSON");
  16.         Object result = json.callMember("parse", jsonString);
  17.         
  18.         if (!(result instanceof Map)) {
  19.             System.out.println("not map");
  20.             return;
  21.         }
  22.         
  23.         // mapに変換
  24.         Map<?, ?> m = (Map<?, ?>)result;
  25.         
  26.         // Boolean
  27.         System.out.println(m.get("result"));
  28.         if (m.get("result") instanceof Boolean) {
  29.             System.out.println("result is Boolean");
  30.         }
  31.         
  32.         // Integer
  33.         System.out.println("-----");
  34.         System.out.println(m.get("count"));
  35.         if (m.get("count") instanceof Integer) {
  36.             System.out.println("count is Integer");
  37.         }
  38.         
  39.         // String
  40.         System.out.println("-----");
  41.         System.out.println(m.get("name"));
  42.         if (m.get("name") instanceof String) {
  43.             System.out.println("name is String");
  44.         }
  45.         
  46.         // Array
  47.         System.out.println("-----");
  48.         ScriptObjectMirror mirror = (ScriptObjectMirror)m.get("list");
  49.         System.out.println(mirror.isArray());
  50.         Integer[] list = mirror.to(Integer[].class);
  51.         for(Integer v : list) {
  52.             System.out.println(v);
  53.         }
  54.         
  55.         
  56.         // Map
  57.         System.out.println("-----");
  58.         ScriptObjectMirror mirror2 = (ScriptObjectMirror)m.get("map");
  59.         System.out.println(mirror2.isArray());
  60.         Map<?, ?> map = (Map<?, ?>)m.get("map");
  61.         for(Map.Entry<?, ?> entry : map.entrySet()) {
  62.             System.out.println(entry.getKey());
  63.             System.out.println(entry.getValue());
  64.         }
  65.     }
  66.     
  67.     
  68. }







エンコード



JavaオブジェクトをJSONにデコードする方法がわからず苦労しました。
普通にJavaオブジェクトをJSON.stringifyに渡してもうまく行きません。

以下は変換に失敗するコードです。


  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import javax.script.ScriptEngine;
  4. import javax.script.ScriptEngineManager;
  5. import jdk.nashorn.api.scripting.ScriptObjectMirror;
  6. public class MainProcess {
  7.     public static void main(String... args) throws Exception {
  8.         
  9.         ScriptEngineManager manager = new ScriptEngineManager();
  10.         ScriptEngine engine = manager.getEngineByName("javascript");
  11.         
  12.         // エンコードするJavaオブジェクト
  13.         Map<Object, Object> m = new HashMap<>();
  14.         m.put("result", true);
  15.         m.put("count", 42);
  16.         m.put("name", "Symfoware");
  17.         m.put("list", new int[]{1, 2, 3});
  18.         
  19.         Map<String, String> map = new HashMap<>();
  20.         map.put("key", "value");
  21.         m.put("map", map);
  22.         
  23.         ScriptObjectMirror json = (ScriptObjectMirror) engine.eval("JSON");
  24.         Object result = json.callMember("stringify", m);
  25.         System.out.println(result);
  26.     }
  27.     
  28. }




実行結果


undefined




JSON.stringifyの引数に指定するのは、javascriptエンジンが解釈可能なオブジェクト
「ScriptObjectMirror」でなくてはいけません。

試行錯誤しながら、こんなコードで変換できました。


  1. import javax.script.ScriptEngine;
  2. import javax.script.ScriptEngineManager;
  3. import jdk.nashorn.api.scripting.ScriptObjectMirror;
  4. public class MainProcess {
  5.     public static void main(String... args) throws Exception {
  6.         
  7.         ScriptEngineManager manager = new ScriptEngineManager();
  8.         ScriptEngine engine = manager.getEngineByName("javascript");
  9.         
  10.         // json文字列に変換する辞書
  11.         ScriptObjectMirror m = (ScriptObjectMirror)engine.eval("new Object()");
  12.         
  13.         m.put("result", true);
  14.         m.put("count", 42);
  15.         m.put("name", "Symfoware");
  16.         
  17.         ScriptObjectMirror list = (ScriptObjectMirror)engine.eval("new Array()");
  18.         list.callMember("push", 1);
  19.         list.callMember("push", 2);
  20.         list.callMember("push", 3);
  21.         m.put("list", list);
  22.         
  23.         ScriptObjectMirror map = (ScriptObjectMirror)engine.eval("new Object()");
  24.         map.put("key", "value");
  25.         m.put("map", map);
  26.         
  27.         
  28.         ScriptObjectMirror json = (ScriptObjectMirror) engine.eval("JSON");
  29.         Object result = json.callMember("stringify", m);
  30.         System.out.println(result);
  31.         
  32.     }
  33.     
  34. }




実行結果


{"result":true,"count":42,"name":"Symfoware","list":[1,2,3],"map":{"key":"value"}}



いい感じです。



【参考URL】

Java スクリプトプログラマーズガイド
Java の上の JavaScript エンジン Nashorn の基本
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON
https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/02/01(木) 23:42:52|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Riot js 書籍ビューワー風なサンプルプログラム

キーボードの左右キーで画像を切り替えるRiotサンプル
Riot キーボードの矢印キーで画像を切り替える

PDFファイルをjpgファイルに変換
PDFBox 2でpdfファイルをページごとにjpgファイルへ変換する

これを組み合わせ、pdfから変換したjpgファイルを見開きで表示するサンプルを作ってみます。


サンプル



Riot キーボードの矢印キーで画像を切り替える
こことほとんど同様の内容です。

imageフォルダにlist.jsonを作成。
画像のリストを記載しておきます。

・image/list.json


  1. [
  2.     {"url1":"image/001.jpg", "url2":"image/002.jpg"},
  3.     {"url1":"image/003.jpg", "url2":"image/004.jpg"},
  4.     {"url1":"image/005.jpg", "url2":"image/006.jpg"},
  5.     {"url1":"image/007.jpg", "url2":"image/008.jpg"},
  6.     {"url1":"image/009.jpg", "url2":"image/010.jpg"},
  7.     {"url1":"image/011.jpg", "url2":"image/012.jpg"},
  8.     {"url1":"image/013.jpg", "url2":"image/014.jpg"},
  9.     {"url1":"image/015.jpg", "url2":"image/016.jpg"},
  10.     {"url1":"image/017.jpg", "url2":"image/018.jpg"},
  11.     {"url1":"image/019.jpg", "url2":"image/020.jpg"},
  12.     {"url1":"image/021.jpg", "url2":"image/022.jpg"},
  13.     {"url1":"image/023.jpg", "url2":"image/024.jpg"},
  14.     {"url1":"image/025.jpg", "url2":"image/026.jpg"},
  15.     {"url1":"image/027.jpg", "url2":"image/028.jpg"},
  16.     {"url1":"image/029.jpg", "url2":"image/030.jpg"},
  17.     {"url1":"image/031.jpg", "url2":"image/032.jpg"},
  18.     {"url1":"image/033.jpg", "url2":"image/034.jpg"}
  19. ]




表示するriotなプログラムはこうなりました。


  1. <!doctype html>
  2. <html lang="ja">
  3. <html>
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <title>Riotサンプル</title>
  7.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. </head>
  9. <body>
  10.     <my-tag></my-tag>
  11. </body>
  12. <script type="riot/tag">
  13. <my-tag>
  14.     <h3>画像表示サンプル { info }</h3>
  15.     <div style="float:left;width:50%">
  16.         <img src="{ url1 }" style="width:100%;height:100%">
  17.     </div>
  18.     <div style="float:left;width:50%">
  19.         <img src="{ url2 }" style="width:100%;height:100%">
  20.     </div>
  21.     <br clear="both"/>
  22. var self = this
  23. self.imagelist = []
  24. self.url1 = ''
  25. self.url2 = ''
  26. self.info = ''
  27. self.index = 0
  28. updateView(operation) {
  29.     self.url1 = self.imagelist[self.index].url1
  30.     self.url2 = self.imagelist[self.index].url2
  31.     self.info = `( ${self.index + 1} / ${self.imagelist.length} ):${operation}`
  32.     self.update()
  33. }
  34. getList() {
  35.     // 画像のURLリストを取得
  36.     const url = 'image/list.json'
  37.     fetch(url)
  38.     .then(function(response) {
  39.         return response.json()
  40.     }).then(function(json){
  41.         self.imagelist = json
  42.         self.updateView('getList')
  43.     })
  44. }
  45. keydown(event) {
  46.     var operation = ''
  47.     switch (event.keyCode) {
  48.         case 37: // left 1つ前の画像
  49.             operation = 'left'
  50.             self.index--
  51.             break
  52.         case 39: // right 次の画像
  53.             operation = 'right'
  54.             self.index++
  55.             break
  56.         default:
  57.             return
  58.     }
  59.     // 範囲チェック
  60.     if (self.index < 0) {
  61.         self.index = 0
  62.         return
  63.     }
  64.     if (self.imagelist.length - 1 < self.index) {
  65.         self.index = self.imagelist.length - 1
  66.         return
  67.     }
  68.     self.updateView(operation)
  69. }
  70. document.onkeydown = this.keydown;
  71. this.getList()
  72. </my-tag>
  73. </script>
  74. <!-- マウント -->
  75. <script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js"></script>
  76. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.8.1/riot+compiler.min.js"></script>
  77. <script>
  78. riot.mount('my-tag')
  79. </script>
  80.     
  81. </html>




2つの画像を左右に並べて表示しています。
動作している様子はこんな感じです。

824_01.gif

※このgifはpeekを使用して作成しました。
Ubuntu 画面をキャプチャしてgifアニメを作成する(Peek)
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/01/31(水) 23:09:23|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

PDFBox 2でpdfファイルをページごとにjpgファイルへ変換する

Apache PDFBox
PDFファイルを操作するライブラです。
PDFファイルの内容をページごとにjpgファイルへ変換してみます。


ライブラリの入手



ダウンロードページ
https://pdfbox.apache.org/download.cgi

「pdfbox-2.0.8.jar」
「fontbox-2.0.8.jar」
「pdfbox-tools-2.0.8.jar」

をダウンロードしてビルドパスに含めました。

823_01.png


「fontbox-2.0.8.jar」
変換するpdfがすべて画像で構成されていれば必要ないのですが、
フォントが埋め込まれているページの変換を行う場合は必要です。
こんなエラーが発生し、変換に失敗します。


Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/fontbox/cff/CFFParser$ByteSource
    at org.apache.pdfbox.pdmodel.font.PDFontFactory.createFont(PDFontFactory.java:60)
    at org.apache.pdfbox.pdmodel.PDResources.getFont(PDResources.java:143)




Apache Commons Loggingに依存していますので、
http://commons.apache.org/proper/commons-logging/download_logging.cgi
こちらから「commons-logging-1.2-bin.zip」をダウンロード。
解凍してcommons-logging-1.2.jarもビルドパスに含めておきます。





サンプルのPDF



変換に使用するPDFファイルはこちらを使用させていただきました。
ftp://ftp.oreilly.co.jp/9784873113647/PCI_sample.pdf

「集合知プログラミング」のサンプルページです。



プログラム



jpgへ変換するプログラムはこちらを参考にしました。
Apache PDFBoxでPDFページを画像にする(ラスタライズ)
https://pdfbox.apache.org/2.0/migration.html#pdf-rendering


  1. import java.awt.image.BufferedImage;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import org.apache.pdfbox.pdmodel.PDDocument;
  7. import org.apache.pdfbox.rendering.ImageType;
  8. import org.apache.pdfbox.rendering.PDFRenderer;
  9. import org.apache.pdfbox.tools.imageio.ImageIOUtil;
  10. public class MainProcess {
  11.     public static void main(String... args) {
  12.         
  13.         File file = new File("PCI_sample.pdf");
  14.         
  15.         try (InputStream in = new FileInputStream(file);
  16.                 PDDocument doc = PDDocument.load(in)) {
  17.             
  18.             
  19.             PDFRenderer pdfRenderer = new PDFRenderer(doc);
  20.             for (int i = 0; i < doc.getNumberOfPages(); i++) {
  21.                 BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);
  22.                 ImageIOUtil.writeImage(image, String.format("%03d.jpg", i + 1), 300);
  23.             }
  24.             
  25.             
  26.         } catch (IOException e) {
  27.             e.printStackTrace();
  28.         }
  29.                 
  30.         
  31.     }
  32.     
  33.     
  34. }




変換した画像と元のPDFとの比較です。
左がjpg、右がpdfです。

823_02.png

823_03.png


jpg側、縮小しているため字が潰れて見えますが、拡大すると綺麗に変換されていることが
確認できます。

823_04.png




【参考URL】

Apache PDFBoxでPDFページを画像にする(ラスタライズ)
https://pdfbox.apache.org/2.0/migration.html#pdf-rendering

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2018/01/31(水) 22:33:33|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
前のページ 次のページ