top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
うそSOAPを ほんのりと抽象化しました。 , これにより SAX2ベースによるSOAP電文のキャプチャおよび再生が可能になります。
うそSOAPから ほんのりと抽象的な部分を抽出しました。
BlancoReverseContentHandler.java
/*
* blancoCommons Copyright (C) 2005 Tosiki Iga
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*/
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
* SAXイベントを入力に あべこべにそれを出力するソースコードを生成します。 <br>
* とっても不思議なSAX2コンテントハンドラです。 <br>
* 2005.08.11 Tosiki Iga 新規作成
*
* @author Tosiki Iga
*/
public class BlancoReverseContentHandler extends BufferedWriter implements
ContentHandler {
/**
* リバースコンテントハンドラのインスタンスを生成します。
*
* @param writer
* リバース結果のソースコードの出力先
*/
public BlancoReverseContentHandler(Writer writer) {
super(writer);
}
public void setDocumentLocator(Locator arg0) {
// ドキュメントロケータは無視します。
}
public void startDocument() throws SAXException {
try {
write("TransformerFactory tf = TransformerFactory.newInstance();");
newLine();
write("SAXTransformerFactory saxTf = (SAXTransformerFactory) tf;");
newLine();
write("TransformerHandler handler = saxTf.newTransformerHandler();");
newLine();
write("handler.setResult(new StreamResult(response.getOutputStream()));");
newLine();
write("handler.startDocument();");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void endDocument() throws SAXException {
try {
write("handler.endDocument();");
newLine();
flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void startPrefixMapping(String arg0, String arg1)
throws SAXException {
try {
write("handler.startPrefixMapping(\"" + arg0 + "\", \"" + arg1
+ "\");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void endPrefixMapping(String arg0) throws SAXException {
try {
write("handler.endPrefixMapping(\"" + arg0 + "\");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 最初のエレメントかどうかを判断します。
*/
private boolean isFirstAttributes = true;
public void startElement(String uri, String localname, String qname,
Attributes attributes) throws SAXException {
try {
if (isFirstAttributes) {
isFirstAttributes = false;
write("AttributesImpl attributes = new AttributesImpl();");
newLine();
} else {
write("attributes = new AttributesImpl();");
newLine();
}
for (int index = 0; index < attributes.getLength(); index++) {
write("attributes.addAttribute(\"" + attributes.getURI(index)
+ "\", \"" + attributes.getLocalName(index) + "\", \""
+ attributes.getQName(index) + "\", \""
+ attributes.getType(index) + "\", \""
+ attributes.getValue(index) + "\");");
newLine();
}
write("handler.startElement(\"" + uri + "\", \"" + localname
+ "\", \"" + qname + "\", attributes);");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void endElement(String arg0, String arg1, String arg2)
throws SAXException {
try {
write("handler.endElement(\"" + arg0 + "\", \"" + arg1 + "\", \""
+ arg2 + "\");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
try {
// 第二引数に0をセットしている点に注意!
write("handler.characters(\"" + new String(arg0, arg1, arg2)
+ "\".toCharArray(), 0, " + arg2 + ");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
throws SAXException {
try {
write("handler.ignorableWhitespace(\""
+ new String(arg0, arg1, arg2) + "\".toCharArray(), 0, "
+ arg2 + ");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void processingInstruction(String arg0, String arg1)
throws SAXException {
try {
write("handler.processingInstruction(\"" + arg0 + "\", \"" + arg1
+ "\");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public void skippedEntity(String arg0) throws SAXException {
try {
write("handler.skippedEntity(\"" + arg0 + "\");");
newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
public static final Transformer getTransformer()
throws TransformerFactoryConfigurationError,
TransformerConfigurationException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty("encoding", "UTF-8");
transformer.setOutputProperty("standalone", "yes");
transformer.setOutputProperty("indent", "yes");
return transformer;
}
}
※このファイルの継続的な維持については blancoCommonsの中において行われていくことでしょう。※さしあたり、例外をSAXExceptionに詰め替えが必要でしょう。その上で うそSOAPでは Faultを適切に扱うべきです。 この場合のキャプチャをおこなうべく まず うそSOAPサーバを起動してキャプチャします。
なお、このサーブレットは非常に良くないことに、「ルート」にキャプチャ結果のファイルを保存します。実行時には よく考えてから実行するようにしてください。Tomcatであれば、startup.batを起動する際のカレントディレクトリが「ルート」となります… ※さすがに改善すべき点でしょうが、時間がないので省略します。
また、このサーブレットを Webサービスだと仮定して呼び出しを行うと、当然のごとく 初回はクライアント側においてエラーが発生します。
加えて、SOAP の Faultに対応していない点も重要です。Envelope -> Body -> Fault のところにエラーコードを適切に返す必要があります。
UsoapServlet.java
``` /*
import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.Enumeration;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult;
import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl;
/** * うそSOAPサーブレット ソースコード * * @author iga * @version 2005.08.11 */ public class UsoapServlet extends HttpServlet {
/**
* <code>ENCODING</code> HTMLで扱う文字コードを与えます。
*/
public static final String ENCODING = "UTF-8";
/**
* Java Servletのエントリポイントです。
*
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public final void service(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
setResponseDefault(response);
try {
try {
recvRequest(request);
} catch (TransformerException e1) {
e1.printStackTrace();
} catch (TransformerFactoryConfigurationError e1) {
e1.printStackTrace();
}
try {
sendResponse(response);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
} finally {
// ReaderもWriterもクローズしません。flushも呼び出してはなりません。(2005.03.13に判明)
}
}
/**
* リクエストをファイルに出力します。
*
* @param request
* @throws IOException
* @throws FileNotFoundException
* @throws TransformerException
* @throws TransformerFactoryConfigurationError
* @throws TransformerConfigurationException
*/
private void recvRequest(final HttpServletRequest request)
throws IOException, FileNotFoundException, TransformerException,
TransformerFactoryConfigurationError,
TransformerConfigurationException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("UsoapServletRequest.txt", true)));
writer.write("HttpClient client = new HttpClient();");
writer.newLine();
writer
.write("client.getHostConfiguration().setHost(\"localhost\", 8080, \"http\");");
writer.newLine();
writer
.write("PostMethod method = new PostMethod(\"/axis/WsTest02.jws\");");
writer.newLine();
for (Enumeration enum = request.getHeaderNames(); enum
.hasMoreElements();) {
String key = (String) enum.nextElement();
writer.write("method.addRequestHeader(\"" + key + "\", \""
+ request.getHeader(key) + "\");");
writer.newLine();
}
writer.newLine();
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(request.getInputStream()));
SAXResult result = new SAXResult();
result.setHandler(new BlancoReverseContentHandler(writer));
BlancoReverseContentHandler.getTransformer().transform(source, result);
writer.newLine();
writer.flush();
writer.close();
}
/**
* レスポンスを送信します。 <br>
* ※注意: ここには うそSOAPのキャプチャ結果ソースコードをそのまま貼り付けます。
*
* @param response
* @throws TransformerFactoryConfigurationError
* @throws TransformerConfigurationException
* @throws IOException
* @throws SAXException
*/
private void sendResponse(final HttpServletResponse response)
throws TransformerFactoryConfigurationError,
TransformerConfigurationException, IOException, SAXException {
// ここからはリバースSAXの出力結果。人手で書いたものではありません。
TransformerFactory tf = TransformerFactory.newInstance();
SAXTransformerFactory saxTf = (SAXTransformerFactory) tf;
TransformerHandler handler = saxTf.newTransformerHandler();
handler.setResult(new StreamResult(response.getOutputStream()));
handler.startDocument();
handler.startPrefixMapping("soapenv",
"http://schemas.xmlsoap.org/soap/envelope/");
handler.startPrefixMapping("xsd", "http://www.w3.org/2001/XMLSchema");
handler.startPrefixMapping("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenv",
"xmlns:soapenv", "CDATA",
"http://schemas.xmlsoap.org/soap/envelope/");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "xsd",
"xmlns:xsd", "CDATA", "http://www.w3.org/2001/XMLSchema");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "xsi",
"xmlns:xsi", "CDATA",
"http://www.w3.org/2001/XMLSchema-instance");
handler.startElement("http://schemas.xmlsoap.org/soap/envelope/",
"Envelope", "soapenv:Envelope", attributes);
attributes = new AttributesImpl();
handler.startElement("http://schemas.xmlsoap.org/soap/envelope/",
"Body", "soapenv:Body", attributes);
handler.startPrefixMapping("ns1", "http://MyNamespace");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns1",
"xmlns:ns1", "CDATA", "http://MyNamespace");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
handler.startElement("http://MyNamespace", "method02Response",
"ns1:method02Response", attributes);
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"arrayType", "soapenc:arrayType", "CDATA", "xsd:anyType[2]");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "soapenc:Array");
handler
.startElement("", "method02Return", "method02Return",
attributes);
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id0");
handler
.startElement("", "method02Return", "method02Return",
attributes);
handler.endElement("", "method02Return", "method02Return");
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id1");
handler
.startElement("", "method02Return", "method02Return",
attributes);
handler.endElement("", "method02Return", "method02Return");
handler.endElement("", "method02Return", "method02Return");
handler.endPrefixMapping("soapenc");
handler.endElement("http://MyNamespace", "method02Response",
"ns1:method02Response");
handler.endPrefixMapping("ns1");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
handler.startPrefixMapping("ns2", "http://MyNamespace");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns2",
"xmlns:ns2", "CDATA", "http://MyNamespace");
attributes.addAttribute("", "id", "id", "CDATA", "id0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "ns2:WsTestOutput");
handler.startElement("", "multiRef", "multiRef", attributes);
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:int");
handler.startElement("", "arg3", "arg3", attributes);
handler.characters("0".toCharArray(), 0, 1);
handler.endElement("", "arg3", "arg3");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:string");
handler.startElement("", "arg4", "arg4", attributes);
handler.characters("は".toCharArray(), 0, 1);
handler.characters("ろ".toCharArray(), 0, 1);
handler.characters("う".toCharArray(), 0, 1);
handler.endElement("", "arg4", "arg4");
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("ns2");
handler.endPrefixMapping("soapenc");
handler.startPrefixMapping("ns3", "http://MyNamespace");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns3",
"xmlns:ns3", "CDATA", "http://MyNamespace");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("", "id", "id", "CDATA", "id1");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "ns3:WsTestOutput");
handler.startElement("", "multiRef", "multiRef", attributes);
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:int");
handler.startElement("", "arg3", "arg3", attributes);
handler.characters("0".toCharArray(), 0, 1);
handler.endElement("", "arg3", "arg3");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:string");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"nil", "xsi:nil", "CDATA", "true");
handler.startElement("", "arg4", "arg4", attributes);
handler.endElement("", "arg4", "arg4");
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("soapenc");
handler.endPrefixMapping("ns3");
handler.endElement("http://schemas.xmlsoap.org/soap/envelope/", "Body",
"soapenv:Body");
handler.endElement("http://schemas.xmlsoap.org/soap/envelope/",
"Envelope", "soapenv:Envelope");
handler.endPrefixMapping("xsi");
handler.endPrefixMapping("xsd");
handler.endPrefixMapping("soapenv");
handler.endDocument();
}
/**
* デフォルトとなるレスポンスヘッダーの付与
*
* @param response
* レスポンスオブジェクトを与えます。
*/
private void setResponseDefault(final HttpServletResponse response) {
response.setContentType("text/xml; charset=" + ENCODING);
response.addHeader("Content-Type", "text/xml");
response.addHeader("charset", ENCODING);
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
}
} ```
※このサーブレットは 「ルート」に作業ファイルを作成してしまいます。実行の前に それが許される環境であるかどうかについて、よく考えてください。 サーバ側でキャプチャできれば、今度はクライアント側にキャプチャ結果を貼り付けて、サーバ側の挙動をキャプチャすることが出来ます。
ここからはクライアント側のコードです。
HttpCaller.java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
public class HttpCaller {
private static final int COUNT = 100;
private void callMethod() {
HttpClient client = new HttpClient();
client.getHostConfiguration().setHost("localhost", 8080, "http");
PostMethod method = new PostMethod("/axis/WsTest02.jws");
method.addRequestHeader("content-type", "text/xml; charset=utf-8");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try {
buildRequest(outStream);
} catch (TransformerConfigurationException e1) {
e1.printStackTrace();
} catch (TransformerFactoryConfigurationError e1) {
e1.printStackTrace();
} catch (SAXException e1) {
e1.printStackTrace();
}
byte[] requestBytes = outStream.toByteArray();
method
.addRequestHeader("accept",
"application/soap+xml, application/dime, multipart/related, text/*");
method.addRequestHeader("user-agent", "Usoap/1.2.1");
method.addRequestHeader("host", "localhost:8080");
method.addRequestHeader("cache-control", "no-cache");
method.addRequestHeader("pragma", "no-cache");
method.addRequestHeader("soapaction", "\"\"");
method.addRequestHeader("content-length", String
.valueOf(requestBytes.length));
method.setRequestBody(new ByteArrayInputStream(requestBytes));
try {
client.executeMethod(method);
try {
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(method
.getResponseBodyAsStream()));
SAXResult result = new SAXResult();
result.setHandler(new BlancoReverseContentHandler(
new OutputStreamWriter(new FileOutputStream(
"HttpCallerResponse.txt"))));
BlancoReverseContentHandler.getTransformer().transform(source,
result);
} catch (TransformerConfigurationException e2) {
e2.printStackTrace();
} catch (TransformerException e2) {
e2.printStackTrace();
} catch (TransformerFactoryConfigurationError e2) {
e2.printStackTrace();
}
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
method.releaseConnection();
}
/**
* 送信電文を組み立てます。
*
* @param outStream
* @throws TransformerFactoryConfigurationError
* @throws TransformerConfigurationException
* @throws SAXException
*/
private void buildRequest(ByteArrayOutputStream outStream)
throws TransformerFactoryConfigurationError,
TransformerConfigurationException, SAXException {
TransformerFactory tf = TransformerFactory.newInstance();
SAXTransformerFactory saxTf = (SAXTransformerFactory) tf;
TransformerHandler handler = saxTf.newTransformerHandler();
handler.setResult(new StreamResult(outStream));
handler.startDocument();
handler.startPrefixMapping("soapenv",
"http://schemas.xmlsoap.org/soap/envelope/");
handler.startPrefixMapping("xsd", "http://www.w3.org/2001/XMLSchema");
handler.startPrefixMapping("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenv",
"xmlns:soapenv", "CDATA",
"http://schemas.xmlsoap.org/soap/envelope/");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "xsd",
"xmlns:xsd", "CDATA", "http://www.w3.org/2001/XMLSchema");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "xsi",
"xmlns:xsi", "CDATA",
"http://www.w3.org/2001/XMLSchema-instance");
handler.startElement("http://schemas.xmlsoap.org/soap/envelope/",
"Envelope", "soapenv:Envelope", attributes);
attributes = new AttributesImpl();
handler.startElement("http://schemas.xmlsoap.org/soap/envelope/",
"Body", "soapenv:Body", attributes);
handler.startPrefixMapping("ns1", "http://MyNamespace");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns1",
"xmlns:ns1", "CDATA", "http://MyNamespace");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
handler.startElement("http://MyNamespace", "method02", "ns1:method02",
attributes);
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes
.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"arrayType", "soapenc:arrayType", "CDATA",
"ns1:WsTestInput[2]");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "soapenc:Array");
handler.startElement("", "input", "input", attributes);
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id0");
handler.startElement("", "input", "input", attributes);
handler.endElement("", "input", "input");
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id1");
handler.startElement("", "input", "input", attributes);
handler.endElement("", "input", "input");
handler.endElement("", "input", "input");
handler.endPrefixMapping("soapenc");
handler.endElement("http://MyNamespace", "method02", "ns1:method02");
handler.endPrefixMapping("ns1");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
handler.startPrefixMapping("ns2", "http://MyNamespace");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns2",
"xmlns:ns2", "CDATA", "http://MyNamespace");
attributes.addAttribute("", "id", "id", "CDATA", "id1");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "ns2:WsTestInput");
handler.startElement("", "multiRef", "multiRef", attributes);
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id2");
handler.startElement("", "arg1", "arg1", attributes);
handler.endElement("", "arg1", "arg1");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:string");
handler.startElement("", "arg2", "arg2", attributes);
handler.characters("abc".toCharArray(), 0, 3);
handler.endElement("", "arg2", "arg2");
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("ns2");
handler.endPrefixMapping("soapenc");
handler.startPrefixMapping("ns3", "http://MyNamespace");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "ns3",
"xmlns:ns3", "CDATA", "http://MyNamespace");
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("", "id", "id", "CDATA", "id0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "ns3:WsTestInput");
handler.startElement("", "multiRef", "multiRef", attributes);
attributes = new AttributesImpl();
attributes.addAttribute("", "href", "href", "CDATA", "#id3");
handler.startElement("", "arg1", "arg1", attributes);
handler.endElement("", "arg1", "arg1");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:string");
handler.startElement("", "arg2", "arg2", attributes);
handler.characters("abc".toCharArray(), 0, 3);
handler.endElement("", "arg2", "arg2");
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("soapenc");
handler.endPrefixMapping("ns3");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("", "id", "id", "CDATA", "id2");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:int");
handler.startElement("", "multiRef", "multiRef", attributes);
handler.characters("3".toCharArray(), 0, 1);
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("soapenc");
handler.startPrefixMapping("soapenc",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes = new AttributesImpl();
attributes.addAttribute("http://www.w3.org/2000/xmlns/", "soapenc",
"xmlns:soapenc", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("", "id", "id", "CDATA", "id3");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/encoding/",
"root", "soapenc:root", "CDATA", "0");
attributes.addAttribute("http://schemas.xmlsoap.org/soap/envelope/",
"encodingStyle", "soapenv:encodingStyle", "CDATA",
"http://schemas.xmlsoap.org/soap/encoding/");
attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
"type", "xsi:type", "CDATA", "xsd:int");
handler.startElement("", "multiRef", "multiRef", attributes);
handler.characters("3".toCharArray(), 0, 1);
handler.endElement("", "multiRef", "multiRef");
handler.endPrefixMapping("soapenc");
handler.endElement("http://schemas.xmlsoap.org/soap/envelope/", "Body",
"soapenv:Body");
handler.endElement("http://schemas.xmlsoap.org/soap/envelope/",
"Envelope", "soapenv:Envelope");
handler.endPrefixMapping("xsi");
handler.endPrefixMapping("xsd");
handler.endPrefixMapping("soapenv");
handler.endDocument();
}
public static void main(String[] args) {
new HttpCaller().callMethod();
}
}
multiRef対応の解析コードの例を示します。 SAX2はコールバックなので、いろいろ応用が利いて便利ですね。
SAX2インラインクラスベースによるhrefおよびmultiRefの解析コード
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(request.getInputStream()));
SAXResult result = new SAXResult();
result.setHandler(new ContentHandler() {
/**
* カレントのタグ
*/
private String currentTag = "";
/**
* テキストの記憶領域。「タグ : テキスト」の組み合わせで記憶していきます。
*/
private Hashtable hashTagText = new Hashtable();
/**
* href/multiRefの記憶領域。「id: タグ」の組み合わせで記憶していきます。
*/
private Hashtable hashHref = new Hashtable();
/**
* カレントの multiRefを記憶します。
*/
private Stack currentMultiRef = new Stack();
public void setDocumentLocator(Locator arg0) {
}
public void startDocument() throws SAXException {
System.out.println("開始します.");
}
public void endDocument() throws SAXException {
// TODO:ここで何かしらの終了処理を行います。
}
public void startPrefixMapping(String arg0, String arg1)
throws SAXException {
}
public void endPrefixMapping(String arg0) throws SAXException {
}
public void startElement(String arg0, String arg1, String arg2,
Attributes attributes) throws SAXException {
// カレントのタグを記憶します。
currentTag = arg2;
if (hashTagText.get(currentTag) == null) {
// もしタグがない場合には新規作成します。
hashTagText.put(currentTag, new CharArrayWriter());
}
if (currentTag.equals("multiRef")) {
for (int index = 0; index < attributes.getLength(); index++) {
if (attributes.getLocalName(index).equals("id")) {
currentMultiRef.push(attributes.getValue(index));
}
}
}
for (int index = 0; index < attributes.getLength(); index++) {
if (attributes.getLocalName(index).equals("href")) {
hashHref.put(attributes.getValue(index).substring(1),
currentTag);
}
}
}
public void endElement(String arg0, String arg1, String arg2)
throws SAXException {
CharArrayWriter writer = null;
String strText = null;
if (currentTag != null && hashTagText.get(currentTag) != null) {
writer = (CharArrayWriter) hashTagText.get(currentTag);
writer.flush();
strText = writer.toString();
System.out.println(currentTag + "[" + strText + "]");
writer.reset();
}
if (currentTag.equals("multiRef")) {
String strCurrentMultiRef = (String) currentMultiRef.pop();
System.out.println("multiRef読み替え:"
+ hashHref.get(strCurrentMultiRef) + "[" + strText
+ "]");
}
// TODO:ここでタグにより分岐処理を行います。
}
public void characters(char[] arg0, int arg1, int arg2)
throws SAXException {
if (hashTagText.get(currentTag) == null) {
// もしタグがない場合には新規作成します。
hashTagText.put(currentTag, new CharArrayWriter());
}
((CharArrayWriter) hashTagText.get(currentTag)).write(arg0,
arg1, arg2);
}
public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
throws SAXException {
}
public void processingInstruction(String arg0, String arg1)
throws SAXException {
}
public void skippedEntity(String arg0) throws SAXException {
}
});
BlancoReverseContentHandler.getTransformer().transform(source, result);
※ほんとうはタグについてもスタック対応すべきなのでしょう。※SOAP 1.2では hrefは名称が enc:refに変更されています。SOAP 1.2では IDREFなどの用語も登場します。 低速な箇所の高速化のために、上記技法が有益であることはわかったのですが、対応実施までは至らず。残念。
関連する日記