naobe @ ウィキ
Digester
最終更新:
Bot(ページ名リンク)
-
view
OpenSourceに戻る
Tomat6内臓のDigesterについて記述する。以下は、上記リンクの要約
初めに
DigesterはXMLに従ってJavaオブジェクトツリーを作成する。もともとstrutsのXML設定ファイルを処理するために作られたが、汎用的であるため、commonsプロジェクトに移管した。
使用するにあたって、要素のマッチングパターンが充足した時に起動する処理ルールによって操作されるスタックをDigesterは外部にさらす。
スタックに関連する操作は以下。意味は一般的なスタックと同じ。
使用するにあたって、要素のマッチングパターンが充足した時に起動する処理ルールによって操作されるスタックをDigesterは外部にさらす。
スタックに関連する操作は以下。意味は一般的なスタックと同じ。
- clear()
- peek()
- pop()
- push()
代表的なデザインパターンは、XMLの特別な要素が始まったときに、ルールがオブジェクトを作成しスタックにpushすること。要素が終了した時にスタックからpopする。
設定プロパティ
オブジェクトスタック
エレメントマッチングパターン
プロセスルール
ロギング
使用例
Tomcat6 server.xml
Tomcat6のorg.apache.catalina.startup.Catalina
server.xmlをパースしている。
server.xmlをパースしている。
public class Catalina extends Embedded { load() Digester digester = createStartDigester(); InputSource inputSource = null; InputStream inputStream = null; File file = null; try { file = configFile(); //server.xml inputStream = new FileInputStream(file); inputSource = new InputSource("file://" + file.getAbsolutePath()); catch (Exception e) { ; } try { inputSource.setByteStream(inputStream); digester.push(this); //自分をスタックにpush digester.parse(inputSource); //server.xmlをparse inputStream.close(); } catch (Exception e) { log.warn("Catalina.start using " + getConfigFile() + ": " , e); return; } // 親の親であるStandardServiceのメソッド public void setServer(Server server) { this.server = server; } createStartDigester() Digester digester = new Digester(); digester.setValidating(false); digester.setRulesValidation(true); HashMap<Class, List<String>> fakeAttributes = new HashMap<Class, List<String>>(); ArrayList<String> attrs = new ArrayList<String>(); attrs.add("className"); fakeAttributes.put(Object.class, attrs); digester.setFakeAttributes(fakeAttributes); digester.setClassLoader(StandardServer.class.getClassLoader()); // Configure the actions we will be using digester.addObjectCreate("Server", // server.xmlの<Server>要素を見つけたらorg.apache.catalina.core.StandardServerを作成し、スタックに積む "org.apache.catalina.core.StandardServer", "className"); digester.addSetProperties("Server"); digester.addSetNext("Server", //上から2番目のスタック(Catalinaオブジェクト)のsetServerメソッドを実行。引数の型はServer。引数の値はStandardServer。 "setServer", "org.apache.catalina.Server"); digester.addObjectCreate("Server/GlobalNamingResources", //server.xmlの<Server><GlobalNamingResources>の要素を見つけたらorg.apache.catalina.deploy.NamingResourcesを作成しスタックに積む。 "org.apache.catalina.deploy.NamingResources"); digester.addSetProperties("Server/GlobalNamingResources"); digester.addSetNext("Server/GlobalNamingResources", // 上から2番目のスタック(StandardServer)のsetGlobalNamingResourcesメソッドを実行 "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResources"); digester.addObjectCreate("Server/Listener", // server.xmlの<Server><Listener>要素を見つけたら、要素classNameのクラスを作成する。 null, // MUST be specified in the element "className"); digester.addSetProperties("Server/Listener"); digester.addSetNext("Server/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className"); digester.addSetProperties("Server/Service"); digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service"); digester.addObjectCreate("Server/Service/Listener", null, // MUST be specified in the element "className"); digester.addSetProperties("Server/Service/Listener"); digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //Executor digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className"); digester.addSetProperties("Server/Service/Executor"); digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor"); digester.addRule("Server/Service/Connector", new ConnectorCreateRule()); digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[]{"executor"})); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector"); digester.addObjectCreate("Server/Service/Connector/Listener", null, // MUST be specified in the element "className"); digester.addSetProperties("Server/Service/Connector/Listener"); digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); // Add RuleSets for nested elements digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); digester.addRuleSet(new EngineRuleSet("Server/Service/")); digester.addRuleSet(new HostRuleSet("Server/Service/Engine/")); digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/ ") ); digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); // When the 'engine' is found, set the parentClassLoader. digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(parentClassLoader)); digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/")); long t2=System.currentTimeMillis(); if (log.isDebugEnabled()) log.debug("Digester for server.xml created " + ( t2-t1 )); return (digester);
commons-digester3-3.2のexample
AddressBook.xml
<?xml version='1.0'?> <!-- Licensed to the [[Apache]] Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <address-book> <person id="1" category="acquaintance"> <name>Gonzo</name> <email type="business">gonzo@muppets.com</email> <address> <type>home</type> <street>123 Maine Ave.</street> <city>Las Vegas</city> <state>NV</state> <zip>01234</zip> <country>USA</country> </address> <address> <type>business</type> <street>234 Maple Dr.</street> <city>Los Angeles</city> <state>CA</state> <zip>98765</zip> <country>USA</country> </address> </person> <person id="2" category="rolemodel"> <name>Kermit</name> <email type="business">kermit@muppets.com</email> <email type="home">kermie@acme.com</email> <address> <type>business</type> <street>987 Brown Rd</street> <city>Las Cruces</city> <state>NM</state> <zip>75321</zip> <country>USA</country> </address> </person> </address-book>
AddressbookParser.java
package suna.digester.addressbook; import java.io.File; import java.io.IOException; import org.apache.commons.digester3.Digester; import org.xml.sax.SAXException; public class AddressbookParser { private static final String XML_FILE = "xml/AddressBook.xml"; public static void main(String[] args) { AddressbookParser parser = new AddressbookParser(); try { AddressBook addressBook = parser.parse(); dbg(addressBook.toString()); } catch (Exception e) { e.printStackTrace(); } } public AddressBook parse() throws IOException, SAXException { File file = new File(XML_FILE); Digester digester = new Digester(); digester.setValidating(false); digester.addObjectCreate("address-book", "suna.digester.addressbook.AddressBook"); digester.addObjectCreate("address-book/person", "suna.digester.addressbook.Person"); digester.addSetProperties("address-book/person"); digester.addSetNext("address-book/person", "addPerson"); digester.addBeanPropertySetter("address-book/person/name", "name"); digester.addObjectCreate("address-book/person/email", "suna.digester.addressbook.Mail"); digester.addSetProperties("address-book/person/email"); digester.addBeanPropertySetter("address-book/person/email", "name"); digester.addSetNext("address-book/person/email", "setMail"); digester.addObjectCreate("address-book/person/address", "suna.digester.addressbook.Address"); digester.addSetNext("address-book/person/address", "addAddress"); digester.addBeanPropertySetter("address-book/person/address/type", "type"); digester.addBeanPropertySetter("address-book/person/address/street", "street"); digester.addBeanPropertySetter("address-book/person/address/city", "city"); digester.addBeanPropertySetter("address-book/person/address/state", "state"); digester.addBeanPropertySetter("address-book/person/address/zip", "zip"); digester.addBeanPropertySetter("address-book/person/address/country", "country"); return digester.parse(file); } private static void dbg(String string) { System.out.println(string); } }
実行結果
[ ##Person## id:1,category:acquaintance,name:Gonzo, mail:[##Mail## type:business,name:gonzo@muppets.com], [##Address## type:home,zip:01234,country:USA,state:NV,city:Las Vegas,street:123 Maine Ave.] [##Address## type:business,zip:98765,country:USA,state:CA,city:Los Angeles,street:234 Maple Dr.] ] [ ##Person## id:2,category:rolemodel,name:Kermit, mail:[##Mail## type:home,name:kermie@acme.com], [##Address## type:business,zip:75321,country:USA,state:NM,city:Las Cruces,street:987 Brown Rd] ]
AddressBook.java
package suna.digester.addressbook; import java.util.ArrayList; import java.util.List; public class AddressBook { private List<Person> personList = new ArrayList<Person>(); public List<Person> getPersonList() { return personList; } public void addPerson(Person person) { personList.add(person); } @Override public String toString() { StringBuffer buf = new StringBuffer(); for(int i = 0; i < personList.size(); i++) { buf.append(personList.get(i).toString()); buf.append(" "); } return buf.toString(); } }
Person.java
package suna.digester.addressbook; import java.util.ArrayList; import java.util.List; public class Person { private String id; private String name; private String category; private Mail mail; private List<Address> addressList = new ArrayList<Address>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCategory() { return category; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setCategory(String category) { this.category = category; } public Mail getMail() { return mail; } public void setMail(Mail mail) { this.mail = mail; } public List<Address> getAddressList() { return addressList; } public void addAddress(Address address) { this.addressList.add(address); } @Override public String toString() { StringBuffer buf = new StringBuffer(); String mailString = ""; if(mail != null) { mailString = mail.toString(); } buf.append("[##Person## ").append("id:").append(id).append(",category:") .append(category).append(",name:").append(name).append(",mail:") .append(mailString).append(","); for(int i = 0; i < addressList.size();i++) { buf.append(addressList.get(i).toString()); } buf.append("]"); return buf.toString(); } }
Mail.java
package suna.digester.addressbook; public class Mail { private String type; private String name; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[##Mail## ").append("type:").append(type).append(",name:").append(name).append("]"); return buf.toString(); } }
Address.java
package suna.digester.addressbook; public class Address { private String type; private String street; private String city; private String state; private String zip; private String country; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[##Address## ").append("type:").append(type) .append(",zip:").append(zip).append(",country:").append(country).append(",state:") .append(state).append(",city:").append(city).append(",street:").append(street).append("]"); return buf.toString(); } }