Author: jochen
Date: Mon Sep 11 04:28:03 2006
New Revision: 442177

URL: http://svn.apache.org/viewvc?view=rev&rev=442177
Log:
Added the "enabledForExceptions" property.

Added:
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcInvocationException.java
Modified:
    
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java
    
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java
    
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/XmlRpcException.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcHttpRequestConfigImpl.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcStreamRequestConfig.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/XmlRpcResponseParser.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/XmlRpcWriter.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcHttpServerConfig.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServerConfigImpl.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcStreamServer.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ConnectionServer.java
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServletServer.java
    webservices/xmlrpc/trunk/src/changes/changes.xml
    webservices/xmlrpc/trunk/src/site/apt/advanced.apt
    webservices/xmlrpc/trunk/src/site/apt/client.apt
    webservices/xmlrpc/trunk/src/site/apt/extensions.apt
    webservices/xmlrpc/trunk/src/site/apt/server.apt
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java

Modified: 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java
 (original)
+++ 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java
 Mon Sep 11 04:28:03 2006
@@ -87,13 +87,11 @@
         Object result;
                try {
                        result = server.execute(pRequest);
+        } catch (XmlRpcException t) {
+            throw t;
                } catch (Throwable t) {
-                       if (t instanceof XmlRpcClientException) {
-                               throw (XmlRpcClientException) t;
-                       } else {
-                               throw new XmlRpcClientException("Failed to 
invoke method " + pRequest.getMethodName()
-                                                                               
                + ": " + t.getMessage(), t);
-                       }
+                   throw new XmlRpcClientException("Failed to invoke method " 
+ pRequest.getMethodName()
+                           + ": " + t.getMessage(), t);
                }
                if (!config.isEnabledForExtensions()) {
                        if (isExtensionType(result)) {

Modified: 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java
 (original)
+++ 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java
 Mon Sep 11 04:28:03 2006
@@ -172,7 +172,7 @@
                try {
                        xp = new XmlRpcResponseParser(pConfig, 
getClient().getTypeFactory());
                        xr.setContentHandler(xp);
-                       xr.parse(isource);
+            xr.parse(isource);
                } catch (SAXException e) {
                        throw new XmlRpcClientException("Failed to parse 
servers response: " + e.getMessage(), e);
                } catch (IOException e) {
@@ -180,8 +180,17 @@
                }
                if (xp.isSuccess()) {
                        return xp.getResult();
-               } else {
-                       throw new XmlRpcException(xp.getErrorCode(), 
xp.getErrorMessage());
                }
+               Throwable t = xp.getErrorCause();
+        if (t == null) {
+            throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage());
+        }
+        if (t instanceof XmlRpcException) {
+            throw (XmlRpcException) t;
+        }
+        if (t instanceof RuntimeException) {
+            throw (RuntimeException) t;
+        }
+        throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage(), t);
        }
 }

Modified: 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java
 (original)
+++ 
webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java
 Mon Sep 11 04:28:03 2006
@@ -18,11 +18,13 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
 
 import org.apache.xmlrpc.client.XmlRpcClient;
 import org.apache.xmlrpc.common.TypeConverter;
 import org.apache.xmlrpc.common.TypeConverterFactory;
 import org.apache.xmlrpc.common.TypeConverterFactoryImpl;
+import org.apache.xmlrpc.common.XmlRpcInvocationException;
 
 
 /**
@@ -101,7 +103,23 @@
                     return pMethod.invoke(pProxy, pArgs);
                 }
                 String methodName = pClass.getName() + "." + pMethod.getName();
-                Object result = client.execute(methodName, pArgs);
+                Object result;
+                try {
+                    result = client.execute(methodName, pArgs);
+                } catch (XmlRpcInvocationException e) {
+                    Throwable t = e.linkedException;
+                    if (t instanceof RuntimeException) {
+                        throw t;
+                    }
+                    Class[] exceptionTypes = pMethod.getExceptionTypes();
+                    for (int i = 0;  i < exceptionTypes.length;  i++) {
+                        Class c = exceptionTypes[i];
+                        if (c.isAssignableFrom(t.getClass())) {
+                            throw t;
+                        }
+                    }
+                    throw new UndeclaredThrowableException(t);
+                }
                 TypeConverter typeConverter = 
typeConverterFactory.getTypeConverter(pMethod.getReturnType());
                 return typeConverter.convert(result);
             }

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/XmlRpcException.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/XmlRpcException.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/XmlRpcException.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/XmlRpcException.java
 Mon Sep 11 04:28:03 2006
@@ -93,4 +93,8 @@
                        linkedException.printStackTrace(pWriter);
                }
        }
+
+       public Throwable getCause() {
+           return linkedException;
+    }
 }

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcHttpRequestConfigImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcHttpRequestConfigImpl.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcHttpRequestConfigImpl.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcHttpRequestConfigImpl.java
 Mon Sep 11 04:28:03 2006
@@ -28,6 +28,7 @@
        private String basicPassword;
     private int    connectionTimeout = 0;
     private int    replyTimeout = 0;
+    private boolean enabledForExceptions;
     
        /** Sets, whether gzip compression is being used for
         * transmitting the request.
@@ -97,4 +98,16 @@
         return replyTimeout;
     }
 
+    /** Sets, whether the response should contain a "faultCause" element
+     * in case of errors. The "faultCause" is an exception, which the
+     * server has trapped and written into a byte stream as a serializable
+     * object.
+     */
+    public void setEnabledForExceptions(boolean pEnabledForExceptions) {
+        enabledForExceptions = pEnabledForExceptions;
+    }
+
+    public boolean isEnabledForExceptions() {
+        return enabledForExceptions;
+    }
 }

Added: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcInvocationException.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcInvocationException.java?view=auto&rev=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcInvocationException.java
 (added)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcInvocationException.java
 Mon Sep 11 04:28:03 2006
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1999,2005 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.xmlrpc.common;
+
+import org.apache.xmlrpc.XmlRpcException;
+
+
+/**
+ * This exception is thrown, if the server catches an exception, which
+ * is thrown by the handler.
+ */
+public class XmlRpcInvocationException extends XmlRpcException {
+    private static final long serialVersionUID = 7439737967784966169L;
+
+    /**
+     * Creates a new instance with the given error code, error message
+     * and cause.
+     */
+    public XmlRpcInvocationException(int pCode, String pMessage, Throwable 
pLinkedException) {
+        super(pCode, pMessage, pLinkedException);
+    }
+
+    /**
+     * Creates a new instance with the given error message and cause.
+     */
+    public XmlRpcInvocationException(String pMessage, Throwable 
pLinkedException) {
+        super(pMessage, pLinkedException);
+    }
+}

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcStreamRequestConfig.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcStreamRequestConfig.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcStreamRequestConfig.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcStreamRequestConfig.java
 Mon Sep 11 04:28:03 2006
@@ -36,4 +36,10 @@
         * @see #isGzipCompressing()
         */
        boolean isGzipRequesting();
+       /** Returns, whether the response should contain a "faultCause" element
+     * in case of errors. The "faultCause" is an exception, which the
+     * server has trapped and written into a byte stream as a serializable
+     * object.
+        */
+       boolean isEnabledForExceptions();
 }

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/XmlRpcResponseParser.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/XmlRpcResponseParser.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/XmlRpcResponseParser.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/XmlRpcResponseParser.java
 Mon Sep 11 04:28:03 2006
@@ -15,6 +15,8 @@
  */
 package org.apache.xmlrpc.parser;
 
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
 import java.util.Map;
 
 import javax.xml.namespace.QName;
@@ -36,6 +38,7 @@
        private boolean isSuccess;
        private int errorCode;
        private String errorMessage;
+    private Throwable errorCause;
 
        /** Creates a new instance.
         * @param pConfig The response configuration.
@@ -63,6 +66,19 @@
                                                                                
        getDocumentLocator());
                        }
                        errorMessage = (String) map.get("faultString");
+            Object exception = map.get("faultCause");
+            if (exception != null) {
+                try {
+                    byte[] bytes = (byte[]) exception;
+                    ByteArrayInputStream bais = new 
ByteArrayInputStream(bytes);
+                    ObjectInputStream ois = new ObjectInputStream(bais);
+                    errorCause = (Throwable) ois.readObject();
+                    ois.close();
+                    bais.close();
+                } catch (Throwable t) {
+                    // Ignore me
+                }
+            }
                }
        }
 
@@ -206,4 +222,9 @@
         * @return The error message.
         */
        public String getErrorMessage() { return errorMessage; }
+
+       /** If the response contained a fault, returns the (optional)
+     * exception.
+        */
+    public Throwable getErrorCause() { return errorCause; }
 }

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/XmlRpcWriter.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/XmlRpcWriter.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/XmlRpcWriter.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/XmlRpcWriter.java
 Mon Sep 11 04:28:03 2006
@@ -15,6 +15,8 @@
  */
 package org.apache.xmlrpc.serializer;
 
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -22,6 +24,7 @@
 import org.apache.xmlrpc.XmlRpcRequestConfig;
 import org.apache.xmlrpc.common.TypeFactory;
 import org.apache.xmlrpc.common.XmlRpcStreamConfig;
+import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -106,13 +109,25 @@
                handler.endDocument();
        }
 
-       /** Writes a servers error message to the output stream.
+    /** Writes a servers error message to the output stream.
+     * @param pConfig The request configuration.
+     * @param pCode The error code
+     * @param pMessage The error message
+     * @throws SAXException Writing the error message failed.
+     */
+    public void write(XmlRpcRequestConfig pConfig, int pCode, String pMessage) 
throws SAXException {
+        write(pConfig, pCode, pMessage, null);
+    }
+
+        /** Writes a servers error message to the output stream.
         * @param pConfig The request configuration.
         * @param pCode The error code
         * @param pMessage The error message
+     * @param pThrowable An exception, which is being sent to the client
         * @throws SAXException Writing the error message failed.
         */
-       public void write(XmlRpcRequestConfig pConfig, int pCode, String 
pMessage) throws SAXException {
+       public void write(XmlRpcRequestConfig pConfig, int pCode, String 
pMessage,
+            Throwable pThrowable) throws SAXException {
                handler.startDocument();
                boolean extensions = pConfig.isEnabledForExtensions();
                if (extensions) {
@@ -123,7 +138,20 @@
                Map map = new HashMap();
         map.put("faultCode", new Integer(pCode));
         map.put("faultString", pMessage == null ? "" : pMessage);
-               writeValue(map);
+        if (pThrowable != null  &&  extensions  &&  (pConfig instanceof 
XmlRpcStreamRequestConfig)  &&
+                ((XmlRpcStreamRequestConfig) 
pConfig).isEnabledForExceptions()) {
+            try {
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(baos);
+                oos.writeObject(pThrowable);
+                oos.close();
+                baos.close();
+                map.put("faultCause", baos.toByteArray());
+            } catch (Throwable t) {
+                // Ignore me
+            }
+        }
+        writeValue(map);
                handler.endElement("", "fault", "fault");
                handler.endElement("", "methodResponse", "methodResponse");
                if (extensions) {

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java
 Mon Sep 11 04:28:03 2006
@@ -23,6 +23,7 @@
 import org.apache.xmlrpc.XmlRpcRequest;
 import org.apache.xmlrpc.common.TypeConverter;
 import org.apache.xmlrpc.common.TypeConverterFactory;
+import org.apache.xmlrpc.common.XmlRpcInvocationException;
 import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
 import org.apache.xmlrpc.metadata.Util;
 import 
org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping.AuthenticationHandler;
@@ -119,7 +120,7 @@
                                          + clazz.getName(), e);
            } catch (InvocationTargetException e) {
                Throwable t = e.getTargetException();
-               throw new XmlRpcException("Failed to invoke method "
+               throw new XmlRpcInvocationException("Failed to invoke method "
                                          + pMethod.getName() + " in class "
                                          + clazz.getName() + ": "
                                          + t.getMessage(), t);

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcHttpServerConfig.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcHttpServerConfig.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcHttpServerConfig.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcHttpServerConfig.java
 Mon Sep 11 04:28:03 2006
@@ -24,4 +24,9 @@
         * @return True, if keepalive is enabled, false otherwise.
         */
        boolean isKeepAliveEnabled();
+
+    /** Returns, whether the server may create a "faultCause" element in an 
error
+     * response. Note, that this may be a security issue!
+     */
+    boolean isEnabledForExceptions();
 }

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServerConfigImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServerConfigImpl.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServerConfigImpl.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServerConfigImpl.java
 Mon Sep 11 04:28:03 2006
@@ -23,6 +23,7 @@
 public class XmlRpcServerConfigImpl extends XmlRpcConfigImpl
                implements XmlRpcServerConfig, XmlRpcHttpServerConfig {
        private boolean isKeepAliveEnabled;
+    private boolean isEnabledForExceptions;
 
        /** Sets, whether HTTP keepalive is enabled for this server.
         * @param pKeepAliveEnabled True, if keepalive is enabled. False 
otherwise.
@@ -32,4 +33,13 @@
        }
 
        public boolean isKeepAliveEnabled() { return isKeepAliveEnabled; }
+
+    /** Sets, whether the server may create a "faultCause" element in an error
+     * response. Note, that this may be a security issue!
+     */
+    public void setEnabledForExceptions(boolean pEnabledForExceptions) {
+        isEnabledForExceptions = pEnabledForExceptions;
+    }
+
+    public boolean isEnabledForExceptions() { return isEnabledForExceptions; }
 }

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcStreamServer.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcStreamServer.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcStreamServer.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcStreamServer.java
 Mon Sep 11 04:28:03 2006
@@ -92,20 +92,29 @@
                }
        }
 
-       protected void writeError(XmlRpcStreamRequestConfig pConfig, 
OutputStream pStream,
+       /**
+     * This method allows to convert the error into another error. For 
example, this
+     * may be an error, which could be deserialized by the client.
+        */
+    protected Throwable convertThrowable(Throwable pError) {
+        return pError;
+    }
+
+    protected void writeError(XmlRpcStreamRequestConfig pConfig, OutputStream 
pStream,
                                                          Throwable pError)
                        throws XmlRpcException {
-               final int code;
+        final Throwable error = convertThrowable(pError);
+        final int code;
                final String message;
-               if (pError instanceof XmlRpcException) {
-                       XmlRpcException ex = (XmlRpcException) pError;
+               if (error instanceof XmlRpcException) {
+                       XmlRpcException ex = (XmlRpcException) error;
                        code = ex.code;
                } else {
                        code = 0;
                }
-               message = pError.getMessage();
+               message = error.getMessage();
                try {
-                       getXmlRpcWriter(pConfig, pStream).write(pConfig, code, 
message);
+                       getXmlRpcWriter(pConfig, pStream).write(pConfig, code, 
message, error);
                } catch (SAXException e) {
                        throw new XmlRpcException("Failed to write XML-RPC 
response: " + e.getMessage(), e);
                }

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/Connection.java
 Mon Sep 11 04:28:03 2006
@@ -121,6 +121,7 @@
         requestData.setBasicEncoding(serverConfig.getBasicEncoding());
         
requestData.setContentLengthOptional(serverConfig.isContentLengthOptional());
         
requestData.setEnabledForExtensions(serverConfig.isEnabledForExtensions());
+        
requestData.setEnabledForExceptions(serverConfig.isEnabledForExceptions());
 
         // reset user authentication
         String line = readLine();
@@ -293,11 +294,13 @@
             output.write(serverName);
             output.write(conclose);
             output.write(ctype);
-            if (pContentLength != -1) {
+            if (pContentLength == -1) {
+                output.write(newline);
+            } else {
                 output.write(clength);
                 output.write(toHTTPBytes(Integer.toString(pContentLength)));
+                output.write(doubleNewline);
             }
-            output.write(doubleNewline);
         }
     }
 

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ConnectionServer.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ConnectionServer.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ConnectionServer.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/ConnectionServer.java
 Mon Sep 11 04:28:03 2006
@@ -16,7 +16,6 @@
 package org.apache.xmlrpc.webserver;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 
 import org.apache.xmlrpc.XmlRpcException;

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServletServer.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServletServer.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServletServer.java
 (original)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServletServer.java
 Mon Sep 11 04:28:03 2006
@@ -80,6 +80,7 @@
                
result.setGzipCompressing(HttpUtil.isUsingGzipEncoding(pRequest.getHeader("Content-Encoding")));
                
result.setGzipRequesting(HttpUtil.isUsingGzipEncoding(pRequest.getHeaders("Accept-Encoding")));
                result.setEncoding(pRequest.getCharacterEncoding());
+        result.setEnabledForExceptions(serverConfig.isEnabledForExceptions());
                HttpUtil.parseAuthorization(result, 
pRequest.getHeader("Authorization"));
                return result;
        }

Modified: webservices/xmlrpc/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/changes/changes.xml?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- webservices/xmlrpc/trunk/src/changes/changes.xml (original)
+++ webservices/xmlrpc/trunk/src/changes/changes.xml Mon Sep 11 04:28:03 2006
@@ -3,6 +3,11 @@
     <title>Changes in Apache XML-RPC</title>
   </properties>
   <body>
+    <release version="3.1-SNAPSHOT" date="Not yet released">
+      <action dev="jochen" type="add">
+        Introduced the "enabledForExceptions" property.
+      </action>
+    </release>
     <release version="3.0.1-SNAPSHOT" date="Not yet released">
       <action dev="jochen" type="fix">
         Make the HttpClient creation in XmlRpcCommonsTransport and the

Modified: webservices/xmlrpc/trunk/src/site/apt/advanced.apt
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/site/apt/advanced.apt?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- webservices/xmlrpc/trunk/src/site/apt/advanced.apt (original)
+++ webservices/xmlrpc/trunk/src/site/apt/advanced.apt Mon Sep 11 04:28:03 2006
@@ -82,6 +82,14 @@
   XmlRpcException, then you'll need to catch the XmlRpcException.
   Otherwise, it's UndeclaredThrowableException.
 
+  It is recommended to use the property enabledForExceptions. If this property
+  is set, then the server will attempt to convert the exception into a byte
+  array, which is transmitted to the client. The client will be able to
+  convert the byte array back into an exception and throw that, as if it
+  came right out of the client. Note, that this approach may cause security
+  and privacy issues, because the serialized exception may, in theory, contain
+  arbitrary objects.
+
 * Cookie handling
 
   Cookie has not yet been generalized. In other words, it depends on the

Modified: webservices/xmlrpc/trunk/src/site/apt/client.apt
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/site/apt/client.apt?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- webservices/xmlrpc/trunk/src/site/apt/client.apt (original)
+++ webservices/xmlrpc/trunk/src/site/apt/client.apt Mon Sep 11 04:28:03 2006
@@ -146,6 +146,12 @@
 |                       | only available, if the property                   |
 |                       | enabledForExtensions is set was well.             |
 *-----------------------+---------------------------------------------------+
+| enabledForExceptions  | Whether the client should request, that the       |
+|                       | server returns exceptions as serializable objects.|
+|                       | If the server does, then the client will          |
+|                       | deserialize such exceptions and throw them, as    |
+|                       | if they had been cause within the clients code.   |
+*-----------------------+---------------------------------------------------+
 | enabledForExtensions  | Whether the vendor extensions of Apache XML-RPC   |
 |                       | should be enabled. By default, Apache XML-RPC is  |
 |                       | strictly compliant to the XML-RPC specification.  |

Modified: webservices/xmlrpc/trunk/src/site/apt/extensions.apt
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/site/apt/extensions.apt?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- webservices/xmlrpc/trunk/src/site/apt/extensions.apt (original)
+++ webservices/xmlrpc/trunk/src/site/apt/extensions.apt Mon Sep 11 04:28:03 
2006
@@ -128,4 +128,9 @@
 ----------------------------------------------------------------------------
   <i8 xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions";>78934</i8>
 ----------------------------------------------------------------------------
-  
\ No newline at end of file
+
+Exception Handling
+
+  If the server property "enabledForExceptions" is turned on, then the server
+  will convert exceptions into a byte array and send them to the client within
+  a "faultCause" message.

Modified: webservices/xmlrpc/trunk/src/site/apt/server.apt
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/site/apt/server.apt?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- webservices/xmlrpc/trunk/src/site/apt/server.apt (original)
+++ webservices/xmlrpc/trunk/src/site/apt/server.apt Mon Sep 11 04:28:03 2006
@@ -90,6 +90,15 @@
 *-----------------------+---------------------------------------------------+
 | Property Name         | Description                                       |
 *-----------------------+---------------------------------------------------+
+| enabledForExceptions  | If the server catches an exception, and this      |
+|                       | property is set, then the server will convert     |
+|                       | the exception into a byte array (by using an      |
+|                       | ObjectOutputStream) and return the exception to   |
+|                       | the client. Note, that this may have privacy      |
+|                       | or even security implications, because Exceptions |
+|                       | may contain arbitrary Java objects, which you     |
+|                       | possibly do not want to be sent to the client.    |
+*-----------------------+---------------------------------------------------+
 | enabledForExtensions  | Whether the vendor extensions of Apache XML-RPC   |
 |                       | should be enabled. By default, Apache XML-RPC is  |
 |                       | strictly compliant to the XML-RPC specification.  |

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java
 Mon Sep 11 04:28:03 2006
@@ -32,6 +32,7 @@
 import org.apache.xmlrpc.XmlRpcException;
 import org.apache.xmlrpc.client.XmlRpcClient;
 import org.apache.xmlrpc.common.XmlRpcExtensionException;
+import org.apache.xmlrpc.common.XmlRpcInvocationException;
 import org.apache.xmlrpc.server.XmlRpcHandlerMapping;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -107,6 +108,12 @@
                 * @return The argument, concatenated with itself.
                 */
                public String stringParam(String pArg) { return pArg+pArg; }
+        /**
+         * Throws a NullPointerException.
+         */
+        public Object throwNPE() {
+            throw new NullPointerException();
+        }
                /** Returns the argument, concatenated with itself.
                 * @param pArg The argument being concatenated.
                 * @return The argument, concatenated with itself.
@@ -884,5 +891,27 @@
         assertEquals(cal2.getTime(), result);
         result = client.execute(getConfig(pProvider), methodName, params);
         assertEquals(cal2.getTime(), result);
+    }
+
+    /**
+     * Tests, whether a NullPointerException, thrown by the server, can be
+     * trapped by the client.
+     */
+    public void testCatchNPE() throws Exception {
+        for (int i = 0;  i < providers.length;  i++) {
+            testCatchNPE(providers[i]);
+        }
+    }
+
+    private void testCatchNPE(ClientProvider pProvider) throws Exception {
+        final XmlRpcClient client = pProvider.getClient();
+        final String methodName = "Remote.throwNPE";
+        try {
+            client.execute(getExConfig(pProvider), methodName, (Object[]) 
null); 
+        } catch (XmlRpcInvocationException e) {
+            if (!(e.getCause() instanceof NullPointerException)) {
+                throw e;
+            }
+        }
     }
 }

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java
 Mon Sep 11 04:28:03 2006
@@ -21,6 +21,7 @@
 import org.apache.xmlrpc.client.XmlRpcClient;
 import org.apache.xmlrpc.client.util.ClientFactory;
 import org.apache.xmlrpc.server.XmlRpcHandlerMapping;
+import org.xml.sax.SAXException;
 
 
 /** Test case for the [EMAIL PROTECTED] ClientFactory}.
@@ -33,6 +34,11 @@
         /** Returns the sum of the given integers.
          */
         public int add(int pNum1, int pNum2);
+
+        /**
+         * Throws a SAXException.
+         */
+        public Object parse(String pMessage) throws SAXException;
     }
 
     /** Implementation of [EMAIL PROTECTED] DynamicProxyTest.Adder}, which is 
used by
@@ -42,6 +48,9 @@
         public int add(int pNum1, int pNum2) {
             return pNum1 + pNum2;
         }
+        public Object parse(String pMessage) throws SAXException {
+            throw new SAXException("Failed to parse message: " + pMessage);
+        }
     }
 
     protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, 
XmlRpcException {
@@ -54,6 +63,12 @@
         return new ClientFactory(client);
     }
 
+    private ClientFactory getExClientFactory(ClientProvider pProvider) throws 
Exception {
+        XmlRpcClient client = pProvider.getClient();
+        client.setConfig(getExConfig(pProvider));
+        return new ClientFactory(client);
+    }
+
     /** Tests calling the [EMAIL PROTECTED] Adder#add(int,int)} method
      * by using an object, which has been created by the
      * [EMAIL PROTECTED] ClientFactory}.
@@ -68,5 +83,24 @@
         ClientFactory factory = getClientFactory(pProvider);
         Adder adder = (Adder) factory.newInstance(Adder.class);
         assertEquals(6, adder.add(2, 4));
+    }
+
+    /** Tests trapping a SAXException.
+     */
+    public void testParseCall() throws Exception {
+        for (int i = 0;   i < providers.length;  i++) {
+            testParseCall(providers[i]);
+        }
+    }
+
+    private void testParseCall(ClientProvider pProvider) throws Exception {
+        ClientFactory factory = getExClientFactory(pProvider);
+        Adder adder = (Adder) factory.newInstance(Adder.class);
+        try {
+            adder.parse("foo");
+            fail("Expected SAXException");
+        } catch (SAXException e) {
+            // Ok
+        }
     }
 }

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/ServletWebServerProvider.java
 Mon Sep 11 04:28:03 2006
@@ -54,6 +54,7 @@
                XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) 
server.getConfig();
                serverConfig.setEnabledForExtensions(true);
                serverConfig.setContentLengthOptional(!contentLength);
+        serverConfig.setEnabledForExceptions(true);
                webServer.start();
                port = webServer.getPort();
         }

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/WebServerProvider.java
 Mon Sep 11 04:28:03 2006
@@ -58,6 +58,7 @@
                        XmlRpcServerConfigImpl serverConfig = 
(XmlRpcServerConfigImpl) server.getConfig();
                        serverConfig.setEnabledForExtensions(true);
                        serverConfig.setContentLengthOptional(!contentLength);
+            serverConfig.setEnabledForExceptions(true);
                        webServer.start();
                        isActive = true;
                }

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java?view=diff&rev=442177&r1=442176&r2=442177
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java
 Mon Sep 11 04:28:03 2006
@@ -52,6 +52,7 @@
     protected XmlRpcClientConfig getExConfig(ClientProvider pProvider) throws 
Exception {
         XmlRpcClientConfigImpl config = getConfig(pProvider);
         config.setEnabledForExtensions(true);
+        config.setEnabledForExceptions(true);
         return config;
     }
 


Reply via email to