You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by bi...@apache.org on 2007/11/17 19:28:05 UTC

svn commit: r595984 - in /incubator/cxf/trunk/rt: core/src/main/java/org/apache/cxf/test/ javascript/src/test/java/org/apache/cxf/javascript/ javascript/src/test/java/org/apache/cxf/javascript/service/ javascript/src/test/java/org/apache/cxf/javascript...

Author: bimargulies
Date: Sat Nov 17 10:28:03 2007
New Revision: 595984

URL: http://svn.apache.org/viewvc?rev=595984&view=rev
Log:
JavaScript clients in the browser talk to the server via the XMLHttpRequest
object. Sadly, Rhino hasn't got one. Well, now it does. This will permit
unit testing of generated clients running the full protocol. For now,
no support for local://, which would be cute but isn't necessary. We can 
run tests over TCP/HTTP. The unit testing of this is not yet complete,
but I'm getting there.



Added:
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsHttpRequestTest.java
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsXMLHttpRequest.java
    incubator/cxf/trunk/rt/javascript/src/test/resources/XMLHttpRequestTestBeans.xml
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/XMLHttpRequestTests.js
    incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/test.html
Modified:
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFSpringTest.java
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JavascriptTestUtilities.java
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsSimpleDomNode.java
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/service/DocLitWrappedTest.java
    incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/types/SerializationTest.java
    incubator/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/Messages.properties

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFSpringTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFSpringTest.java?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFSpringTest.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/test/AbstractCXFSpringTest.java Sat Nov 17 10:28:03 2007
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.test;
 
+import org.junit.Before;
 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.GenericApplicationContext;
@@ -31,14 +32,23 @@
  * doesn't inject into the test itself from the beans.
  */
 public abstract class AbstractCXFSpringTest extends AbstractCXFTest {
-    
-    private GenericApplicationContext applicationContext;
+    // subvert JUnit. We want to set up the application context ONCE, since it
+    // is likely to include a Jetty or something else that we can't get rid of.
+    private static GenericApplicationContext applicationContext;
     private DefaultResourceLoader resourceLoader;
 
     /**
      * Load up all the beans from the XML files returned by the getConfigLocations method.
+     * @throws Exception 
      */
-    protected AbstractCXFSpringTest() {
+    protected AbstractCXFSpringTest() throws Exception {
+    }
+    
+    @Before
+    public void setupBeans() throws Exception {
+        if (applicationContext != null) {
+            return;
+        }
         applicationContext = new GenericApplicationContext();
         resourceLoader = new DefaultResourceLoader(getClass().getClassLoader());
         for (String beanDefinitionPath : getConfigLocations()) {
@@ -46,6 +56,7 @@
             Resource resource = resourceLoader.getResource(beanDefinitionPath);
             reader.loadBeanDefinitions(resource);
         }
+        additionalSpringConfiguration(applicationContext);
         applicationContext.refresh();
     }
     
@@ -60,6 +71,13 @@
         return applicationContext;
     }
     
+    /**
+     * subclasses may override this.
+     * @param context
+     * @throws Exception 
+     */
+    protected abstract void additionalSpringConfiguration(GenericApplicationContext context) throws Exception;
+
     /**
      * Convenience method for the common case of retrieving a bean from the context.
      * One would expect Spring to have this. 

Modified: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JavascriptTestUtilities.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JavascriptTestUtilities.java?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JavascriptTestUtilities.java (original)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JavascriptTestUtilities.java Sat Nov 17 10:28:03 2007
@@ -29,6 +29,7 @@
 import org.junit.Assert;
 import org.mozilla.javascript.Context;
 import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
 import org.mozilla.javascript.RhinoException;
 import org.mozilla.javascript.ScriptableObject;
 import org.mozilla.javascript.tools.debugger.Main;
@@ -137,7 +138,18 @@
         return rhinoContext.evaluateString(rhinoScope, jsExpression, "<testcase>", 1, null);
     }
     
-    public Object rhinoCall(String functionName, Object ... args) {
+    /**
+     * Call a JavaScript function. Optionally, require it to throw an exception equal to
+     * a supplied object. If the exception is called for, this function will either return null
+     * or Assert.
+     * @param expectingException Exception desired, or null.
+     * @param functionName Function to call.
+     * @param args args for the function. Be sure to Javascript-ify them as appropriate.
+     * @return
+     */
+    public Object rhinoCallExpectingException(Object expectingException, 
+                                              String functionName, 
+                                              Object ... args) {
         Object fObj = rhinoScope.get(functionName, rhinoScope);
         if (!(fObj instanceof Function)) {
             throw new RuntimeException("Missing test function " + functionName);
@@ -146,12 +158,20 @@
         try {
             return function.call(rhinoContext, rhinoScope, rhinoScope, args);
         } catch (RhinoException angryRhino) {
+            if (expectingException != null && angryRhino instanceof JavaScriptException) {
+                JavaScriptException jse = (JavaScriptException)angryRhino;
+                Assert.assertEquals(jse.getValue(), expectingException);
+                return null;
+            }
             String trace = angryRhino.getScriptStackTrace();
             Assert.fail("JavaScript error: " + angryRhino.toString() + " " + trace);
         } catch (JavaScriptAssertionFailed assertion) {
             Assert.fail(assertion.getMessage());
         }
-        // we never reach here, but Eclipse doesn't know about Assert.fail.
         return null;
+    }
+    
+    public Object rhinoCall(String functionName, Object ... args) {
+        return rhinoCallExpectingException(null, functionName, args);
     }
 }

Added: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsHttpRequestTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsHttpRequestTest.java?rev=595984&view=auto
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsHttpRequestTest.java (added)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsHttpRequestTest.java Sat Nov 17 10:28:03 2007
@@ -0,0 +1,102 @@
+/**
+ * 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.cxf.javascript;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Properties;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.test.AbstractCXFSpringTest;
+import org.junit.Test;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.support.GenericApplicationContext;
+
+
+/**
+ * 
+ */
+public class JsHttpRequestTest extends AbstractCXFSpringTest {
+
+    // shadow declaration from base class.
+    private JavascriptTestUtilities testUtilities;
+    
+    public JsHttpRequestTest() throws Exception {
+        testUtilities = new JavascriptTestUtilities(getClass());
+        testUtilities.addDefaultNamespaces();
+    }
+    
+    public void additionalSpringConfiguration(GenericApplicationContext applicationContext) throws Exception {
+        // bring in some property values from a Properties file
+        PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
+        Properties properties = new Properties();
+        properties.setProperty("staticResourceURL", getStaticResourceURL());
+        cfg.setProperties(properties);
+        // now actually do the replacement
+        cfg.postProcessBeanFactory(applicationContext.getBeanFactory());        
+    }
+
+    @Override
+    protected String[] getConfigLocations() {
+        return new String[] {"classpath:XMLHttpRequestTestBeans.xml"};
+    }
+    
+    
+    
+    private
+    void setupRhino() throws Exception {
+        testUtilities.setBus(getBean(Bus.class, "cxf"));
+        testUtilities.initializeRhino();
+        JsXMLHttpRequest.register(testUtilities.getRhinoScope());
+        testUtilities.readResourceIntoRhino("/org/apache/cxf/javascript/XMLHttpRequestTests.js");
+    }
+    
+    @Test
+    public void testInvalidURI() throws Exception {
+        setupRhino();
+        testUtilities.rhinoCallExpectingException("SYNTAX_ERR", "testOpaqueURI");
+        testUtilities.rhinoCallExpectingException("SYNTAX_ERR", "testNonAbsolute");
+        testUtilities.rhinoCallExpectingException("SYNTAX_ERR", "testNonHttp");
+    }
+    
+    @Test
+    public void testSequencing() throws Exception {
+        setupRhino();
+        testUtilities.rhinoCallExpectingException("INVALID_STATE_ERR", "testSendNotOpenError");
+    }
+    
+    @Test
+    public void testSyncHttpFetch() throws Exception {
+        setupRhino();
+        Object httpObj = testUtilities.rhinoCall("testSyncHttpFetch");
+        assertNotNull(httpObj);
+        assertTrue(httpObj instanceof String);
+        String httpResponse = (String) httpObj;
+        assertTrue(httpResponse.contains("\u05e9\u05dc\u05d5\u05dd"));
+    }
+    
+    public String getStaticResourceURL() throws Exception {
+        File staticFile = new File(this.getClass().getResource("test.html").toURI());
+        staticFile = staticFile.getParentFile();
+        staticFile = staticFile.getAbsoluteFile();
+        URL furl = staticFile.toURL();
+        return furl.toString();
+    }
+}

Modified: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsSimpleDomNode.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsSimpleDomNode.java?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsSimpleDomNode.java (original)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsSimpleDomNode.java Sat Nov 17 10:28:03 2007
@@ -63,6 +63,10 @@
         return "Node";
     }
     
+    public Node getWrappedNode() {
+        return wrappedNode;
+    }
+    
     //CHECKSTYLE:OFF
     public String jsGet_localName() {
         return wrappedNode.getLocalName();       

Added: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsXMLHttpRequest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsXMLHttpRequest.java?rev=595984&view=auto
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsXMLHttpRequest.java (added)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/JsXMLHttpRequest.java Sat Nov 17 10:28:03 2007
@@ -0,0 +1,634 @@
+/**
+ * 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.cxf.javascript;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.jdom.input.DOMBuilder;
+import org.jdom.output.XMLOutputter;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.ScriptableObject;
+
+/**
+ * Implementation of XMLHttpRequest for Rhino. This might be given knowledge of
+ * CXF 'local' URLs if the author is feeling frisky.
+ */
+public class JsXMLHttpRequest extends ScriptableObject {
+    private static final Logger LOG = LogUtils.getL7dLogger(JsXMLHttpRequest.class);
+    private static Charset utf8 = Charset.forName("utf-8");
+    private static Set<String> validMethods;
+    static {
+        validMethods = new HashSet<String>();
+        validMethods.add("GET");
+        validMethods.add("POST");
+        validMethods.add("HEAD");
+        validMethods.add("PUT");
+        validMethods.add("OPTIONS");
+        validMethods.add("DELETE");
+    }
+    private static String[] invalidHeaders = {"Accept-Charset", "Accept-Encoding", "Connection",
+                                              "Content-Length", "Content-Transfer-Encoding", "Date",
+                                              "Expect", "Host", "Keep-Alive", "Referer", "TE", "Trailer",
+                                              "Transfer-Encoding", "Upgrade", "Via"};
+    private int readyState = jsGet_UNSENT();
+    private Object readyStateChangeListener;
+    private Map<String, String> requestHeaders;
+    private String storedMethod;
+    private String storedUser;
+    private String storedPassword;
+    private boolean sendFlag;
+    private URI uri;
+    private URL url;
+    private boolean storedAsync;
+    private URLConnection connection;
+    private HttpURLConnection httpConnection;
+    private Map<String, List<String>> responseHeaders;
+    private int httpResponseCode;
+    private String httpResponseText;
+    private String responseText;
+    private JsSimpleDomNode responseXml;
+    private boolean errorFlag;
+
+    public JsXMLHttpRequest() {
+        requestHeaders = new HashMap<String, String>();
+        storedMethod = null;
+    }
+    
+    public static void register(ScriptableObject scope) {
+        try {
+            ScriptableObject.defineClass(scope, JsXMLHttpRequest.class);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        } catch (InstantiationException e) {
+            throw new RuntimeException(e);
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public String getClassName() {
+        return "XMLHttpRequest";
+    }
+
+    private void notifyReadyStateChangeListener() {
+        if (readyStateChangeListener instanceof Function) {
+            LOG.info("notify " + readyState);
+            // for now, call with no args.
+            Function listenerFunction = (Function)readyStateChangeListener;
+            listenerFunction.call(Context.getCurrentContext(), getParentScope(), null, new Object[] {});
+        }
+    }
+
+    private void doOpen(String method, String urlString, boolean async, String user, String password) {
+        // ignoring auth for now.
+        LOG.info("doOpen " + method + " " + urlString + " " + Boolean.toString(async));
+
+        storedAsync = async;
+        responseText = null;
+        responseXml = null;
+        // see 4
+        method = method.toUpperCase();
+        // 1 check method
+        if (!validMethods.contains(method)) {
+            LOG.info("Invalid method syntax error.");
+            throwError("SYNTAX_ERR");
+        }
+        // 2 security check (we don't have any)
+        // 3 store method
+        storedMethod = method;
+        // 4 we already mapped it to upper case.
+        // 5 make a URL, dropping any fragment.
+        uri = null;
+        try {
+            URI tempUri = new URI(urlString);
+            if (tempUri.isOpaque()) { 
+                LOG.info("Relative URL syntax error.");
+                throwError("SYNTAX_ERR");
+            }
+            
+            uri = new URI(tempUri.getScheme(), tempUri.getUserInfo(), tempUri.getHost(), tempUri.getPort(),
+                          tempUri.getPath(), tempUri.getQuery(), null /*
+                                                                         * no
+                                                                         * fragment
+                                                                         */);
+            url = uri.toURL();
+        } catch (URISyntaxException e) {
+            LOG.log(Level.SEVERE, "URI syntax error", e);
+            throwError("SYNTAX_ERR");
+        } catch (MalformedURLException e) {
+            LOG.log(Level.SEVERE, "URI isn't URL", e);
+            throwError("SYNTAX_ERR");
+        }
+        // 6 deal with relative URLs. We don't have a base. This is a limitation
+        // on browser compatibility.
+        if (!uri.isAbsolute()) {
+            throwError("SYNTAX_ERR");
+        }
+        // 7 scheme check. Well, for now ...
+        if (!uri.getScheme().equals("http") && !uri.getScheme().equals("https")) {
+            LOG.severe("Not http " + uri.toString());
+            throwError("NOT_SUPPORTED_ERR");
+        }
+        // 8 user:password is OK for HTTP.
+        // 9, 10 user/password parsing
+        if (uri.getUserInfo() != null) {
+            String[] userAndPassword = uri.getUserInfo().split(":");
+            storedUser = userAndPassword[0];
+            if (userAndPassword.length == 2) {
+                storedPassword = userAndPassword[1];
+            }
+        }
+        // 11 cross-scripting check. We don't implement it.
+        // 12 default async. Already done.
+        // 13 check user for syntax. Not Our Job.
+        // 14 encode the user. We think we can leave this for the Http code we
+        // use below
+        // 15, 16, 17, 18 more user/password glop.
+        // 19: abort any pending activity.
+        // TODO: abort
+        // 20 cancel network activity.
+        // TODO: cancel
+        // 21 set state to OPENED and fire the listener.
+        readyState = jsGet_OPENED();
+        sendFlag = false;
+        notifyReadyStateChangeListener();
+    }
+
+    private void doSetRequestHeader(String header, String value) {
+        // 1 check state
+        if (readyState != jsGet_OPENED()) {
+            LOG.severe("setRequestHeader invalid state " + readyState);
+            throwError("INVALID_STATE_ERR");
+        }
+        // 2 check flag
+        if (sendFlag) {
+            LOG.severe("setRequestHeader send flag set.");
+            throwError("INVALID_STATE_ERR");
+        }
+        // 3 check field-name production.
+        // 4 ignore null values.
+        if (value == null) {
+            return;
+        }
+        // 5 check value
+        // 6 check for bad headers
+        for (String invalid : invalidHeaders) {
+            if (header.equalsIgnoreCase(invalid)) {
+                LOG.severe("setRequestHeader invalid header.");
+                throwError("SECURITY_ERR");
+            }
+        }
+        // 7 check for proxy
+        String headerLower = header.toLowerCase();
+        if (headerLower.startsWith("proxy-")) {
+            LOG.severe("setRequestHeader proxy header.");
+            throwError("SECURITY_ERR");
+        }
+        // 8, 9, handle appends.
+        String previous = requestHeaders.get(header);
+        if (previous != null) {
+            value = previous + ", " + value;
+        }
+        requestHeaders.put(header, value);
+    }
+
+    private void doSend(byte[] dataToSend, boolean xml) {
+        // avoid warnings on stuff we arent using yet.
+        if (storedUser != null || storedPassword != null) {
+            LOG.finest(storedUser + storedPassword);
+        }
+        // 1 check state
+        if (readyState != jsGet_OPENED()) {
+            LOG.severe("send state != OPENED.");
+            throwError("INVALID_STATE_ERR");
+        }
+        // 2 check flag
+        if (sendFlag) {
+            LOG.severe("send sendFlag set.");
+            throwError("INVALID_STATE_ERR");
+        }
+        // 3
+        sendFlag = storedAsync;
+        // 4 preprocess data. Handled on the way in here, we're called with
+        // UTF-8 bytes.
+        if (xml && !requestHeaders.containsKey("Content-Type")) {
+            requestHeaders.put("ContentType", "application/xml");
+        }
+        
+        // 5 talk to the server.
+        try {
+            connection = url.openConnection();
+        } catch (IOException e) {
+            LOG.log(Level.SEVERE, "send connection failed.", e);
+            throwError("CONNECTION_FAILED");
+        }
+        connection.setDoInput(true);
+        connection.setUseCaches(false); // Enable tunneling.
+        boolean post = false;
+        httpConnection = null;
+        if (connection instanceof HttpURLConnection) {
+            httpConnection = (HttpURLConnection)connection;
+            try {
+                httpConnection.setRequestMethod(storedMethod);
+                if ("POST".equalsIgnoreCase(storedMethod)) {
+                    httpConnection.setDoOutput(true);
+                    post = true;
+                }
+                for (Map.Entry<String, String> headerEntry : requestHeaders.entrySet()) {
+                    httpConnection.setRequestProperty(headerEntry.getKey(), headerEntry.getValue());
+                }
+            } catch (ProtocolException e) {
+                LOG.log(Level.SEVERE, "send http protocol exception.", e);
+                throwError("HTTP_PROTOCOL_ERROR");
+            }
+        }
+        
+        if (post) {
+            try {
+                OutputStream outputStream = connection.getOutputStream(); // implicitly connects?
+                if (dataToSend != null) {
+                    outputStream.write(dataToSend);
+                    outputStream.flush();
+                    outputStream.close();
+                }
+            } catch (IOException e) {
+                errorFlag = true;
+                LOG.log(Level.SEVERE, "send output error.", e);
+                throwError("NETWORK_ERR");
+            }
+        }
+        // 6
+        notifyReadyStateChangeListener();
+        
+        if (storedAsync) {
+            new Thread() {
+                public void run() {
+                    try {
+                        Context cx = Context.enter();
+                        communicate(cx);
+                    } finally {
+                        Context.exit();
+                    }
+                }
+            } .run();
+        } else {
+            communicate(Context.getCurrentContext());
+        }
+    }
+
+    private void communicate(Context cx) {
+        try {
+            InputStream is = connection.getInputStream();
+            httpResponseCode = -1;
+            // this waits, I hope, for a response.
+            responseHeaders = connection.getHeaderFields();
+            readyState = jsGet_HEADERS_RECEIVED();
+            notifyReadyStateChangeListener();
+            
+            if (httpConnection != null) {
+                httpResponseCode = httpConnection.getResponseCode();
+                httpResponseText = httpConnection.getResponseMessage();
+            }
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int read;
+            boolean notified = false;
+            while ((read = is.read(buffer)) != -1) {
+                if (!notified) {
+                    readyState = jsGet_LOADING();
+                    notifyReadyStateChangeListener();
+                }
+                baos.write(buffer, 0, read);
+            }
+            is.close();
+            // convert bytes to text.
+            String contentEncoding = connection.getContentEncoding();
+            if (contentEncoding == null || contentEncoding.length() == 0) {
+                contentEncoding = "utf-8";
+            }
+            
+            Charset contentCharset = Charset.forName(contentEncoding);
+            byte[] contentBytes = baos.toByteArray();
+            CharBuffer contentChars = 
+                contentCharset.decode(ByteBuffer.wrap(contentBytes)); // not the most efficient way.
+            responseText = contentChars.toString();
+            
+            // throw away any encoding modifier.
+            String contentType = connection.getContentType().split(";")[0];
+            
+            if ("text/xml".equals(contentType)
+                || "application/xml".equals(contentType) 
+                || contentType.endsWith("+xml")) {
+                
+                try {
+                    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+                    ByteArrayInputStream bais = new ByteArrayInputStream(contentBytes);
+                    InputSource inputSource = new InputSource(bais);
+                    inputSource.setEncoding(contentEncoding);
+                    Document xmlDoc = builder.parse(inputSource);
+                    responseXml = JsSimpleDomNode.wrapNode(getParentScope(), xmlDoc);
+                } catch (ParserConfigurationException e) {
+                    LOG.log(Level.SEVERE, "ParserConfigurationError", e);
+                    responseXml = null;
+                } catch (SAXException e) {
+                    LOG.log(Level.SEVERE, "Error parsing XML response", e);
+                    responseXml = null;
+                }
+            }
+
+            readyState = jsGet_DONE();
+            notifyReadyStateChangeListener();
+
+            if (httpConnection != null) {
+                httpConnection.disconnect();
+            }
+        } catch (IOException ioException) {
+            errorFlag = true;
+            readyState = jsGet_DONE();
+            if (!storedAsync) {
+                LOG.log(Level.SEVERE, "IO error reading response", ioException);
+                throwError("NETWORK_ERR");
+                notifyReadyStateChangeListener();
+            }
+        }
+    }
+
+    private void throwError(String errorName) {
+        LOG.info("Javascript throw: " + errorName);
+        throw new JavaScriptException(Context.javaToJS(errorName, getParentScope()), "XMLHttpRequest", 0);
+    }
+
+    private byte[] utf8Bytes(String data) {
+        ByteBuffer bb = utf8.encode(data);
+        byte[] val = new byte[bb.capacity()];
+        bb.get(val);
+        return val;
+    }
+
+    private byte[] domToUtf8(JsSimpleDomNode xml) {
+        Node node = xml.getWrappedNode();
+        Document document = (Document)node; // assume that we're given the
+        // entire document.
+        // if that's an issue, we could code something more complex.
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        org.jdom.Document jDocument = new DOMBuilder().build(document);
+        org.jdom.output.Format format = org.jdom.output.Format.getRawFormat();
+        format.setEncoding("utf-8");
+        try {
+            new XMLOutputter(format).output(jDocument, baos);
+        } catch (IOException e) {
+            LOG.log(Level.SEVERE, "impossible IO exception serializing XML", e);
+            throw new RuntimeException(e);
+        }
+        return baos.toByteArray();
+    }
+    
+    public void doAbort() {
+        // this is messy.
+    }
+    
+    public String doGetAllResponseHeaders() {
+        // 1 check state.
+        if (readyState == jsGet_UNSENT() || readyState == jsGet_OPENED()) {
+            LOG.severe("Invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        
+        // 2 check error flag
+        if (errorFlag) {
+            LOG.severe("error flag set");
+            return null;
+        }
+        
+        // 3 pile up the headers.
+        StringBuilder builder = new StringBuilder();
+        for (Map.Entry<String, List<String>> headersEntry : responseHeaders.entrySet()) {
+            builder.append(headersEntry.getKey());
+            builder.append(": ");
+            for (String value : headersEntry.getValue()) {
+                builder.append(value);
+                builder.append(", ");
+            }
+            builder.setLength(builder.length() - 2); // trim extra comma/space
+            builder.append("\r\n");
+        }
+        return builder.toString();
+    }
+    
+    public String doGetResponseHeader(String header) {
+        // 1 check state.
+        if (readyState == jsGet_UNSENT() || readyState == jsGet_OPENED()) {
+            LOG.severe("invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        
+        // 2 check header format, we don't do it.
+        
+        // 3 check error flag
+        if (errorFlag) {
+            LOG.severe("error flag");
+            return null;
+        }
+        
+        //4 -- oh, it's CASE-INSENSITIVE. Well, we do it the hard way.
+        for (Map.Entry<String, List<String>> headersEntry : responseHeaders.entrySet()) {
+            if (header.equalsIgnoreCase(headersEntry.getKey())) {
+                StringBuilder builder = new StringBuilder();
+                for (String value : headersEntry.getValue()) {
+                    builder.append(value);
+                    builder.append(", ");
+                }
+                builder.setLength(builder.length() - 2); // trim extra comma/space
+                return builder.toString();
+            }
+        }
+        return null;
+    }
+    
+    public String doGetResponseText() {
+        // 1 check state.
+        if (readyState == jsGet_UNSENT() || readyState == jsGet_OPENED()) {
+            LOG.severe("invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        
+        // 2 return what we have.
+        return responseText;
+    }
+    
+    public Object doGetResponseXML() {
+        // 1 check state.
+        if (readyState == jsGet_UNSENT() || readyState == jsGet_OPENED()) {
+            LOG.severe("invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        
+        return responseXml;
+    }
+    
+    public int doGetStatus() {
+        if (httpResponseCode == -1) {
+            LOG.severe("invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        return httpResponseCode;
+            
+    }
+    
+    public String doGetStatusText() {
+        if (httpResponseText == null) {
+            LOG.severe("invalid state");
+            throwError("INVALID_STATE_ERR");
+        }
+        return httpResponseText;
+    }
+
+    // CHECKSTYLE:OFF
+
+    public Object jsGet_onreadystatechange() {
+        return readyStateChangeListener;
+    }
+
+    public void jsSet_onreadystatechange(Object listener) {
+        readyStateChangeListener = listener;
+    }
+
+    public int jsGet_UNSENT() {
+        return 0;
+    }
+
+    public int jsGet_OPENED() {
+        return 1;
+    }
+
+    public int jsGet_HEADERS_RECEIVED() {
+        return 2;
+    }
+
+    public int jsGet_LOADING() {
+        return 3;
+    }
+
+    public int jsGet_DONE() {
+        return 4;
+    }
+
+    public int jsGet_readyState() {
+        return readyState;
+    }
+
+    public void jsFunction_open(String method, String url) {
+        doOpen(method, url, true, null, null);
+    }
+
+    public void jsFunction_open(String method, String url, boolean async) {
+        doOpen(method, url, async, null, null);
+    }
+
+    public void jsFunction_open(String method, String url, boolean async, String user) {
+        doOpen(method, url, async, user, null);
+    }
+
+    public void jsFunction_open(String method, String url, boolean async, String user, String password) {
+        doOpen(method, url, async, user, password);
+    }
+
+    public void jsFunction_setRequestHeader(String header, String value) {
+        doSetRequestHeader(header, value);
+    }
+
+    public void jsFunction_send() {
+        doSend(null, false);
+
+    }
+
+    public void jsFunction_send(String data) {
+        doSend(utf8Bytes(data), false);
+
+    }
+
+    public void jsFunction_send(JsSimpleDomNode xml) {
+        doSend(domToUtf8(xml), true);
+    }
+
+    public void jsFunction_abort() {
+        doAbort();
+    }
+
+    public String jsFunction_getAllResponseHeaders() {
+        return doGetAllResponseHeaders();
+    }
+
+    public String jsFunction_getResponseHeader(String header) {
+        return doGetResponseHeader(header);
+    }
+
+    public String jsGet_responseText() {
+        return doGetResponseText();
+    }
+
+    public Object jsGet_responseXML() {
+        return doGetResponseXML();
+    }
+
+    public int jsGet_status() {
+        return doGetStatus();
+    }
+
+    public String jsGet_statusText() {
+        return doGetStatusText();
+    }
+}

Modified: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/service/DocLitWrappedTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/service/DocLitWrappedTest.java?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/service/DocLitWrappedTest.java (original)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/service/DocLitWrappedTest.java Sat Nov 17 10:28:03 2007
@@ -59,6 +59,7 @@
 import org.junit.Test;
 import org.mozilla.javascript.Scriptable;
 import org.mozilla.javascript.ScriptableObject;
+import org.springframework.context.support.GenericApplicationContext;
 
 //@org.junit.Ignore
 public class DocLitWrappedTest extends AbstractCXFSpringTest {
@@ -78,7 +79,7 @@
     private NamespacePrefixAccumulator prefixManager;
     private DocumentBuilder documentBuilder;
 
-    public DocLitWrappedTest() {
+    public DocLitWrappedTest() throws Exception {
         testUtilities = new JavascriptTestUtilities(getClass());
         testUtilities.addDefaultNamespaces();
         xmlInputFactory = XMLInputFactory.newInstance();
@@ -204,5 +205,9 @@
         LOG.fine(serviceInfo.toString());
         LOG.fine(serviceJavascript);
         testUtilities.readStringIntoRhino(serviceJavascript, serviceInfo.getName() + ".js");
+    }
+
+    @Override
+    protected void additionalSpringConfiguration(GenericApplicationContext context) throws Exception {
     }
 }

Modified: incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/types/SerializationTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/types/SerializationTest.java?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/types/SerializationTest.java (original)
+++ incubator/cxf/trunk/rt/javascript/src/test/java/org/apache/cxf/javascript/types/SerializationTest.java Sat Nov 17 10:28:03 2007
@@ -48,6 +48,7 @@
 import org.apache.cxf.test.AbstractCXFSpringTest;
 import org.apache.cxf.wsdl.EndpointReferenceUtils;
 import org.junit.Test;
+import org.springframework.context.support.GenericApplicationContext;
 
 //@org.junit.Ignore
 public class SerializationTest extends AbstractCXFSpringTest {
@@ -60,7 +61,7 @@
     private NameManager nameManager;
     private JaxWsProxyFactoryBean clientProxyFactory;
 
-    public SerializationTest() {
+    public SerializationTest() throws Exception {
         testUtilities = new JavascriptTestUtilities(getClass());
         testUtilities.addDefaultNamespaces();
         xmlInputFactory = XMLInputFactory.newInstance();
@@ -203,5 +204,9 @@
             assertNotNull(allThatJavascript);
             testUtilities.readStringIntoRhino(allThatJavascript, schema.toString() + ".js");
         }
+    }
+
+    @Override
+    protected void additionalSpringConfiguration(GenericApplicationContext context) throws Exception {
     }
 }

Added: incubator/cxf/trunk/rt/javascript/src/test/resources/XMLHttpRequestTestBeans.xml
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/resources/XMLHttpRequestTestBeans.xml?rev=595984&view=auto
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/resources/XMLHttpRequestTestBeans.xml (added)
+++ incubator/cxf/trunk/rt/javascript/src/test/resources/XMLHttpRequestTestBeans.xml Sat Nov 17 10:28:03 2007
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:sec="http://cxf.apache.org/configuration/security"
+  xmlns:http="http://cxf.apache.org/transports/http/configuration"
+  xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+  xmlns:jaxws="http://cxf.apache.org/jaxws"
+  xsi:schemaLocation="
+           http://cxf.apache.org/jaxws                                 
+              http://cxf.apache.org/schemas/jaxws.xsd
+  		   http://cxf.apache.org/configuration/security
+  		      http://cxf.apache.org/schemas/configuration/security.xsd
+           http://cxf.apache.org/transports/http/configuration
+              http://cxf.apache.org/schemas/configuration/http-conf.xsd
+           http://cxf.apache.org/transports/http-jetty/configuration
+              http://cxf.apache.org/schemas/configuration/http-jetty.xsd
+           http://www.springframework.org/schema/beans
+              http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+              
+  <import resource="classpath:META-INF/cxf/cxf.xml" />
+  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
+  <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
+  <import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />
+              
+ <httpj:engine-factory bus="cxf">
+  <httpj:engine port="8808">
+   <httpj:handlers>
+    <bean class="org.mortbay.jetty.handler.ContextHandler">
+     <property name="contextPath" value="/" />
+     <property name="handler">
+      <bean class="org.mortbay.jetty.handler.ResourceHandler">
+       <property name="baseResource">
+        <bean class="org.mortbay.resource.FileResource">
+         <constructor-arg value="${staticResourceURL}" />
+        </bean>
+        </property>
+      </bean>
+     </property>
+    </bean>
+    <bean class="org.mortbay.jetty.handler.DefaultHandler"/>
+   </httpj:handlers>
+  </httpj:engine>
+ </httpj:engine-factory>
+ 
+ <jaxws:endpoint id="greeter-service-endpoint" 
+    implementor="org.apache.hello_world_doc_lit.GreeterImplDoc" 
+    address="http://localhost:8808/Greeter">
+ </jaxws:endpoint>
+ 
+ </beans>
\ No newline at end of file

Added: incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/XMLHttpRequestTests.js
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/XMLHttpRequestTests.js?rev=595984&view=auto
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/XMLHttpRequestTests.js (added)
+++ incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/XMLHttpRequestTests.js Sat Nov 17 10:28:03 2007
@@ -0,0 +1,62 @@
+/**
+ * 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.
+ */
+ 
+function assertionFailed(explanation)
+{
+ 	var assert = new Assert(explanation); // this will throw out in Java.
+}
+
+function testOpaqueURI()
+{
+	var r = new XMLHttpRequest();
+	if(r.readyState != r.UNSENT) {
+		assertionFailed("initial state not UNSENT");
+	}
+	r.open("GET", "uri:opaque", false);
+}
+
+function testNonAbsolute() {
+	var r = new XMLHttpRequest();
+	r.open("GET", "http:relative", false);
+}
+
+function testNonHttp() {
+	var r = new XMLHttpRequest();
+	r.open("GET", "ftp:relative", false);
+}
+
+function testSendNotOpenError() {
+	var r = new XMLHttpRequest();
+	r.send();
+}
+
+function testSyncHttpFetch() {
+	
+	var r = new XMLHttpRequest();
+	r.open("GET", "http://localhost:8808/test.html", false);
+	if (r.readyState != r.OPENED) {
+		assertionFailed("state not OPENED after OPEN");
+	}
+	r.send();
+	if (r.readyState != r.DONE) {
+		assertionFailed("state not DONE after sync send.")
+	}
+	return r.responseText;
+	
+}
\ No newline at end of file

Added: incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/test.html
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/test.html?rev=595984&view=auto
==============================================================================
--- incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/test.html (added)
+++ incubator/cxf/trunk/rt/javascript/src/test/resources/org/apache/cxf/javascript/test.html Sat Nov 17 10:28:03 2007
@@ -0,0 +1,23 @@
+<html>
+<!--
+  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.
+-->
+<body>
+Test &#x05e9;&#x05dc;&#x05d5;&#x05dd; שלום 
+</body>
+</html>
\ No newline at end of file

Modified: incubator/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/Messages.properties
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/Messages.properties?rev=595984&r1=595983&r2=595984&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/Messages.properties (original)
+++ incubator/cxf/trunk/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/Messages.properties Sat Nov 17 10:28:03 2007
@@ -22,5 +22,5 @@
 ADD_HANDLER_FAILED_MSG = Could not add cxf jetty handler to Jetty server: {0}
 REMOVE_HANDLER_FAILED_MSG = Could not remove cxf jetty handler from Jetty server: {0}
 CAN_NOT_FIND_HANDLER_MSG = Could not find the handler to remove for context url {0}
-FAILED_TO_SHUTDOWN_ENGINE_MSG = Failed to shutdown Jetty server: {0} because it is still in use
+FAILED_TO_SHUTDOWN_ENGINE_MSG = Failed to shutdown Jetty server on port {0,number,####0} because it is still in use
 UNKNOWN_CONNECTOR_MSG = Unknown connector type, can't set the socket reuseAddress flag.