blob: 5a4406d004b661057ccf5a90c9eae255869e04a6 [file] [log] [blame]
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed 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.axis.message;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.description.ParameterDesc;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.constants.Style;
import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.commons.logging.Log;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
/** An RPC parameter
*
* @author Glen Daniels (gdaniels@apache.org)
*/
public class RPCParam extends MessageElement implements Serializable
{
protected static Log log =
LogFactory.getLog(RPCParam.class.getName());
private Object value = null;
private int countSetCalls = 0; // counts number of calls to set
private ParameterDesc paramDesc;
/**
* Do we definitely want (or don't want) to send xsi:types? If null
* (the default), just do whatever our SerializationContext is configured
* to do. If TRUE or FALSE, the SerializationContext will do what we
* want.
*/
private Boolean wantXSIType = null;
private static Method valueSetMethod;
static {
Class cls = RPCParam.class;
try {
valueSetMethod = cls.getMethod("set", new Class[] {Object.class});
} catch (NoSuchMethodException e) {
log.error(Messages.getMessage("noValue00", "" + e));
throw new RuntimeException(e.getMessage());
}
}
/** Constructor for building up messages.
*/
public RPCParam(String name, Object value)
{
this(new QName("", name), value);
}
public RPCParam(QName qname, Object value)
{
super(qname);
if (value instanceof java.lang.String) {
try {
this.addTextNode((String) value);
} catch (SOAPException e) {
throw new RuntimeException(Messages.getMessage("cannotCreateTextNode00"));
}
} else {
this.value = value;
}
}
public RPCParam(String namespace, String name, Object value)
{
this(new QName(namespace, name), value);
}
public void setRPCCall(RPCElement call)
{
parent = call;
}
public Object getObjectValue()
{
return value;
}
public void setObjectValue(Object value)
{
this.value = value;
}
/**
* This set method is registered during deserialization
* to set the deserialized value.
* If the method is called multiple times, the
* value is automatically changed into a container to
* hold all of the values.
* @param newValue is the deserialized object
*/
public void set(Object newValue) {
countSetCalls++;
// If this is the first call,
// simply set the value.
if (countSetCalls==1) {
this.value = newValue;
return;
}
// If this is the second call, create an
// ArrayList to hold all the values
else if (countSetCalls==2) {
ArrayList list = new ArrayList();
list.add(this.value);
this.value = list;
}
// Add the new value to the list
((ArrayList) this.value).add(newValue);
}
public static Method getValueSetMethod()
{
return valueSetMethod;
}
public ParameterDesc getParamDesc() {
return paramDesc;
}
public void setParamDesc(ParameterDesc paramDesc) {
this.paramDesc = paramDesc;
}
public void setXSITypeGeneration(Boolean value) {
this.wantXSIType = value;
}
public Boolean getXSITypeGeneration() {
return this.wantXSIType;
}
public void serialize(SerializationContext context)
throws IOException
{
// Set the javaType to value's class unless
// parameter description information exists.
// Set the xmlType using the parameter description
// information. (an xmlType=null causes the
// serialize method to search for a compatible xmlType)
Class javaType = value == null ? null: value.getClass();
QName xmlType = null;
// we'll send a null unless our description tells us
// that we may be omitted
Boolean sendNull = Boolean.TRUE;
if (paramDesc != null) {
if (javaType == null) {
javaType = paramDesc.getJavaType() != null ?
paramDesc.getJavaType(): javaType;
} else if (!(javaType.equals(paramDesc.getJavaType()))) {
Class clazz = JavaUtils.getPrimitiveClass(javaType);
if(clazz == null || !clazz.equals(paramDesc.getJavaType())) {
if (!(javaType.equals(
JavaUtils.getHolderValueType(paramDesc.getJavaType())))) {
// This must (assumedly) be a polymorphic type - in ALL
// such cases, we must send an xsi:type attribute.
wantXSIType = Boolean.TRUE;
}
}
}
xmlType = paramDesc.getTypeQName();
QName itemQName = paramDesc.getItemQName();
if (itemQName == null) {
MessageContext mc = context.getMessageContext();
if (mc != null && mc.getOperation() != null && mc.getOperation().getStyle() == Style.DOCUMENT) {
itemQName = Constants.QNAME_LITERAL_ITEM;
}
}
context.setItemQName(itemQName);
QName itemType = paramDesc.getItemType();
context.setItemType(itemType);
// don't send anything if we're able to be omitted,
// although we'll prefer to send xsi:nill if possible
if (paramDesc.isOmittable() && !paramDesc.isNillable())
sendNull = Boolean.FALSE;
}
context.serialize(getQName(), // element qname
null, // no extra attrs
value, // value
xmlType, // java/xml type
sendNull, wantXSIType);
}
private void writeObject(ObjectOutputStream out)
throws IOException {
if (getQName() == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeObject(getQName().getNamespaceURI());
out.writeObject(getQName().getLocalPart());
}
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
if (in.readBoolean()) {
setQName(new QName((String)in.readObject(),
(String)in.readObject()));
}
in.defaultReadObject();
}
protected void outputImpl(SerializationContext context) throws Exception {
serialize(context);
}
public String getValue() {
return getValueDOM();
}
/**
* @see javax.xml.soap.SOAPElement#addTextNode(java.lang.String)
*/
public SOAPElement addTextNode(String s) throws SOAPException {
value = s;
return super.addTextNode(s);
}
/**
* @see javax.xml.soap.Node#setValue(java.lang.String)
*/
public void setValue(String value) {
this.value = value;
super.setValue(value);
}
}