1
2
3
4
5
6
7 package org.astrogrid.dataservice.service;
8 import java.io.PrintWriter;
9 import java.io.StringWriter;
10 import java.rmi.RemoteException;
11 import java.security.Principal;
12 import javax.xml.namespace.QName;
13 import javax.xml.rpc.soap.SOAPFaultException;
14 import javax.xml.soap.Detail;
15 import javax.xml.soap.SOAPException;
16 import javax.xml.soap.SOAPFactory;
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.astrogrid.dataservice.metadata.VoDescriptionServer;
20 import org.astrogrid.dataservice.queriers.status.QuerierStatus;
21 import org.astrogrid.xml.DomHelper;
22
23 /***
24 * Provides methods suitable for a SOAP implementation of the Datacenter. This
25 * is an abstract class as we want to *force* people to subclass. That means
26 * that if the interface changes, a new subclass can be added without
27 * interfering with the old one.
28 *
29 * @author M Hill
30 * @author Noel Winstanly
31 *
32 */
33
34 public abstract class SoapDataServer {
35
36 protected static Log log = LogFactory.getLog(SoapDataServer.class);
37
38 protected DataServer server = new DataServer();
39
40 public SoapDataServer() {
41 }
42
43 /***
44 * Returns the metadata file as a string
45 */
46 public String getMetadata() throws SOAPFaultException {
47 try {
48 return DomHelper.DocumentToString(VoDescriptionServer.getVoDescription());
49 }
50 catch (Throwable e) {
51 throw makeSoapFault("Server", "Could not access metadata", e);
52 }
53 }
54
55 /***
56 * This routine is public so that we can test our client-side error
57 * reporting */
58 public void testFault(String message) throws SOAPFaultException {
59 throw makeSoapFault(message);
60 }
61
62 /***
63 * Sets up a SOAP Fault Exception suitable for passing the original cause of
64 * the error across the web interface.
65 * Note that it is not sufficient to throw this; the fault handler requires
66 * some work to include the details in the fault response.
67 * @see summary at http://www.w3schools.com/SOAP/soap_fault.asp
68 * @see .Net-related article at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnservice/html/service09172002.asp
69 * @see JAX-RPC article (low level) at http://www.fawcette.com/javapro/2004_01/online/webservices_kjones_01_21_04/page2.aspx
70 *
71 * <p>
72 * The actor is assumed to be this service.
73 * <p>
74 * This can be overridden by subclasses to throw faults more appropriate to
75 * their publication mechanism. For example AxisFault is more useful for
76 * Axis services. Unfortunately AxisFault subclasses RuntimeException and
77 * SOAPFaultException subclasses RemoteException (->IOException).
78 * <p>
79 * @code - Client, Server depending on whether the error is caused by
80 * something wrong being sent from the client, or a failure inside the server
81 */
82 protected SOAPFaultException makeSoapFault(String code, String message, Throwable cause) {
83
84 log.error("An error has occured, so throwing "+cause+" to client, message="+message, cause);
85
86 QName faultCode = new QName(code);
87
88 try {
89 Detail detail = SOAPFactory.newInstance().createDetail();
90
91 if (cause != null) {
92 detail.addTextNode(cause.getClass().toString());
93 detail.addTextNode(cause.toString());
94
95
96 StringWriter writer = new StringWriter();
97 cause.printStackTrace(new PrintWriter(writer));
98 detail.addTextNode(writer.toString());
99 }
100
101 return new SOAPFaultException(faultCode, message, cause.toString(), detail);
102 }
103 catch (SOAPException se) {
104 log.error(se+" trying to build SOAPFaultException("+faultCode+", "+message+", "+cause.toString()+")");
105 return new SOAPFaultException(faultCode, message, cause.toString(), null);
106 }
107
108 }
109
110 /***
111 * Convenience method for makeSoapFault(String, Throwable=null)
112 */
113 protected SOAPFaultException makeSoapFault(String message) {
114
115 return makeSoapFault("Server", message, null);
116 }
117
118 /***
119 * Aborts the query specified by the given id. Returns
120 * nothing - if there are any problems doing this it's a server-end problem.
121 */
122 public void abortQuery(Principal user, String queryId) throws SOAPFaultException {
123 try {
124 server.abortQuery(user, queryId);
125 }
126 catch (IllegalArgumentException iae) {
127 throw makeSoapFault("Client", "Aborting "+queryId, iae);/
128
129
130
131
132
133
134
135
136
137
138 public QuerierStatus getQueryStatus(Principal user, String queryId) throws RemoteException {
139 try {
140 return server.getQueryStatus(user, queryId);
141 }
142 catch (IllegalArgumentException iae) {
143 throw makeSoapFault("Client", "Aborting "+queryId, iae);/
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186