なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

さらにcobraを使って簡易ブラウザを作ってしまうテスト

ほとんどのコードはCobra: Java HTML Parser & Viewer (Open Source)にあるBarebonesTest.javaからお借りしている。
できればもっと正確に表示できるものを作りたいところ。

package main;

import java.awt.*;
import javax.swing.*;

import java.awt.event.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.*;

import org.w3c.dom.Document;
import org.w3c.dom.html2.HTMLElement;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.lobobrowser.html.*;
import org.lobobrowser.html.gui.*;
import org.lobobrowser.html.parser.*;
import org.lobobrowser.html.test.*;

public class HttpClientFrame extends JFrame {

	// エラーがうるさいのでIDを自動生成
	private static final long serialVersionUID = 1L;

	// 上下のパネル設定
	JPanel abovePanel = new JPanel();
	JPanel underPanel = new JPanel();

	// ラベル、テキストエリア、ボタンの設定(上部)
	private JLabel label = new JLabel("URL:");
	private JTextField tf = new JTextField("", 30);
	private JButton b1 = new JButton("OK");

	// ラベル、テキストエリア、ボタンの最小サイズを求めておく
	Dimension sz1 = label.getMaximumSize();
	Dimension sz2 = tf.getMaximumSize();
	Dimension sz3 = b1.getMaximumSize();

	// テキストエリアの設定(下部)
	HtmlPanel htmlPanel = new HtmlPanel();

	HttpClientFrame() {

		// 要素の下準備
		sz2.width = Short.MAX_VALUE; // テキストエリアはどこまでも大きくなる
		sz2.height = sz3.height;
		tf.setMaximumSize(sz2);

		// 縦2パネル構成 (上:URL入力欄 ボタンなど 下:HTML文出力)
		setLayout(new BorderLayout());
		add("North", abovePanel);
		add("Center", underPanel);

		// 要素をパネルに配置(上部)
		abovePanel.setLayout(new BoxLayout(abovePanel, BoxLayout.LINE_AXIS));
		abovePanel.add(label);
		abovePanel.add(tf);
		b1.addActionListener(new inputURLListener());
		abovePanel.add(b1);

		// 要素をパネルに配置(下部)
		underPanel.setLayout(new GridLayout(1, 1));
		JScrollPane scrollpane = new JScrollPane(htmlPanel);
		underPanel.add(scrollpane);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("HttpClientGUI");
		setSize(640, 480);
		setVisible(true);
	}

	// アクションリスナークラス
	class inputURLListener implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// OKボタンが押されたときの処理
			if (tf.getText() != null) {
				String uri = tf.getText();
				URL url;
				try {
					// URLオブジェクトの生成
					url = new URL(uri);
					URLConnection connection = url.openConnection();

					// 接続したURLから読み取る
					InputStream in = connection.getInputStream();
					Reader reader = new InputStreamReader(in);
					InputSource is = new InputSourceImpl(reader, uri);

					UserAgentContext ucontext = new LocalUserAgentContext();
					HtmlRendererContext rendererContext = new LocalHtmlRendererContext(
							htmlPanel, ucontext);

					DocumentBuilderImpl builder = new DocumentBuilderImpl(
							rendererContext.getUserAgentContext(),
							rendererContext);

					Document document = builder.parse(is);
					in.close();

					htmlPanel.setDocument(document, rendererContext);

				} catch (MalformedURLException e1) {
					e1.printStackTrace();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				} catch (SAXException se) {
					se.printStackTrace();
				}
			}
		}

	}

	private static class LocalUserAgentContext extends SimpleUserAgentContext {
		// Override methods from SimpleUserAgentContext to
		// provide more accurate information about application.

		public LocalUserAgentContext() {
		}

		public String getAppMinorVersion() {
			return "0";
		}

		public String getAppName() {
			return "BarebonesTest";
		}

		public String getAppVersion() {
			return "1";
		}

		public String getUserAgent() {
			return "Mozilla/4.0 (compatible;) CobraTest/1.0";
		}
	}

	private static class LocalHtmlRendererContext extends
			SimpleHtmlRendererContext {
		// Override methods from SimpleHtmlRendererContext
		// to provide browser functionality to the renderer.

		public LocalHtmlRendererContext(HtmlPanel contextComponent,
				UserAgentContext ucontext) {
			super(contextComponent, ucontext);
		}

		public void linkClicked(HTMLElement linkNode, URL url, String target) {
			super.linkClicked(linkNode, url, target);
			// This may be removed:
			System.out.println("## Link clicked: " + linkNode);
		}

		public HtmlRendererContext open(URL url, String windowName,
				String windowFeatures, boolean replace) {
			// This is called on window.open().
			HtmlPanel newPanel = new HtmlPanel();
			JFrame frame = new JFrame();
			frame.setSize(600, 400);
			frame.getContentPane().add(newPanel);
			HtmlRendererContext newCtx = new LocalHtmlRendererContext(newPanel,
					this.getUserAgentContext());
			newCtx.navigate(url, "_this");
			return newCtx;
		}
	}

	public static void main(String args[]) {
		// Cobraに警告が出た場合の時のためにロガーを初期化
		Logger.getLogger("org.lobobrowser").setLevel(Level.WARNING);
		new HttpClientFrame();
	}

}


実行時の様子

・ブラウザの一番大事な機能であるレンダラとパーサーを一手に行ってくれているのでダウンロードしたHTML文をぶち込むだけで表示できている
・ただし意味不明な文字化けが多い