KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > dig > DIGConnection


1 /*****************************************************************************
2  * Source code information
3  * -----------------------
4  * Original author Ian Dickinson, HP Labs Bristol
5  * Author email ian.dickinson@hp.com
6  * Package Jena 2
7  * Web http://sourceforge.net/projects/jena/
8  * Created 11-Sep-2003
9  * Filename $RCSfile: DIGConnection.java,v $
10  * Revision $Revision: 1.12 $
11  * Release status $State: Exp $
12  *
13  * Last modified on $Date: 2005/03/24 17:33:18 $
14  * by $Author: ian_dickinson $
15  *
16  * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
17  * [See end of file]
18  *****************************************************************************/

19
20
21 // Package
22
///////////////
23
package com.hp.hpl.jena.reasoner.dig;
24
25
26
27 // Imports
28
///////////////
29
import java.io.*;
30 import java.net.*;
31 import java.util.*;
32
33 import javax.xml.parsers.*;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.xml.serialize.*;
38 import org.w3c.dom.*;
39
40 import com.hp.hpl.jena.util.FileUtils;
41
42
43 /**
44  * <p>
45  * Encapsulates the connection to a DIG reasoner.
46  * </p>
47  *
48  * @author Ian Dickinson, HP Labs (<a HREF="mailto:Ian.Dickinson@hp.com">email</a>)
49  * @version Release @release@ ($Id: DIGConnection.java,v 1.12 2005/03/24 17:33:18 ian_dickinson Exp $)
50  */

51 public class DIGConnection {
52     // Constants
53
//////////////////////////////////
54

55     /** Default URL for connecting to a local DIG reasoner on port 8081 */
56     public static final String JavaDoc DEFAULT_REASONER_URL = "http://localhost:8081";
57     
58     /** Namespace for XSI */
59     public static final String JavaDoc XSI = "http://www.w3.org/2001/XMLSchema-instance";
60     
61
62     // Static variables
63
//////////////////////////////////
64

65     private static Log log = LogFactory.getLog( DIGConnection.class );
66     
67     
68     // Instance variables
69
//////////////////////////////////
70

71     /** The URL to connect to, initialised to the default URL */
72     protected String JavaDoc m_extReasonerURL = DEFAULT_REASONER_URL;
73     
74     /** URI of current KB */
75     private String JavaDoc m_kbURI;
76     
77     /** The XML document builder we are using */
78     protected DocumentBuilderFactory m_factory = DocumentBuilderFactory.newInstance();
79     
80     /** List of most recent warnings */
81     private List m_warnings = new ArrayList();
82     
83     /** Flag to control whether we log incoming and outgoing messages */
84     protected boolean m_logCommunications = true;
85     
86     
87     // Constructors
88
//////////////////////////////////
89

90     // External signature methods
91
//////////////////////////////////
92

93     /**
94      * <p>Send a verb to the attached DIG reasoner and answer the result. The verb is encoded as an XML
95      * document object.</p>
96      * @param digVerb A DIG verb (information request, ask or tell) as an XML document
97      * @return The resulting XML document formed from the response from the reasoner
98      * @exception DigReasonerException for any errors in XML encoding or HTTP transmission
99      */

100     public Document sendDigVerb( Document digVerb, DIGProfile profile ) {
101         try {
102             // make sure we set the KB uri
103
Element verb = digVerb.getDocumentElement();
104             if (!verb.hasAttribute( DIGProfile.URI )) {
105                 verb.setAttribute( DIGProfile.URI, m_kbURI );
106             }
107             
108             // first open the connection
109
URL url = new URL( m_extReasonerURL );
110             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
111
112             // pre-serialise the content so we can set the Content-Length field correctly
113
StringWriter out = new StringWriter();
114             serialiseDocument( digVerb, out );
115             
116             conn.setDoOutput( true );
117             conn.setRequestMethod( "POST" );
118             conn.setRequestProperty( "Content-Length", Integer.toString( out.getBuffer().length() ) );
119             
120             // different varaints on the protocol make different choices here
121
conn.setRequestProperty( "Content-Type", profile.getContentType() );
122             
123             // log
124
logMessage( true, digVerb );
125             
126             // send
127
conn.connect();
128             PrintWriter pw = FileUtils.asPrintWriterUTF8( conn.getOutputStream() );
129             pw.print( out.getBuffer() );
130             pw.flush();
131             pw.close();
132             
133             // and receive
134
Document response = getDigResponse( conn );
135
136             // log
137
logMessage( false, response );
138             
139             errorCheck( response );
140             return response;
141         }
142         catch (IOException e) {
143             throw new DIGWrappedException( e );
144         }
145     }
146
147
148     /**
149      * <p>Serialise the given document to the given output writer.</p>
150      * @param doc An XML document to serialise
151      * @param out A writer that will consume the seralised form of the document
152      */

153     public void serialiseDocument( Document doc, Writer out ) {
154         try {
155             // write the given document to the string buffer
156
XMLSerializer serializer = new XMLSerializer ( out, createXMLFormatter( doc ) );
157             serializer.asDOMSerializer();
158             serializer.serialize( doc );
159         }
160         catch (IOException e) {
161             throw new DIGWrappedException( e );
162         }
163     }
164
165
166     /**
167      * <p>Bind a DIG KB to this adapter, by requesting a KB URI through the newKB
168      * verb. If there is already a binding, do nothing unless rebind is true.
169      * @param rebind If true, any existing KB will be released before binding
170      * to a new KB
171      */

172     public void bindKB( boolean rebind, DIGProfile profile ) {
173         // delete the old KB
174
if (rebind && m_kbURI != null) {
175             Document release = createDigVerb( DIGProfile.RELEASEKB, profile );
176
177             Document response = sendDigVerb( release, profile );
178             errorCheck( response );
179
180             if (warningCheck(response)) {
181                 log.warn( "DIG reasoner warning: " + getWarnings().next() );
182             }
183             m_kbURI = null;
184         }
185         
186         // allocate a new KB
187
if (m_kbURI == null) {
188             // request a whole new KB
189
Document response = sendDigVerb( createDigVerb( DIGProfile.NEWKB, profile ), profile );
190             errorCheck( response );
191             
192             // extract the new KB URI
193
Element kb = (Element) response.getDocumentElement()
194                                            .getElementsByTagName( DIGProfile.KB )
195                                            .item( 0 );
196             if (kb == null) {
197                 throw new DIGReasonerException( "Could not locate DIG KB identifier in return value from newKB" );
198             }
199             else {
200                 m_kbURI = kb.getAttribute( DIGProfile.URI );
201             }
202         }
203     }
204     
205
206     /**
207      * <p>Check the response from the DIG server to see if there is an error code,
208      * and raise an excption if so.</p>
209      * @param response The response from the DIG server
210      */

211     public void errorCheck( Document response ) {
212         Element root = response.getDocumentElement();
213         NodeList errs = root.getElementsByTagName( DIGProfile.ERROR );
214         
215         if (errs != null && errs.getLength() > 0) {
216             Element error = (Element) errs.item( 0 );
217             
218             String JavaDoc errCode = error.getAttribute( DIGProfile.CODE );
219             int code = (errCode == null || errCode.length() == 0) ? 0 : Integer.parseInt( errCode );
220             
221             String JavaDoc msgAttr = error.getAttribute( DIGProfile.MESSAGE );
222             
223             NodeList messages = error.getChildNodes();
224             String JavaDoc message = (messages.getLength() > 0) ? ((Text) messages.item( 0 )).getNodeValue().trim() : "(no message)";
225             
226             throw new DIGErrorResponseException( message, msgAttr, code );
227         }
228     }
229     
230     
231     /**
232      * <p>Append any warning messages from this response to the list of recent warnings,
233      * which is first cleared.</p>
234      * @param response The response from the DIG server
235      * @return True if any warnings were detected.
236      */

237     public boolean warningCheck( Document response ) {
238         Element root = response.getDocumentElement();
239         NodeList ok = root.getElementsByTagName( DIGProfile.OK );
240         m_warnings.clear();
241         
242         if (ok != null && ok.getLength() > 0) {
243             Element e = (Element) ok.item(0);
244             NodeList warnings = e.getElementsByTagName( DIGProfile.WARNING );
245             
246             if (warnings != null && warnings.getLength() > 0) {
247                 for (int i = 0; i < warnings.getLength(); i++) {
248                     // append the warning message to the list
249
Element warn = (Element) warnings.item( i );
250                     m_warnings.add( warn.getAttribute( DIGProfile.MESSAGE ) );
251                 }
252                 
253                 return true;
254             }
255         }
256         
257         return false;
258     }
259
260
261     /**
262      * <p>Answer an iterator over the warnings received since the last tell operation</p>
263      * @return An iterator over warnings
264      */

265     public Iterator getWarnings() {
266         return m_warnings.iterator();
267     }
268     
269     
270     /**
271      * <p>Release this connection back to the connection pool.</p>
272      */

273     public void release() {
274         DIGConnectionPool.getInstance().release( this );
275     }
276     
277     
278     /**
279      * <p>Answer the URL of the external reasoner this connection is bound to.</p>
280      * @return The current external reasoner URL
281      */

282     public String JavaDoc getReasonerURL() {
283         return m_extReasonerURL;
284     }
285     
286     
287     /**
288      * <p>Set the URL of the external reasoner with which this connection communicates.</p>
289      * @param url The URL of the new external reasoner connection point
290      */

291     public void setReasonerURL( String JavaDoc url ) {
292         m_extReasonerURL = url;
293         m_kbURI = null;
294     }
295
296
297     // Internal implementation methods
298
//////////////////////////////////
299

300     /**
301      * <p>Answer the XML document object that resulted from the most recent request.</p>
302      * @param conn The current HTTP connection
303      * @return The response from the DIG reasoner, as an XML object
304      * @exception DigReasonerException if the underling connection or XML parser raises
305      * an error.
306      */

307     protected Document getDigResponse( HttpURLConnection conn ) {
308         try {
309             // check for successful response
310
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
311                 throw new DIGReasonerException( "DIG reasoner returned failure code " +
312                                                 conn.getResponseCode() + ": " +
313                                                 conn.getResponseMessage() );
314             }
315             
316             BufferedInputStream in = new BufferedInputStream( conn.getInputStream() );
317             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
318             
319             // read the return result into a string buffer before we parse it
320
int ch = in.read();
321             while (ch > 0) {
322                 buf.append( (char) ch );
323                 ch = in.read();
324             }
325             
326             // TODO remove LogFactory.getLog( getClass() ).debug( "Response buffer = " + buf.toString() );
327
// now parse into a document
328
DocumentBuilder builder = m_factory.newDocumentBuilder();
329             return builder.parse( new ByteArrayInputStream( buf.toString().getBytes() ) );
330         }
331         catch (Exception JavaDoc e) {
332             e.printStackTrace( System.err );
333             throw new DIGWrappedException( e );
334         }
335     }
336
337
338     /**
339      * <p>Answer an XML formatter object for the given document
340      * @param doc The XML document to be serialised
341      * @return An XML formatter object for the document
342      */

343     protected OutputFormat createXMLFormatter( Document doc ) {
344         OutputFormat format = new OutputFormat( doc );
345         format.setIndenting( true );
346         format.setLineWidth( 0 );
347         format.setPreserveSpace( false );
348         
349         return format;
350     }
351
352
353     /**
354      * <p>Create a DIG verb as an xml element in a new document object.</p>
355      * @param verbName The name of the DIG verb, as a string
356      * @return An XML DOM element representing the DIG verb
357      */

358     protected Document createDigVerb( String JavaDoc verbName, DIGProfile profile ) {
359         try {
360             // initialise the XML DOM tree
361
DocumentBuilder builder = m_factory.newDocumentBuilder();
362             Document doc = builder.newDocument();
363             
364             // create the verb as the root element of the XML document
365
Element root = doc.createElementNS( profile.getDIGNamespace(), verbName );
366             doc.appendChild( root );
367             
368             // set the standard attributes
369
root.setAttribute( "xmlns", profile.getDIGNamespace() );
370             root.setAttribute( "xmlns:xsi", XSI );
371             root.setAttributeNS( XSI, "xsi:schemaLocation",
372                                  profile.getDIGNamespace() + " " + profile.getSchemaLocation() );
373             if (m_kbURI != null) {
374                 root.setAttribute( DIGProfile.URI, m_kbURI );
375             }
376             
377             return doc;
378         }
379         catch (FactoryConfigurationError e) {
380             throw new DIGWrappedException( e );
381         }
382         catch (ParserConfigurationException e) {
383             throw new DIGWrappedException( e );
384         }
385     }
386     
387
388     /**
389      * <p>Log the messages going to and from DIG</p>
390      * @param outgoing True for send, false for receive
391      * @param msg The document sent or received.
392      */

393     protected void logMessage( boolean outgoing, Document msg ) {
394         if (m_logCommunications) {
395             StringWriter out = new StringWriter();
396             serialiseDocument( msg, out );
397             
398             if (log.isDebugEnabled()) {
399                 log.debug( outgoing ? "Sending to DIG reasoner ..." : "Received from DIG reasoner ..." );
400                 log.debug( out );
401             }
402         }
403     }
404
405
406     //==============================================================================
407
// Inner class definitions
408
//==============================================================================
409

410 }
411
412
413 /*
414  * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
415  * All rights reserved.
416  *
417  * Redistribution and use in source and binary forms, with or without
418  * modification, are permitted provided that the following conditions
419  * are met:
420  * 1. Redistributions of source code must retain the above copyright
421  * notice, this list of conditions and the following disclaimer.
422  * 2. Redistributions in binary form must reproduce the above copyright
423  * notice, this list of conditions and the following disclaimer in the
424  * documentation and/or other materials provided with the distribution.
425  * 3. The name of the author may not be used to endorse or promote products
426  * derived from this software without specific prior written permission.
427  *
428  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
429  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
430  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
431  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
432  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
433  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
434  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
435  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
436  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
437  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
438  */

439
Popular Tags