gdaniels    02/04/22 20:54:26

  Modified:    java/src/org/apache/axis Handler.java MessageContext.java
               java/src/org/apache/axis/client Call.java
               java/src/org/apache/axis/encoding
                        DeserializationContextImpl.java
                        DeserializerImpl.java
               java/src/org/apache/axis/handlers BasicHandler.java
               java/src/org/apache/axis/message BodyBuilder.java
                        RPCElement.java RPCHandler.java
               java/src/org/apache/axis/transport/local LocalSender.java
               java/test/encoding TestArrayListConversions.java
                        TestAttributes.java
  Log:
  * Speed up OperationDesc dispatch a bit - get the possible overloads
    only a single time, in BodyBuilder, then store them in the RPCElement.
  
  * Add getUnderstoodHeaders() method to Handler, with default noop
    implementation in BasicHandler.  This is to be used for "up-front"
    MU checking later, but I wanted to get it in the interface for
    beta-2 so people get used to seeing it.
  
  * Couple of little bulletproofing-type bug fixes
  
  * Housecleaning, remove dead code, fix javadoc, etc.
  
  Revision  Changes    Path
  1.26      +8 -0      xml-axis/java/src/org/apache/axis/Handler.java
  
  Index: Handler.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/Handler.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Handler.java      15 Mar 2002 05:07:10 -0000      1.25
  +++ Handler.java      23 Apr 2002 03:54:25 -0000      1.26
  @@ -61,6 +61,7 @@
   import javax.xml.rpc.namespace.QName;
   import java.io.Serializable;
   import java.util.Hashtable;
  +import java.util.List;
   
   /**
    *
  @@ -99,6 +100,13 @@
        * Can this Handler process this QName?
        */
       public boolean canHandleBlock(QName qname);
  +
  +    /**
  +     * Return a list of QNames which this Handler understands.  By returning
  +     * a particular QName here, we are committing to fulfilling any contracts
  +     * defined in the specification of the SOAP header with that QName.
  +     */
  +    public List getUnderstoodHeaders();
   
       /**
        * Add the given option (name/value) to this handler's bag of options
  
  
  
  1.89      +22 -4     xml-axis/java/src/org/apache/axis/MessageContext.java
  
  Index: MessageContext.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/MessageContext.java,v
  retrieving revision 1.88
  retrieving revision 1.89
  diff -u -r1.88 -r1.89
  --- MessageContext.java       15 Apr 2002 02:35:57 -0000      1.88
  +++ MessageContext.java       23 Apr 2002 03:54:25 -0000      1.89
  @@ -192,10 +192,14 @@
       {
           currentOperation = operation;
       }
  -    public OperationDesc getOperationByQName(QName qname)
  +
  +    public OperationDesc [] getPossibleOperationsByQName(QName qname)
       {
  -        if (currentOperation != null)
  -            return currentOperation;
  +        if (currentOperation != null) {
  +            return new OperationDesc [] { currentOperation };
  +        }
  +
  +        OperationDesc [] possibleOperations = null;
   
           if (serviceHandler == null) {
               try {
  @@ -218,9 +222,23 @@
           ServiceDesc desc = serviceHandler.getInitializedServiceDesc(this);
   
           if (desc != null) {
  -            currentOperation = desc.getOperationByElementQName(qname);
  +            possibleOperations = desc.getOperationsByQName(qname);
               setOperationStyle(desc.getStyle());
           }
  +
  +        return possibleOperations;
  +    }
  +
  +    public OperationDesc getOperationByQName(QName qname)
  +    {
  +        if (currentOperation != null)
  +            return currentOperation;
  +
  +        OperationDesc [] possibleOperations = getPossibleOperationsByQName(qname);
  +        if (possibleOperations != null && possibleOperations.length > 0) {
  +            currentOperation = possibleOperations[0];
  +        }
  +
           return currentOperation;
       }
   
  
  
  
  1.116     +34 -41    xml-axis/java/src/org/apache/axis/client/Call.java
  
  Index: Call.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/client/Call.java,v
  retrieving revision 1.115
  retrieving revision 1.116
  diff -u -r1.115 -r1.116
  --- Call.java 12 Apr 2002 22:36:53 -0000      1.115
  +++ Call.java 23 Apr 2002 03:54:25 -0000      1.116
  @@ -57,20 +57,23 @@
   
   import org.apache.axis.AxisFault;
   import org.apache.axis.Constants;
  +import org.apache.axis.Handler;
  +import org.apache.axis.InternalException;
   import org.apache.axis.Message;
   import org.apache.axis.MessageContext;
  -import org.apache.axis.SOAPPart;
  -import org.apache.axis.configuration.FileProvider;
  +import org.apache.axis.description.OperationDesc;
  +import org.apache.axis.description.ParameterDesc;
  +import org.apache.axis.description.ServiceDesc;
   import org.apache.axis.encoding.DeserializerFactory;
  -import org.apache.axis.encoding.SerializerFactory;
  -import org.apache.axis.encoding.ser.BaseSerializerFactory;
  -import org.apache.axis.encoding.ser.BaseDeserializerFactory;
   import org.apache.axis.encoding.SerializationContext;
   import org.apache.axis.encoding.SerializationContextImpl;
  -import org.apache.axis.encoding.Serializer;
  -import org.apache.axis.encoding.TypeMappingRegistry;
  +import org.apache.axis.encoding.SerializerFactory;
   import org.apache.axis.encoding.TypeMapping;
  +import org.apache.axis.encoding.TypeMappingRegistry;
   import org.apache.axis.encoding.XMLType;
  +import org.apache.axis.encoding.ser.BaseDeserializerFactory;
  +import org.apache.axis.encoding.ser.BaseSerializerFactory;
  +import org.apache.axis.handlers.soap.SOAPService;
   import org.apache.axis.message.RPCElement;
   import org.apache.axis.message.RPCParam;
   import org.apache.axis.message.SOAPBodyElement;
  @@ -79,42 +82,28 @@
   import org.apache.axis.message.SOAPHeaderElement;
   import org.apache.axis.transport.http.HTTPTransport;
   import org.apache.axis.utils.JavaUtils;
  -import org.apache.axis.attachments.AttachmentPart;
  -import org.apache.axis.InternalException;
  -import org.apache.axis.Handler;
  -import org.apache.axis.handlers.soap.SOAPService;
  -import org.apache.axis.description.OperationDesc;
  -import org.apache.axis.description.ServiceDesc;
  -import org.apache.axis.description.ParameterDesc;
  -
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   
  -import javax.wsdl.Binding;
  -import javax.wsdl.BindingInput;
  -import javax.wsdl.BindingOperation;
  -import javax.wsdl.Definition;
  -import javax.wsdl.Input;
  -import javax.wsdl.Operation;
  -import javax.wsdl.Output;
  -import javax.wsdl.Part;
  -import javax.wsdl.Port;
  -import javax.wsdl.PortType;
  +import javax.wsdl.*;
   import javax.wsdl.extensions.soap.SOAPAddress;
   import javax.wsdl.extensions.soap.SOAPBody;
   import javax.wsdl.extensions.soap.SOAPOperation;
  -
  -import javax.xml.rpc.namespace.QName;
   import javax.xml.rpc.JAXRPCException;
   import javax.xml.rpc.ParameterMode;
  -import javax.xml.soap.SOAPException;
  -
  +import javax.xml.rpc.namespace.QName;
   import java.beans.IntrospectionException;
  -import java.io.PrintWriter;
   import java.io.StringWriter;
   import java.net.MalformedURLException;
   import java.net.URL;
  -import java.util.*;
  +import java.util.ArrayList;
  +import java.util.HashMap;
  +import java.util.Hashtable;
  +import java.util.Iterator;
  +import java.util.List;
  +import java.util.Map;
  +import java.util.StringTokenizer;
  +import java.util.Vector;
   
   /**
    * Axis' JAXRPC Dynamic Invocation Interface implementation of the Call
  @@ -386,9 +375,7 @@
       }
   
       /**
  -     * Gets the names of configurable properties supported by this Call object.
  -     *
  -     * @return Iterator for the property names
  +     * Configurable properties supported by this Call object.
        */
       private static ArrayList propertyNames = null;
   
  @@ -757,7 +744,6 @@
        * @return XMLType    XMLType of paramName, or null if not found.
        */
       public QName getParameterTypeByName(String paramName) {
  -        int  i ;
           QName paramQName = new QName("", paramName);
   
           return getParameterTypeByQName(paramQName);
  @@ -772,7 +758,6 @@
        * @return XMLType    XMLType of paramQName, or null if not found.
        */
       public QName getParameterTypeByQName(QName paramQName) {
  -        int i;
           ParameterDesc param = operation.getParamByQName(paramQName);
           if (param != null) {
               return param.getTypeQName();
  @@ -891,8 +876,6 @@
           Definition wsdlDefinition = service.getWSDLDefinition();
           javax.wsdl.Service wsdlService = service.getWSDLService();
   
  -        javax.wsdl.QName qn = new javax.wsdl.QName( portName.getNamespaceURI(),
  -                                                    portName.getLocalPart() );
           if ( wsdlDefinition == null )
               throw new JAXRPCException( JavaUtils.getMessage("wsdlMissing00") );
   
  @@ -1140,7 +1123,7 @@
        *
        * @param  params Array of parameters to invoke the Web Service with
        * @return Object Return value of the operation/method - or null
  -     * @throws RemoteException if there's an error
  +     * @throws java.rmi.RemoteException if there's an error
        */
       public Object invoke(Object[] params) throws java.rmi.RemoteException {
           /* First see if we're dealing with Messaging instead of RPC.        */
  @@ -1389,7 +1372,7 @@
        *
        * Note: Not part of JAX-RPC specification.
        *
  -     * @param transport the Transport object we'll use to set up
  +     * @param trans the Transport object we'll use to set up
        *                  MessageContext properties.
        */
       public void setTransport(Transport trans) {
  @@ -1524,13 +1507,23 @@
        * @param javaType is  the Java class of the data type.
        * @param xmlType the xsi:type QName of the associated XML type.
        * @param sf/df are the factories (or the Class objects of the factory).
  -     * @param force Indicates whether to add the information if already registered.
        */
       public void registerTypeMapping(Class javaType, QName xmlType,
                                       SerializerFactory sf,
                                       DeserializerFactory df) {
           registerTypeMapping(javaType, xmlType, sf, df, true);
       }
  +
  +    /**
  +     * Register type mapping information for serialization/deserialization
  +     *
  +     * Note: Not part of JAX-RPC specification.
  +     *
  +     * @param javaType is  the Java class of the data type.
  +     * @param xmlType the xsi:type QName of the associated XML type.
  +     * @param sf/df are the factories (or the Class objects of the factory).
  +     * @param force Indicates whether to add the information if already registered.
  +     */
       public void registerTypeMapping(Class javaType, QName xmlType,
                                       SerializerFactory sf,
                                       DeserializerFactory df,
  
  
  
  1.25      +1 -1      
xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java
  
  Index: DeserializationContextImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- DeserializationContextImpl.java   15 Apr 2002 02:35:57 -0000      1.24
  +++ DeserializationContextImpl.java   23 Apr 2002 03:54:25 -0000      1.25
  @@ -225,7 +225,7 @@
       public void setCurElement(MessageElement el)
       {
           curElement = el;
  -        if (curElement.getRecorder() != recorder) {
  +        if (curElement != null && curElement.getRecorder() != recorder) {
               recorder = curElement.getRecorder();
           }
       }
  
  
  
  1.8       +1 -0      xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java
  
  Index: DeserializerImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DeserializerImpl.java     25 Mar 2002 04:44:01 -0000      1.7
  +++ DeserializerImpl.java     23 Apr 2002 03:54:25 -0000      1.8
  @@ -359,6 +359,7 @@
               if (ref == null) {
                   // Nothing yet... register for later interest.
                   context.registerFixup(href, this);
  +                return;
               }
               
               if (ref instanceof MessageElement) {
  
  
  
  1.28      +10 -0     xml-axis/java/src/org/apache/axis/handlers/BasicHandler.java
  
  Index: BasicHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/handlers/BasicHandler.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- BasicHandler.java 18 Mar 2002 04:03:36 -0000      1.27
  +++ BasicHandler.java 23 Apr 2002 03:54:25 -0000      1.28
  @@ -69,6 +69,7 @@
   import javax.xml.rpc.namespace.QName;
   import java.util.Enumeration;
   import java.util.Hashtable;
  +import java.util.List;
   
   /** <code>BasicHandler</code> is a utility class which implements simple
    * property setting/getting behavior, and stubs out a lot of the Handler
  @@ -186,5 +187,14 @@
   
       public void generateWSDL(MessageContext msgContext) throws AxisFault
       {
  +    }
  +
  +    /**
  +     * Return a list of QNames which this Handler understands.  By returning
  +     * a particular QName here, we are committing to fulfilling any contracts
  +     * defined in the specification of the SOAP header with that QName.
  +     */
  +    public List getUnderstoodHeaders() {
  +        return null;
       }
   }
  
  
  
  1.26      +12 -4     xml-axis/java/src/org/apache/axis/message/BodyBuilder.java
  
  Index: BodyBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/BodyBuilder.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- BodyBuilder.java  15 Apr 2002 02:35:57 -0000      1.25
  +++ BodyBuilder.java  23 Apr 2002 03:54:26 -0000      1.26
  @@ -116,7 +116,7 @@
           if ((root != null) && root.equals("0")) isRoot = false;
   
           MessageContext msgContext = context.getMessageContext();
  -        OperationDesc operation = msgContext.getOperationByQName(qname);
  +        OperationDesc [] operations = 
msgContext.getPossibleOperationsByQName(qname);
   
           /** Now we make a plain SOAPBodyElement IF we either:
            * a) have an non-root element, or
  @@ -130,12 +130,20 @@
                                              context);
           } else if (!gotRPCElement) {
               if (isRoot &&
  -                (operation == null ||
  -                 (operation.getStyle() !=
  +                (operations == null ||
  +                 (operations[0].getStyle() !=
                     ServiceDesc.STYLE_MESSAGE))) {
                   gotRPCElement = true;
                   element = new RPCElement(namespace, localName, prefix,
  -                                         attributes, context, operation);
  +                                         attributes, context, operations);
  +// * This will be a first cut at switching streaming deserialization back on. *
  +// Only deserialize this way if there is a unique operation for this QName for
  +// now.  If there are overloads, we'll need to start recording.
  +//                if (operations != null && operations.length == 1) {
  +//                    handler = new RPCHandler((RPCElement)element, false);
  +//                    ((RPCHandler)handler).setOperation(operations[0]);
  +//                    msgContext.setOperation(operations[0]);
  +//                }
               }
           }
   
  
  
  
  1.54      +20 -31    xml-axis/java/src/org/apache/axis/message/RPCElement.java
  
  Index: RPCElement.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/RPCElement.java,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- RPCElement.java   18 Apr 2002 04:20:17 -0000      1.53
  +++ RPCElement.java   23 Apr 2002 03:54:26 -0000      1.54
  @@ -76,13 +76,14 @@
       protected Vector params = new Vector();
       protected boolean needDeser = false;
       protected boolean elementIsFirstParam = false;
  +    OperationDesc [] operations = null;
   
       public RPCElement(String namespace,
                         String localName,
                         String prefix,
                         Attributes attributes,
                         DeserializationContext context,
  -                      OperationDesc operation)
  +                      OperationDesc [] operations)
       {
           super(namespace, localName, prefix, attributes, context);
   
  @@ -93,12 +94,27 @@
           // This came from parsing XML, so we need to deserialize it sometime
           needDeser = true;
   
  -        if (operation != null) {
  +        MessageContext msgContext = context.getMessageContext();
  +
  +        // Obtain our possible operations
  +        if (operations == null) {
  +            SOAPService service    = msgContext.getService();
  +            if (service != null) {
  +                ServiceDesc serviceDesc = 
service.getInitializedServiceDesc(msgContext);
  +
  +                String lc = Utils.xmlNameToJava(name);
  +                operations = serviceDesc.getOperationsByName(lc);
  +            }
  +        }
  +
  +        if (operations != null && operations.length > 0) {
               // IF we're doc/literal... we can't count on the element name
               // being the method name.
  -            elementIsFirstParam = (operation.getStyle() ==
  +            elementIsFirstParam = (operations[0].getStyle() ==
                                      ServiceDesc.STYLE_DOCUMENT);
           }
  +
  +        this.operations = operations;
       }
   
       public RPCElement(String namespace, String methodName, Object [] args)
  @@ -136,33 +152,6 @@
           needDeser = false;
   
           MessageContext msgContext = context.getMessageContext();
  -        SOAPService service    = msgContext.getService();
  -        OperationDesc [] operations = null;
  -
  -        // Obtain our possible operations
  -        if (service != null) {
  -            ServiceDesc serviceDesc = service.getInitializedServiceDesc(msgContext);
  -
  -            // If we've got a service description now, we want to use
  -            // the matching operations in there.
  -            QName qname = new QName(namespaceURI, name);
  -            operations = serviceDesc.getOperationsByQName(qname);
  -            
  -            if (operations == null) {
  -                String lc = Utils.xmlNameToJava(name);
  -                operations = serviceDesc.getOperationsByName(lc);
  -            }
  -        }
  -
  -        // if we don't have a service that has the operations,
  -        // (i.e. for client side), the operation
  -        // may already be set in the message context.
  -        if (operations == null) {
  -            OperationDesc oper = msgContext.getOperation();
  -            if (oper != null) {
  -                operations = new OperationDesc [] { oper };
  -            }
  -        }
   
           // Figure out if we should be looking for out params or in params
           // (i.e. is this message a response?)
  @@ -189,7 +178,7 @@
                       // Set the operation so the RPCHandler can get at it
                       rpcHandler.setOperation(operation);
                       try {
  -                        if (elementIsFirstParam) {
  +                        if (elementIsFirstParam && operation.getNumInParams() > 0) {
                               context.pushElementHandler(rpcHandler);
                               context.setCurElement(null);
                           } else {
  
  
  
  1.35      +5 -1      xml-axis/java/src/org/apache/axis/message/RPCHandler.java
  
  Index: RPCHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/RPCHandler.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- RPCHandler.java   15 Apr 2002 19:37:22 -0000      1.34
  +++ RPCHandler.java   23 Apr 2002 03:54:26 -0000      1.35
  @@ -131,7 +131,11 @@
               log.debug(JavaUtils.getMessage("enter00",
                                              "RPCHandler.onStartChild()"));
           }
  -        
  +        if (!context.isDoneParsing()) {
  +            context.pushNewElement(new MessageElement(namespace,
  +            localName, prefix+":"+localName,attributes,context));
  +        }
  +
           Vector params = rpcElem.getParams();
           
           // This is a param.
  
  
  
  1.29      +0 -1      
xml-axis/java/src/org/apache/axis/transport/local/LocalSender.java
  
  Index: LocalSender.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/transport/local/LocalSender.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- LocalSender.java  22 Feb 2002 23:39:47 -0000      1.28
  +++ LocalSender.java  23 Apr 2002 03:54:26 -0000      1.29
  @@ -59,7 +59,6 @@
   import org.apache.axis.Constants;
   import org.apache.axis.Message;
   import org.apache.axis.MessageContext;
  -import org.apache.axis.configuration.FileProvider;
   import org.apache.axis.handlers.BasicHandler;
   import org.apache.axis.message.SOAPEnvelope;
   import org.apache.axis.message.SOAPFaultElement;
  
  
  
  1.18      +1 -0      xml-axis/java/test/encoding/TestArrayListConversions.java
  
  Index: TestArrayListConversions.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/encoding/TestArrayListConversions.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- TestArrayListConversions.java     15 Apr 2002 02:35:58 -0000      1.17
  +++ TestArrayListConversions.java     23 Apr 2002 03:54:26 -0000      1.18
  @@ -137,6 +137,7 @@
       public static void main(String[] args) {
           TestArrayListConversions tester = new 
TestArrayListConversions("TestArrayListConversions");
           try {
  +            tester.setUp();
               tester.testArrayConversion();
               tester.testLinkedListConversion();
               tester.testVectorConversion();
  
  
  
  1.6       +5 -16     xml-axis/java/test/encoding/TestAttributes.java
  
  Index: TestAttributes.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/encoding/TestAttributes.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- TestAttributes.java       20 Apr 2002 00:22:25 -0000      1.5
  +++ TestAttributes.java       23 Apr 2002 03:54:26 -0000      1.6
  @@ -1,37 +1,26 @@
   package test.encoding;
   
   import junit.framework.TestCase;
  +import org.apache.axis.Constants;
  +import org.apache.axis.Message;
   import org.apache.axis.MessageContext;
  -import org.apache.axis.encoding.DeserializationContext;
  -import org.apache.axis.encoding.DeserializationContextImpl;
  +import org.apache.axis.configuration.BasicServerConfig;
   import org.apache.axis.encoding.SerializationContext;
   import org.apache.axis.encoding.SerializationContextImpl;
  -import org.apache.axis.encoding.TypeMappingRegistry;
   import org.apache.axis.encoding.TypeMapping;
  -import org.apache.axis.encoding.SimpleType;
  -import org.apache.axis.encoding.ser.BeanSerializerFactory;
  +import org.apache.axis.encoding.TypeMappingRegistry;
   import org.apache.axis.encoding.ser.BeanDeserializerFactory;
  +import org.apache.axis.encoding.ser.BeanSerializerFactory;
   import org.apache.axis.encoding.ser.SimpleDeserializerFactory;
   import org.apache.axis.encoding.ser.SimpleNonPrimitiveSerializerFactory;
  -import org.apache.axis.Constants;
  -import org.apache.axis.Message;
  -import org.apache.axis.configuration.BasicServerConfig;
  -import org.apache.axis.description.TypeDesc;
  -import org.apache.axis.description.FieldDesc;
  -import org.apache.axis.description.OperationDesc;
  -import org.apache.axis.description.ServiceDesc;
  -import org.apache.axis.utils.XMLUtils;
  -import org.apache.axis.client.Call;
   import org.apache.axis.message.RPCElement;
   import org.apache.axis.message.RPCParam;
   import org.apache.axis.message.SOAPEnvelope;
   import org.apache.axis.server.AxisServer;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  -import org.xml.sax.InputSource;
   
   import javax.xml.rpc.namespace.QName;
  -import java.io.StringReader;
   import java.io.StringWriter;
   import java.io.Writer;
   import java.util.Vector;
  
  
  


Reply via email to