001: package com.sun.xml.ws.mex.server;
002:
003: import com.sun.xml.stream.buffer.MutableXMLStreamBuffer;
004: import com.sun.xml.ws.api.SOAPVersion;
005: import com.sun.xml.ws.api.addressing.AddressingVersion;
006: import com.sun.xml.ws.api.message.HeaderList;
007: import com.sun.xml.ws.api.message.Message;
008: import com.sun.xml.ws.api.message.Messages;
009: import com.sun.xml.ws.api.server.BoundEndpoint;
010: import com.sun.xml.ws.api.server.Module;
011: import com.sun.xml.ws.api.server.WSEndpoint;
012: import com.sun.xml.ws.api.server.WSWebServiceContext;
013: import com.sun.xml.ws.developer.JAXWSProperties;
014: import com.sun.xml.ws.transport.http.servlet.ServletModule;
015: import java.util.List;
016: import java.util.logging.Level;
017: import java.util.logging.Logger;
018: import javax.annotation.Resource;
019: import javax.xml.stream.XMLStreamException;
020: import javax.xml.stream.XMLStreamWriter;
021: import javax.xml.ws.BindingProvider;
022: import javax.xml.ws.WebServiceContext;
023: import javax.xml.ws.WebServiceException;
024: import javax.xml.ws.handler.MessageContext;
025: import javax.xml.ws.Provider;
026: import javax.xml.ws.Service;
027: import javax.xml.ws.ServiceMode;
028: import javax.xml.ws.WebServiceProvider;
029: import javax.xml.ws.soap.Addressing;
030: import com.sun.xml.ws.mex.MetadataConstants;
031: import javax.servlet.http.HttpServletRequest;
032: import com.sun.xml.ws.mex.MessagesMessages;
033:
034: import static com.sun.xml.ws.mex.MetadataConstants.GET_MDATA_REQUEST;
035: import static com.sun.xml.ws.mex.MetadataConstants.GET_REQUEST;
036: import static com.sun.xml.ws.mex.MetadataConstants.GET_RESPONSE;
037: import static com.sun.xml.ws.mex.MetadataConstants.MEX_NAMESPACE;
038: import static com.sun.xml.ws.mex.MetadataConstants.MEX_PREFIX;
039: import static com.sun.xml.ws.mex.MetadataConstants.WSA_PREFIX;
040:
041: @ServiceMode(value=Service.Mode.MESSAGE)
042: @WebServiceProvider
043: @Addressing(enabled=true,required=true)
044: public class MEXEndpoint implements Provider<Message> {
045:
046: @Resource
047: protected WebServiceContext wsContext;
048:
049: private static final Logger logger = Logger
050: .getLogger(MEXEndpoint.class.getName());
051:
052: public Message invoke(Message requestMsg) {
053: if (requestMsg == null || !requestMsg.hasHeaders()) {
054: // TODO: Better error message
055: throw new WebServiceException("Malformed MEX Request");
056: }
057:
058: WSEndpoint wsEndpoint = (WSEndpoint) wsContext
059: .getMessageContext().get(JAXWSProperties.WSENDPOINT);
060: SOAPVersion soapVersion = wsEndpoint.getBinding()
061: .getSOAPVersion();
062:
063: // try w3c version of ws-a first, then member submission version
064: final HeaderList headers = requestMsg.getHeaders();
065:
066: String action = headers.getAction(AddressingVersion.W3C,
067: soapVersion);
068: AddressingVersion wsaVersion = AddressingVersion.W3C;
069: if (action == null) {
070: action = headers.getAction(AddressingVersion.MEMBER,
071: soapVersion);
072: wsaVersion = AddressingVersion.MEMBER;
073: }
074:
075: if (action == null) {
076: // TODO: Better error message
077: throw new WebServiceException("No wsa:Action specified");
078: } else if (action.equals(GET_REQUEST)) {
079: final String toAddress = headers.getTo(wsaVersion,
080: soapVersion);
081: return processGetRequest(requestMsg, toAddress, wsaVersion,
082: soapVersion);
083: } else if (action.equals(GET_MDATA_REQUEST)) {
084: final Message faultMessage = Messages.create(
085: GET_MDATA_REQUEST, wsaVersion, soapVersion);
086: wsContext.getMessageContext().put(
087: BindingProvider.SOAPACTION_URI_PROPERTY,
088: wsaVersion.getDefaultFaultAction());
089: return faultMessage;
090: }
091: // If here, either action is unsupported
092: // TODO: Better error message
093: throw new UnsupportedOperationException(action);
094: }
095:
096: /*
097: * This method creates an xml stream buffer, writes the response to
098: * it, and uses it to create a response message.
099: */
100: private Message processGetRequest(final Message request,
101: String address, final AddressingVersion wsaVersion,
102: final SOAPVersion soapVersion) {
103:
104: try {
105: final MutableXMLStreamBuffer buffer = new MutableXMLStreamBuffer();
106: final XMLStreamWriter writer = buffer
107: .createFromXMLStreamWriter();
108:
109: WSEndpoint wsEndpoint = (WSEndpoint) wsContext
110: .getMessageContext()
111: .get(JAXWSProperties.WSENDPOINT);
112: HttpServletRequest servletRequest = (HttpServletRequest) wsContext
113: .getMessageContext().get(
114: MessageContext.SERVLET_REQUEST);
115: if (servletRequest == null) {
116: // TODO: better error message
117: throw new WebServiceException(
118: "MEX: no ServletRequest can be found");
119: }
120:
121: // Derive the address of the owner endpoint.
122: // e.g. http://localhost/foo/mex --> http://localhost/foo
123: WSEndpoint ownerEndpoint = null;
124: ServletModule module = (ServletModule) wsEndpoint
125: .getContainer().getSPI(ServletModule.class);
126: String baseAddress = module.getContextPath(servletRequest);
127: String ownerEndpointAddress = null;
128: List<BoundEndpoint> boundEndpoints = module
129: .getBoundEndpoints();
130: for (BoundEndpoint endpoint : boundEndpoints) {
131: if (wsEndpoint == endpoint.getEndpoint()) {
132: ownerEndpointAddress = endpoint.getAddress(
133: baseAddress).toString();
134: break;
135: }
136: }
137: ownerEndpointAddress = ownerEndpointAddress.substring(0,
138: ownerEndpointAddress.length() - "/mex".length());
139:
140: boundEndpoints = module.getBoundEndpoints();
141: for (BoundEndpoint endpoint : boundEndpoints) {
142: //compare ownerEndpointAddress with this endpoints address
143: // if matches, set ownerEndpoint to the corresponding WSEndpoint
144: String endpointAddress = endpoint.getAddress(
145: baseAddress).toString();
146: if (endpointAddress.equals(ownerEndpointAddress)) {
147: ownerEndpoint = endpoint.getEndpoint();
148: break;
149: }
150: }
151:
152: // If the owner endpoint has been found, then
153: // get its metadata and write it to the response message
154: if (ownerEndpoint != null) {
155: address = address.substring(0, address.length() - 4);
156: writeStartEnvelope(writer, wsaVersion, soapVersion);
157: WSDLRetriever wsdlRetriever = new WSDLRetriever(
158: ownerEndpoint);
159: wsdlRetriever.addDocuments(writer, null, address);
160: writer.writeEndDocument();
161: writer.flush();
162: final Message responseMessage = Messages.create(buffer);
163: wsContext.getMessageContext().put(
164: BindingProvider.SOAPACTION_URI_PROPERTY,
165: GET_RESPONSE);
166: return responseMessage;
167: }
168:
169: // If we get here there was no metadata for the owner endpoint
170: // TODO: This should probably be something other than unsupported action for clarity
171: final Message faultMessage = Messages.create(GET_REQUEST,
172: wsaVersion, soapVersion);
173: wsContext.getMessageContext().put(
174: BindingProvider.SOAPACTION_URI_PROPERTY,
175: wsaVersion.getDefaultFaultAction());
176: return faultMessage;
177: } catch (XMLStreamException streamE) {
178: final String exceptionMessage = MessagesMessages
179: .MEX_0001_RESPONSE_WRITING_FAILURE(address);
180: logger.log(Level.SEVERE, exceptionMessage, streamE);
181: throw new WebServiceException(exceptionMessage, streamE);
182: }
183: }
184:
185: private void writeStartEnvelope(final XMLStreamWriter writer,
186: final AddressingVersion wsaVersion,
187: final SOAPVersion soapVersion) throws XMLStreamException {
188:
189: final String soapPrefix = "soapenv";
190:
191: writer.writeStartDocument();
192: writer.writeStartElement(soapPrefix, "Envelope",
193: soapVersion.nsUri);
194:
195: // todo: this line should go away after bug fix - 6418039
196: writer.writeNamespace(soapPrefix, soapVersion.nsUri);
197:
198: writer.writeNamespace(MetadataConstants.WSA_PREFIX,
199: wsaVersion.nsUri);
200: writer.writeNamespace(MetadataConstants.MEX_PREFIX,
201: MetadataConstants.MEX_NAMESPACE);
202:
203: writer.writeStartElement(soapPrefix, "Body", soapVersion.nsUri);
204: writer.writeStartElement(MetadataConstants.MEX_PREFIX,
205: "Metadata", MetadataConstants.MEX_NAMESPACE);
206: }
207:
208: }
|