View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.juddi.registry.local;
17  
18  import java.util.Vector;
19  
20  import javax.xml.parsers.DocumentBuilder;
21  import javax.xml.parsers.DocumentBuilderFactory;
22  import javax.xml.parsers.ParserConfigurationException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.juddi.datatype.RegistryObject;
27  import org.apache.juddi.datatype.response.DispositionReport;
28  import org.apache.juddi.datatype.response.ErrInfo;
29  import org.apache.juddi.datatype.response.Result;
30  import org.apache.juddi.error.BusyException;
31  import org.apache.juddi.error.FatalErrorException;
32  import org.apache.juddi.error.RegistryException;
33  import org.apache.juddi.error.UnsupportedException;
34  import org.apache.juddi.handler.HandlerMaker;
35  import org.apache.juddi.handler.IHandler;
36  import org.apache.juddi.registry.RegistryEngine;
37  import org.w3c.dom.Document;
38  import org.w3c.dom.Element;
39  import org.w3c.dom.Node;
40  
41  /***
42   * @author Kurt Stam (kurt.stam@redhat.com)
43   */
44  public class RequestHandler implements Runnable
45  {
46    // private reference to the webapp's logger.
47    private static Log log = LogFactory.getLog(RequestHandler.class);
48    
49    // XML Document Builder
50    private static DocumentBuilder docBuilder = null;
51    
52    private volatile String version;
53    private volatile String operation;
54    private volatile Element uddiReq;
55    private volatile Node response;
56    private volatile String exception;
57     
58      /***
59     * Grab the local name of the UDDI request element
60     * from the UDDI Request. If a value isn't returned 
61     * (either null or an empty String is returned) then 
62     * throw a FatalError exception. This is probably a 
63     * configuration problem related to the XML Parser 
64     * that jUDDI is using.
65     * @param uddiReq
66     * @return 
67     * @throws Exception
68     */
69    public String getOperation(Element uddiReq) throws Exception
70    {
71        if (uddiReq == null)
72            throw new FatalErrorException("A UDDI request was not " +
73              "found in the SOAP message.");
74  
75        String operation = uddiReq.getLocalName();
76        if ((operation == null) || (operation.trim().length() == 0))
77          throw new FatalErrorException("The UDDI service operation " +
78            "could not be identified.");
79        setOperation(operation);
80        return operation;
81    }
82    /***
83     * Grab the generic attribute value (version value).  If 
84     * one isn't specified or the value specified is not "2.0" 
85     * then throw an exception (this value must be specified 
86     * for all UDDI requests and currently only vesion 2.0
87     * UDDI requests are supported).
88     *   
89     * @param uddiReq
90     * @return
91     * @throws Exception
92     */
93    public String getVersion(Element uddiReq, String operation) throws Exception
94    {
95        String version = uddiReq.getAttribute("generic");
96        if (version == null)
97          throw new FatalErrorException("A UDDI generic attribute " +
98            "value was not found for UDDI request: "+operation+" (The " +
99            "'generic' attribute must be present)");
100       setVersion(version);
101       return version;
102   }
103   
104   public void run()
105   {
106     try 
107     { 
108       // Lookup the appropriate XML handler.  Throw an 
109       // UnsupportedException if one could not be located.
110       HandlerMaker maker = HandlerMaker.getInstance();
111 			IHandler requestHandler = maker.lookup(operation);
112       if (requestHandler == null)
113         throw new UnsupportedException("The UDDI service operation " +
114           "specified is unknown or unsupported: " +operation);
115       
116       // Unmarshal the raw xml into the appropriate jUDDI
117       // request object.
118 
119       RegistryObject uddiReqObj = requestHandler.unmarshal(uddiReq);
120       
121       // Grab a reference to the shared jUDDI registry 
122       // instance (make sure it's running) and execute the 
123       // requested UDDI function.
124       
125       RegistryObject uddiResObj = null;      
126       RegistryEngine registry = Registry.getRegistry();
127       if ((registry != null) && (registry.isAvailable()))
128         uddiResObj = registry.execute(uddiReqObj);
129       else
130         throw new BusyException("The Registry is currently unavailable.");
131       
132       // Lookup the appropriate response handler which will
133       // be used to marshal the UDDI object into the appropriate 
134       // xml format.
135       
136       IHandler responseHandler = maker.lookup(uddiResObj.getClass().getName());
137       if (responseHandler == null)
138         throw new FatalErrorException("The response object " +
139           "type is unknown: " +uddiResObj.getClass().getName());
140       
141       // Create a new 'temp' XML element to use as a container 
142       // in which to marshal the UDDI response data into.
143         
144       DocumentBuilder docBuilder = getDocumentBuilder();
145       Document document = docBuilder.newDocument();
146       Element element = document.createElement("temp");
147       
148       // Lookup the appropriate response handler and marshal 
149       // the juddi object into the appropriate xml format (we 
150       // only support UDDI v2.0 at this time).  Attach the
151       // results to the body of the SOAP response.
152         
153       responseHandler.marshal(uddiResObj,element);
154       
155       // Grab a reference to the 'temp' element's
156       // only child here (this has the effect of
157       // discarding the temp element) and append 
158       // this child to the soap response body
159       document.appendChild(element.getFirstChild());
160       setResponse(document);
161     }
162     catch (RegistryException rex) 
163     {
164     	log.error(rex.getMessage());
165     	
166         // All RegistryException and subclasses of RegistryException
167         // should contain values for populating a SOAP Fault as well
168         // as a UDDI DispositionReport with specific information 
169         // about the problem.
170     	// SOAP Fault values
171         String faultCode = rex.getFaultCode();
172         String faultString = rex.getFaultString();
173         String faultActor = rex.getFaultActor();
174         
175         // UDDI DispositionReport values
176         String errno = null;
177         String errCode = null;
178         String errText = null;
179         
180         DispositionReport dispRpt = rex.getDispositionReport();
181         if (dispRpt != null)
182         {
183           Result result = null;
184           ErrInfo errInfo = null;
185         
186           Vector results = dispRpt.getResultVector();
187           if ((results != null) && (!results.isEmpty()))
188             result = (Result)results.elementAt(0);
189         
190           if (result != null)
191           {
192             errno = String.valueOf(result.getErrno());  // UDDI Result errno
193             errInfo = result.getErrInfo();
194           
195             if (errInfo != null)
196             {
197               errCode = errInfo.getErrCode();  // UDDI ErrInfo errCode
198               errText = errInfo.getErrMsg();  // UDDI ErrInfo errMsg
199             }
200           }
201         }
202         // We should have everything we need to assemble 
203         // the SOAPFault so lets piece it together and 
204         // send it on it's way.
205         String fault = "faultCode=" + faultCode + ", faultString=" + faultString 
206     	+ ", faultActor=" + faultActor + ", errno=" + errno + ", errCode=" + errCode
207     	+ ", errText=" + errText;
208         setException(fault);
209         
210     }
211     catch(Exception ex) // Catch any other exceptions
212     {
213         log.error(ex.getMessage());
214     
215         // Because something occured that jUDDI wasn't expecting
216         // let's set default SOAP Fault values.  Since SOAPExceptions
217         // here are most likely XML validation errors let's blame the
218         // client by placing "Client" in the Fault Code and pass
219         // the Exception message back to the client.
220         
221         String faultCode = "Server";
222         String faultString = ex.getMessage();
223         String faultActor = null;
224         
225         // Let's set default values for the UDDI DispositionReport
226         // here.  While we didn't catch a RegistryException (or 
227         // subclass) but we're going to be friendly and include a
228         // FatalError DispositionReport within the SOAP Fault anyway.
229         
230         String errno = String.valueOf(Result.E_FATAL_ERROR);
231         String errCode = Result.lookupErrCode(Result.E_FATAL_ERROR); 
232         String errText = Result.lookupErrText(Result.E_FATAL_ERROR) +
233                   " An internal UDDI server error has " +
234                   "occurred. Please report this error " +
235                   "to the UDDI server administrator.";
236 
237         // We should have everything we need to assemble 
238         // the SOAPFault so lets piece it together and 
239         // send it on it's way.
240         String fault = "faultCode=" + faultCode + ", faultString=" + faultString 
241     	+ ", faultActor=" + faultActor + ", errno=" + errno + ", errCode=" + errCode
242     	+ ", errText=" + errText;
243         setException(fault);
244     }
245   }
246   
247   /***
248    *
249    */
250   private DocumentBuilder getDocumentBuilder()
251   {
252     if (docBuilder == null)
253       docBuilder = createDocumentBuilder();    
254     return docBuilder;
255   }
256 
257   /***
258    *
259    */
260   private synchronized DocumentBuilder createDocumentBuilder()
261   {
262     if (docBuilder != null)
263       return docBuilder;
264 
265     try {
266      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
267      factory.setNamespaceAware(true);
268      //factory.setValidating(true);
269 
270      docBuilder = factory.newDocumentBuilder();
271     }
272     catch(ParserConfigurationException pcex) {
273       pcex.printStackTrace();
274     }
275 
276     return docBuilder;
277   }
278 public String getOperation() {
279     return operation;
280 }
281 public void setOperation(String operation) {
282     this.operation = operation;
283 }
284 public Node getResponse() {
285     return response;
286 }
287 public void setResponse(Node response) {
288     this.response = response;
289 }
290 public Element getUddiReq() {
291     return uddiReq;
292 }
293 public void setUddiReq(Element uddiReq) {
294     this.uddiReq = uddiReq;
295 }
296 public String getVersion() {
297     return version;
298 }
299 public void setVersion(String version) {
300     this.version = version;
301 }
302 public String getException() {
303     return exception;
304 }
305 public void setException(String exception) {
306     this.exception = exception;
307 }
308 }