package com.vaadin.server;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;

import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import junit.framework.TestCase;

import com.vaadin.DefaultDeploymentConfiguration;

public class TestAbstractApplicationServletStaticFilesLocation extends TestCase {

    VaadinServlet servlet;

    // private Method getStaticFilesLocationMethod;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        servlet = new VaadinServlet();

        // Workaround to avoid calling init and creating servlet config
        Field f = VaadinServlet.class.getDeclaredField("servletService");
        f.setAccessible(true);
        f.set(servlet, new VaadinServletService(servlet,
                new DefaultDeploymentConfiguration(servlet.getClass(),
                        new Properties())));

    }

    public void testWidgetSetLocation() throws Exception {
        String location;

        /* SERVLETS */
        // http://dummy.host:8080/contextpath/servlet
        // should return /contextpath
        location = testLocation("http://dummy.host:8080", "/contextpath",
                "/servlet", "");
        assertEquals("/contextpath", location);

        // http://dummy.host:8080/servlet
        // should return ""
        location = testLocation("http://dummy.host:8080", "", "/servlet", "");
        assertEquals("", location);

        // http://dummy.host/contextpath/servlet/extra/stuff
        // should return /contextpath
        location = testLocation("http://dummy.host", "/contextpath",
                "/servlet", "/extra/stuff");
        assertEquals("/contextpath", location);

        // http://dummy.host/context/path/servlet/extra/stuff
        // should return /context/path
        location = testLocation("http://dummy.host", "/context/path",
                "/servlet", "/extra/stuff");
        assertEquals("/context/path", location);

        /* Include requests */
        location = testIncludedLocation("http://my.portlet.server", "/user",
                "/tmpservletlocation1", "");
        assertEquals("Wrong widgetset location", "/user", location);

    }

    private String testLocation(String base, String contextPath,
            String servletPath, String pathInfo) throws Exception {

        HttpServletRequest request = createNonIncludeRequest(base, contextPath,
                servletPath, pathInfo);
        // Set request into replay mode
        replay(request);

        String location = servlet.getService().getStaticFileLocation(
                servlet.createVaadinRequest(request));
        return location;
    }

    private String testIncludedLocation(String base, String portletContextPath,
            String servletPath, String pathInfo) throws Exception {

        HttpServletRequest request = createIncludeRequest(base,
                portletContextPath, servletPath, pathInfo);
        // Set request into replay mode
        replay(request);

        String location = servlet.getService().getStaticFileLocation(
                servlet.createVaadinRequest(request));
        return location;
    }

    private HttpServletRequest createIncludeRequest(String base,
            String realContextPath, String realServletPath, String pathInfo)
            throws Exception {
        HttpServletRequest request = createRequest(base, "", "", pathInfo);
        expect(request.getAttribute("javax.servlet.include.context_path"))
                .andReturn(realContextPath).anyTimes();
        expect(request.getAttribute("javax.servlet.include.servlet_path"))
                .andReturn(realServletPath).anyTimes();

        return request;
    }

    private HttpServletRequest createNonIncludeRequest(String base,
            String realContextPath, String realServletPath, String pathInfo)
            throws Exception {
        HttpServletRequest request = createRequest(base, realContextPath,
                realServletPath, pathInfo);
        expect(request.getAttribute("javax.servlet.include.context_path"))
                .andReturn(null).anyTimes();
        expect(request.getAttribute("javax.servlet.include.servlet_path"))
                .andReturn(null).anyTimes();

        return request;
    }

    /**
     * Creates a HttpServletRequest mock using the supplied parameters.
     * 
     * @param base
     *            The base url, e.g. http://localhost:8080
     * @param contextPath
     *            The context path where the application is deployed, e.g.
     *            /mycontext
     * @param servletPath
     *            The servlet path to the servlet we are testing, e.g. /myapp
     * @param pathInfo
     *            Any text following the servlet path in the request, not
     *            including query parameters, e.g. /UIDL/
     * @return A mock HttpServletRequest object useful for testing
     * @throws MalformedURLException
     */
    private HttpServletRequest createRequest(String base, String contextPath,
            String servletPath, String pathInfo) throws MalformedURLException {
        URL url = new URL(base + contextPath + pathInfo);
        HttpServletRequest request = createMock(HttpServletRequest.class);
        expect(request.isSecure()).andReturn(
                url.getProtocol().equalsIgnoreCase("https")).anyTimes();
        expect(request.getServerName()).andReturn(url.getHost()).anyTimes();
        expect(request.getServerPort()).andReturn(url.getPort()).anyTimes();
        expect(request.getRequestURI()).andReturn(url.getPath()).anyTimes();
        expect(request.getContextPath()).andReturn(contextPath).anyTimes();
        expect(request.getPathInfo()).andReturn(pathInfo).anyTimes();
        expect(request.getServletPath()).andReturn(servletPath).anyTimes();

        return request;
    }

}

@@ -1237,32 +1237,61 @@
 / should return 
+. (relative url resolving to 
 /contextpath%0A   
@@ -1278,32 +1278,33 @@
  to /contextpath
+)
 %0A        locatio
@@ -1413,36 +1413,300 @@
 sertEquals(%22
-/contextpath
+.%22, location);%0A%0A        // http://dummy.host:8080/contextpath/servlet/%0A        // should return ./.. (relative url resolving to /contextpath)%0A        location = testLocation(%22http://dummy.host:8080%22, %22/contextpath%22,%0A                %22/servlet%22, %22/%22);%0A        assertEquals(%22./..
 %22, location)
@@ -1776,16 +1776,17 @@
 return %22
+.
 %22%0A      
@@ -1880,16 +1880,17 @@
 Equals(%22
+.
 %22, locat
@@ -1974,32 +1974,67 @@
 / should return 
+./../.. (relative url resolving to 
 /contextpath%0A   
@@ -2025,24 +2025,25 @@
 /contextpath
+)
 %0A        loc
@@ -2167,28 +2167,23 @@
 Equals(%22
-/contextpath
+./../..
 %22, locat
@@ -2276,16 +2276,51 @@
  return 
+./../.. (relative url resolving to 
 /context
@@ -2324,16 +2324,17 @@
 ext/path
+)
 %0A       
@@ -2463,29 +2463,23 @@
 Equals(%22
-/context/path
+./../..
 %22, locat
@@ -2515,32 +2515,176 @@
 uests */%0A       
+ // Include request support dropped with support for portlet1%0A        // Might reconsider when JSP integration support is implemented%0A        //
  location = test
@@ -2745,23 +2745,18 @@
         
-       
+//
  %22/tmpse
@@ -2776,32 +2776,35 @@
 1%22, %22%22);%0A       
+ //
  assertEquals(%22W

Update test to use relative paths (#6771)