デフォルトのcatalina.policyを使うとexamplesでcatalina.logにwarningが出る
2011/01/21 10:50:26 org.apache.catalina.startup.HostConfig deployDirectory INFO: Webアプリケーションディレクトリ examples を配備します 2011/01/21 10:50:26 org.apache.catalina.loader.WebappClassLoader findClass WARNING: WebappClassLoader.findClassInternal(chat.ChatServlet) security exception: access denied (java.lang.RuntimePermission accessClassInPackage.org.apache.catalina) java.security.AccessControlException: access denied (java.lang.RuntimePermission accessClassInPackage.org.apache.catalina)
logが汚れて邪魔なので、examplesにpermissionを付与する。
// ========== EXAMPLE CODE PERMISSIONS ======================================= // These permissions apply to example grant codeBase "file:${catalina.home}/webapps/examples/WEB-INF/classes/-" { permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina"; // permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager"; // permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager.util"; };
Tomcatで動かすWebアプリをプラグインで機能拡張可能にするためにやったこと
ここら辺を参考に。
- プラグインで拡張できるJavaプログラムを作る (1/3):CodeZine(コードジン)
- http://osima.jp/blog/howto-make-plugin-system-improved.html
プラグインのインターフェースを決める
とりあえず適当に決める。
priority付けてるのはプラグインが複数あったときに実行順を決めたかっただけ。
package com.example; public interface FooPlugin { public int getPriority(); public Bar execute(Bar bar); }
プラグイン読み込み管理クラスをつくる
最初URLClassLoaderで試してたんだけど、うまくいかないので、RMIClassLoaderに変更。
package com.example; import java.io.File; import java.io.IOException; import java.rmi.RMISecurityManager; import java.rmi.server.RMIClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.logging.Logger; public class FooPluginManager { private static final Logger logger = Logger.getLogger(FooPluginManager.class.getName()); private ArrayList<FooPlugin> plugins = new ArrayList<FooPlugin>(); public FooPluginManager(String pluginPath) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { logger.info(pluginPath); if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } File dir = new File(pluginPath); String[] files = dir.list(); for (int i = 0; i < files.length; i++) { if (files[i].toLowerCase().endsWith(".jar")) { File jarFile = new File(pluginPath + File.separator + files[i]); JarFile jar = new JarFile(jarFile); Manifest manifest = jar.getManifest(); Attributes attribs = manifest.getMainAttributes(); String className = attribs.getValue("Plugin-Class"); if (className != null) { className = className.trim(); Class<?> clazz = RMIClassLoader.loadClass(jarFile.toURL(), className); logger.info("load... " + className); Object obj = clazz.newInstance(); plugins.add((FooPlugin) obj); } } } } public ArrayList<FooPlugin> sort() { Collections.sort(plugins, new Comparator<FooPlugin>() { public int compare(FooPlugin a, FooPlugin b) { if (a.getPriority() < b.getPriority()) return -1; if (a.getPriority() > b.getPriority()) return 1; return a.getClass().getCanonicalName().compareTo(b.getClass().getCanonicalName()); } }); for (Iterator<FooPlugin> iter = plugins.iterator(); iter.hasNext();) { logger.info("sort... " + iter.next().getClass().getCanonicalName()); } return plugins; } }
プラグインを書く
2個くらい書いてみる。
package com.example; import com.example.Bar; import com.example.FooPlugin; public class FooPluginImpl1 implements FooPlugin { private static final int priority = 2; public int getPriority() { return priority; } public Bar execute(Bar bar) { return bar; } }
package com.example; import com.example.Bar; import com.example.FooPlugin; public class FooPluginImpl2 implements FooPlugin { private static final int priority = 1; public int getPriority() { return priority; } public Bar execute(Bar bar) { return bar; } }
マニフェストを書いてjarファイルをつくる
EclipseのExport機能を使ってjarファイルをつくる。(任意のマニフェストを指定できる。)
p1.mf
Manifest-Version: 1.0 Plugin-Class: com.example.FooPluginImpl1
メインプログラム
とりあえず読み込んでソートだけしてみる。
FooPluginManager pm = new FooPluginManager("C:\\jakarta-tomcat-6.0\\webapps\\foo\\WEB-INF\\plugins"); ArrayList<FooPlugin> plugins = pm.sort();
jakarta-tomcat-6.0/conf/catalina.policyの変更
とりあえずゆるゆるで。
// ========== FOO CODE PERMISSIONS ======================================= // These permissions apply to foo grant codeBase "file:${catalina.home}/webapps/foo/WEB-INF/classes/-" { permission java.security.AllPermission; }; // These permissions apply to plugin grant codeBase "file:${catalina.home}/webapps/foo/WEB-INF/plugins/-" { permission java.security.AllPermission; };
Tomcat起動引数を追加
デフォルトだとcatalina.policyは使われず、JREのlib/security/java.policyが使われる。-securityオプションを付けるとcatalina.policyを使うようになるとTomcatのドキュメントにあったんだけど、実際に試すとそんなコマンドはないとか言われて困り果てたところ、RE: Simple Security Manager how to ? というのを見つけた。
Configure -> [Java] タブ -> Java Options
-Djava.security.manager -Djava.security.policy=C:\jakarta-tomcat-6.0\conf\catalina.policy
おわり
ログで動作確認。
2011/01/19 10:54:17 com.example.FooPluginManager <init> INFO: C:\jakarta-tomcat-6.0\webapps\foo\WEB-INF\plugins 2011/01/19 10:54:17 com.example.FooPluginManager <init> INFO: load... com.example.FooPluginImpl1 2011/01/19 10:54:17 com.example.FooPluginManager <init> INFO: load... com.example.FooPluginImpl2 2011/01/19 10:54:17 com.example.FooPluginManager sort INFO: sort... com.example.FooPluginImpl2 2011/01/19 10:54:17 com.example.FooPluginManager sort INFO: sort... com.example.FooPluginImpl1
放置していたtumblrを再動させつつあるので、やっつけbookmarklet書いた。
選択範囲からそれっぽい引用HTMLを生成
javascript:(function(d,t,s,r,f){t.appendChild(d.createTextNode(['<blockquote%20title="'+document.title+'"%20cite="'+location.href+'"><dl>','<dt>'+f(s.shift())+'</dt>',(s.length>0?'<dd><pre>'+s.map(function(v){v=f(v);v=v.replace(r,'<a%20href="$1;">$1;</a>');return%20v}).join('\n')+'</pre></dd>\n':'')+'</dl></blockquote>'].join('\n')));with(t.style){position='fixed';bottom=left=0;zIndex=999;width='90%';height='9em'}d.body.appendChild(t);t.addEventListener('blur',function(){this.parentNode.removeChild(this)},false);t.select()})(document,document.createElement('textarea'),getSelection().toString().split(/\n/).filter(function(v)v),/(https?:\/\/[\-_.!~*\'()\w;\/?:\@&=+\$,%#]+)/g,function(s)s.replace(/^\s+|\s+$/,''))
僕の Ado
ado.wsc
こういうのを書いて ado.wsc で保存して、右クリックで COM 登録して使ってる。
GUID は GUIDの生成 - Ci.nsIZIGOROu - Mozilla 拡張機能勉強会 でやると便利ですよ。
saveFile メソッドは utf-8n 用。 ADODB.Streamオブジェクトを使ってBOMなしUTF-8のファイルを作成する方法 - 大人になったら肺呼吸
ENTITY使ってますか
全国のXMLerの皆さん、ENTITY使ってますか。DTDをそらで書ける皆さんなら当然使ってますよね。たとえば、Androidの設定ファイルなんかでも、
main.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE LinearLayout [ <!ENTITY padding '10dp'> <!ENTITY view.text ' <TextView android:text="copy" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="&padding;" /> '> ]> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ListView android:id="@+id/list_view_select" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="&padding;" /> <Spinner android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="&padding;" /> <RatingBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="&padding;" /> <EditText android:hint="コメント" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="&padding;" /> &view.text; &view.text; &view.text; &view.text; </LinearLayout>
paddingの共通値に使ってみたり、Viewを複製してみたり、
strings.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE resources [ <!ENTITY serv 'http://localhost/'> ]> <resources> <string name="app_name">Layout</string> <string name="url_hoge">&serv;hoge</string> <string name="url_piyo">&serv;piyo</string> <string name="url_fuga">&serv;fuga</string> <string name="text_view_camera">カメラ</string> <string name="text_view_camera_role">カメラロール</string> </resources>
文字列の共通部分とかにも! 簡単でしょ?
Linuxでtitanium起動
rm ~/.titanium/runtime/linux/1.0.0/libgobject-2.0.* rm ~/.titanium/runtime/linux/1.0.0/libglib-2.0.* rm ~/.titanium/runtime/linux/1.0.0/libgio-2.0.* rm ~/.titanium/runtime/linux/1.0.0/libgthread-2.0.*http://developer.appcelerator.com/question/14471/symbol-lookup-error-usrliblibgdk-x11-20so0-undefined-symbol-gmallocn-solved
つうか、消していいんですかね……