/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.transport.sms; import org.apache.axiom.om.*; import org.apache.axiom.soap.SOAPBody; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.MessageContext; import org.apache.axis2.description.*; import org.apache.axis2.engine.AxisConfiguration; import org.apache.axis2.wsdl.WSDLConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ws.commons.schema.*; import javax.activation.DataHandler; import javax.xml.namespace.QName; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Builds the MessageContext for the from the incoming SMS * accepts the RPC style message format * serviceName : operationName : param_1 = value_1 : param_2 = value_2 : param_3 = value _3 : ... : param_n = value_n * eg: Election : vote : party = XXX : candidate = XXX */ public class DefaultSMSMessageBuilderImpl implements SMSMessageBuilder { public static final String KEY_VALUE_SEPERATOR="="; /** the reference to the actual commons logger to be used for log messages */ protected Log log = LogFactory.getLog(this.getClass()); public MessageContext buildMessaage(SMSMessage msg,ConfigurationContext configurationContext) throws InvalidMessageFormatException { String message = msg.getContent(); String sender = msg.getSender(); String receiver = msg.getReceiver(); String[] parts = message.split(":"); //may be can add feature to send message format for a request like ???? if (parts.length < 2) { throw new InvalidMessageFormatException("format must be \"service_name \" : \"opration_name\" : " + "\"parm_1=val_1\" :..:\"param_n = val_n\""); } else { AxisConfiguration repo = configurationContext.getAxisConfiguration(); MessageContext messageContext = configurationContext.createMessageContext(); parts = trimSplited(parts); try { AxisService axisService = repo.getService(parts[0]); if (axisService == null) { throw new InvalidMessageFormatException("Service : " + parts[0] + "does not exsist"); } else { messageContext.setAxisService(axisService); AxisOperation axisOperation = axisService.getOperation(new QName(parts[1])); if (axisOperation == null) { throw new InvalidMessageFormatException("Operation: " + parts[1] + " does not exsist"); } messageContext.setAxisOperation(axisOperation); messageContext.setAxisMessage(axisOperation.getMessage( WSDLConstants.MESSAGE_LABEL_IN_VALUE)); Map params = getParams(parts,2); SOAPEnvelope soapEnvelope = createSoapEnvelope(messageContext , params); messageContext.setServerSide(true); messageContext.setEnvelope(soapEnvelope); TransportInDescription in = configurationContext.getAxisConfiguration().getTransportIn("sms"); TransportOutDescription out = configurationContext.getAxisConfiguration().getTransportOut("sms"); messageContext.setIncomingTransportName("sms"); messageContext.setProperty(SMSTransportConstents.SEND_TO , sender); messageContext.setProperty(SMSTransportConstents.DESTINATION , receiver); messageContext.setTransportIn(in); messageContext.setTransportOut(out); handleSMSProperties(msg , messageContext); return messageContext; } } catch (AxisFault axisFault) { log.debug("[DefaultSMSMessageBuilderImpl] Error while extracting the axis2Service \n" + axisFault); } } return null; } /** * this will add the SMSMessage properties to the Axis2MessageContext * @param msg * @param messageContext */ protected void handleSMSProperties(SMSMessage msg , MessageContext messageContext) { Iterator<String> it = msg.getProperties().keySet().iterator(); while (it.hasNext()) { String key = it.next(); messageContext.setProperty(key , msg.getProperties().get(key)); } } private SOAPEnvelope createSoapEnvelope(MessageContext messageContext , Map params) { SOAPFactory soapFactory = OMAbstractFactory.getSOAP12Factory(); SOAPEnvelope inEnvlope = soapFactory.getDefaultEnvelope(); SOAPBody inBody = inEnvlope.getBody(); XmlSchemaElement xmlSchemaElement; AxisOperation axisOperation = messageContext.getAxisOperation(); if (axisOperation != null) { AxisMessage axisMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE); xmlSchemaElement = axisMessage.getSchemaElement(); if (xmlSchemaElement == null) { OMElement bodyFirstChild = soapFactory .createOMElement(messageContext.getAxisOperation().getName(), inBody); createSOAPMessageWithoutSchema(soapFactory,bodyFirstChild,params); } else { // first get the target namespace from the schema and the wrapping element. // create an OMElement out of those information. We are going to extract parameters from // url, create OMElements and add them as children to this wrapping element. String targetNamespace = xmlSchemaElement.getQName().getNamespaceURI(); QName bodyFirstChildQName; if (targetNamespace != null && !"".equals(targetNamespace)) { bodyFirstChildQName = new QName(targetNamespace, xmlSchemaElement.getName()); } else { bodyFirstChildQName = new QName(xmlSchemaElement.getName()); } OMElement bodyFirstChild = soapFactory.createOMElement(bodyFirstChildQName, inBody); // Schema should adhere to the IRI style in this. So assume IRI style and dive in to // schema XmlSchemaType schemaType = xmlSchemaElement.getSchemaType(); if (schemaType instanceof XmlSchemaComplexType) { XmlSchemaComplexType complexType = ((XmlSchemaComplexType)schemaType); XmlSchemaParticle particle = complexType.getParticle(); if (particle instanceof XmlSchemaSequence || particle instanceof XmlSchemaAll) { XmlSchemaGroupBase xmlSchemaGroupBase = (XmlSchemaGroupBase)particle; Iterator iterator = xmlSchemaGroupBase.getItems().getIterator(); // now we need to know some information from the binding operation. while (iterator.hasNext()) { XmlSchemaElement innerElement = (XmlSchemaElement)iterator.next(); QName qName = innerElement.getQName(); if (qName == null && innerElement.getSchemaTypeName() .equals(org.apache.ws.commons.schema.constants.Constants.XSD_ANYTYPE)) { createSOAPMessageWithoutSchema(soapFactory, bodyFirstChild, params); break; } long minOccurs = innerElement.getMinOccurs(); boolean nillable = innerElement.isNillable(); String name = qName != null ? qName.getLocalPart() : innerElement.getName(); Object value; OMNamespace ns = (qName == null || qName.getNamespaceURI() == null || qName.getNamespaceURI().length() == 0) ? null : soapFactory.createOMNamespace( qName.getNamespaceURI(), null); // FIXME changed if ((value = params.get(name)) != null ) { addRequestParameter(soapFactory, bodyFirstChild, ns, name, value); minOccurs--; } if (minOccurs > 0) { if (nillable) { OMNamespace xsi = soapFactory.createOMNamespace( Constants.URI_DEFAULT_SCHEMA_XSI, Constants.NS_PREFIX_SCHEMA_XSI); OMAttribute omAttribute = soapFactory.createOMAttribute("nil", xsi, "true"); soapFactory.createOMElement(name, ns, bodyFirstChild) .addAttribute(omAttribute); } else { // throw new AxisFault("Required element " + qName + // " defined in the schema can not be" + // " found in the request"); } } } } } } } return inEnvlope; } private static void createSOAPMessageWithoutSchema(SOAPFactory soapFactory, OMElement bodyFirstChild, Map requestParameterMap) { // first add the parameters in the URL if (requestParameterMap != null) { Iterator requestParamMapIter = requestParameterMap.keySet().iterator(); while (requestParamMapIter.hasNext()) { String key = (String) requestParamMapIter.next(); Object value = requestParameterMap.get(key); if (value != null) { addRequestParameter(soapFactory, bodyFirstChild, null, key, value); } } } } private static void addRequestParameter(SOAPFactory soapFactory, OMElement bodyFirstChild, OMNamespace ns, String key, Object parameter) { if (parameter instanceof DataHandler) { DataHandler dataHandler = (DataHandler) parameter; OMText dataText = bodyFirstChild.getOMFactory().createOMText( dataHandler, true); soapFactory.createOMElement(key, ns, bodyFirstChild).addChild( dataText); } else { String textValue = parameter.toString(); soapFactory.createOMElement(key, ns, bodyFirstChild).setText( textValue); } } private Map getParams(String []array , int startIndex) throws InvalidMessageFormatException{ HashMap params = new HashMap(); for(int i=startIndex ;i < array.length ;i++) { String [] pramParts = array[i].split(KEY_VALUE_SEPERATOR); pramParts = trimSplited(pramParts); if(pramParts == null || pramParts.length != 2) { throw new InvalidMessageFormatException("format must be \"service_name \" : \"opration_name\" : " + "\"parm_1=val_1\" :..:\"param_n = val_n\""); } params.put( pramParts[0] , pramParts[1] ); } return params; } private String[] trimSplited(String parts[]) { if (parts == null) { return null; } for (int i = 0; i < parts.length; i++) { parts[i] = parts[i].trim(); } return parts; } }