Commits

Bob Bergman committed c4e884c

Fixes and improves testing for:

* StaticResourcesFilter: content-type fix
* AsbtractPageServlet: run in-process
* Port MyAdminServlet to use AbstractPageServlet

Change-Id: Id2fdbabf83705cead24df0717b9aecf954412d8d

  • Participants
  • Parent commits ea949d4

Comments (0)

Files changed (10)

File plugin/src/main/java/com/atlassian/labs/remoteapps/plugin/iframe/StaticResourcesFilter.java

             return;
         }
 
+        res.setContentType(entry.getContentType());
+        res.setHeader("ETag", entry.getEtag());
+        res.setHeader("Vary", "Accept-Encoding");
+        setCacheControl(res, entry.getTTLSeconds());
+        res.setHeader("Connection", "keep-alive");
+
         String previousToken = req.getHeader("If-None-Match");
         if (previousToken != null && previousToken.equals(entry.getEtag()))
         {
             sos.close();
         }
 
-        res.setContentType(entry.getContentType());
-        res.setHeader("ETag", entry.getEtag());
-        res.setHeader("Vary", "Accept-Encoding");
-        setCacheControl(res, entry.getTTLSeconds());
-        res.setHeader("Connection", "keep-alive");
-
         if (devMode)
         {
             cache.remove(localPath);

File servlet-kit/src/main/java/com/atlassian/labs/remoteapps/kit/servlet/AbstractPageServlet.java

 
     protected List<String> getAppStylesheetUrls()
     {
-        return getAppResourcePaths(AppStylesheets.class, "stylesheet", "css");
+        return getAppResourceUrls(AppStylesheets.class, "stylesheet", "css");
     }
 
     protected List<String> getAppScriptUrls()
     {
-        return getAppResourcePaths(AppScripts.class, "script", "js");
+        return getAppResourceUrls(AppScripts.class, "script", "js");
     }
 
     private String getViewPath(String view)
     }
 
     // scans AppStylesheets and AppScripts annotations to build a list of resource paths
-    private List<String> getAppResourcePaths(Class<? extends Annotation> type, String typeName, String typeExt)
+    private List<String> getAppResourceUrls(Class<? extends Annotation> type, String typeName, String typeExt)
     {
-        ImmutableList.Builder<String> paths = ImmutableList.builder();
+        ImmutableList.Builder<String> urls = ImmutableList.builder();
         Annotation[] annotations = getClass().getAnnotations();
         boolean noMatches = true;
 
                             value = value.trim();
                             if (value.length() > 0)
                             {
-                                resolveResourcePath(value, typeName, typeExt, paths, true);
+                                resolveResourcePath(value, typeName, typeExt, urls, true);
                             }
                         }
                     }
                 }
                 else
                 {
-                    resolveResourcePath(resourceBaseName, typeName, typeExt, paths, true);
+                    resolveResourcePath(resourceBaseName, typeName, typeExt, urls, true);
                 }
             }
         }
         if (noMatches)
         {
-            resolveResourcePath(resourceBaseName, typeName, typeExt, paths, false);
+            resolveResourcePath(resourceBaseName, typeName, typeExt, urls, false);
         }
-        return paths.build();
+        return urls.build();
     }
 
     // scans resources/public for the desired resource base name, trying public/<ext> and then public/
     // while preferring minified versions (identified by either -min or .min sub-extensions) in prod mode;
     // minifcation and aggregation concerns are left to the app itself
-    private void resolveResourcePath(String name, String type, String ext, ImmutableList.Builder<String> paths, boolean warn)
+    private void resolveResourcePath(String name, String type, String ext, ImmutableList.Builder<String> urls, boolean warn)
     {
-        String path = null;
-        List<String> candidates = newArrayList();
-        if (!devMode)
+        String url = null;
+        if (name.startsWith("//") || name.startsWith("http:") || name.startsWith("https:"))
         {
-            candidates.add(getResourcePath(ext, name + ".min", ext));
-            candidates.add(getResourcePath(ext, name + "-min", ext));
-            candidates.add(getResourcePath(name + ".min", ext));
-            candidates.add(getResourcePath(name + "-min", ext));
+            url = name;
+            urls.add(url);
+            logger.debug("Added " + type + " resource with absolute url '" + url + "'");
         }
-        candidates.add(getResourcePath(ext, name, ext));
-        candidates.add(getResourcePath(name, ext));
-        for (String candidate : candidates)
+        else
         {
-            String publicPath = "public/" + candidate;
-            if (hasResource(publicPath))
+            ImmutableList.Builder<String> builder = ImmutableList.builder();
+            if (!devMode) builder.addAll(minifiedCandidates(name, ext)); // prefer min in prod mode
+            builder.add(getResourcePath(name, ext));
+            if (devMode) builder.addAll(minifiedCandidates(name, ext)); // prefer normal in dev mode, but fallback to min
+            List<String> candidates = builder.build();
+            for (String candidate : candidates)
             {
-                path = publicPath;
-                break;
+                String publicPath = "public/" + candidate;
+                if (hasResource(publicPath))
+                {
+                    url = publicPath;
+                    break;
+                }
+            }
+            if (url != null)
+            {
+                urls.add(url);
+                logger.debug("Found " + type + " resource for name '" + name + "' at path 'public/" + url + "'");
+            }
+            else if (warn)
+            {
+                logger.warn("No " + type + " resource found for name " + name + " (tried " + Joiner.on(", ").join(candidates) + ")");
             }
-        }
-        if (path != null)
-        {
-            paths.add(path);
-            logger.debug("Found " + type + " resource for name '" + name + "' at path public/" + path);
-        }
-        else if (warn)
-        {
-            logger.warn("No " + type + " found for resource " + name + " (tried " + Joiner.on(", ").join(candidates) + ")");
         }
     }
 
             return Joiner.on('/').join(Arrays.copyOfRange(parts, 0, parts.length - 1)) + '.' + parts[parts.length - 1];
         }
     }
+
+    private List<String> minifiedCandidates(String name, String ext)
+    {
+        return ImmutableList.of(
+            getResourcePath(name + ".min", ext),
+            getResourcePath(name + "-min", ext)
+        );
+    }
 }

File servlet-kit/src/main/resources/views/layout-head-aui.vm

 <link rel="stylesheet" href="$hostBaseResourceUrl/aui/$auiVersion/css/aui.css">
 <link rel="stylesheet" href="$hostBaseResourceUrl/aui/$auiVersion/css/aui-experimental.css">
-#if ($appStylesheetUrls)
-  #foreach ($url in $appStylesheetUrls)
-  <link rel="stylesheet" href="$url">
-  #end
+#foreach ($url in $appStylesheetUrls)
+<link rel="stylesheet" href="$url">
 #end
 <!--[if IE]><link rel="stylesheet" href="$hostBaseResourceUrl/aui/$auiVersion/css/aui-ie.css"><![endif]-->
 <!--[if IE 9]><link rel="stylesheet" href="$hostBaseResourceUrl/aui/$auiVersion/css/aui-ie9.css"><![endif]-->

File servlet-kit/src/main/resources/views/layout-head-default.vm

 <link rel="stylesheet" href="$hostStylesheetUrl">
-#if ($appStylesheetUrls)
-  #foreach ($url in $appStylesheetUrls)
-  <link rel="stylesheet" href="$url">
-  #end
+#foreach ($url in $appStylesheetUrls)
+<link rel="stylesheet" href="$url">
 #end

File servlet-kit/src/main/resources/views/layout-tail-aui.vm

 <script src="$hostBaseResourceUrl/aui/$auiVersion/js/aui-dependencies.js"></script>
 <script src="$hostBaseResourceUrl/aui/$auiVersion/js/aui.js"></script>
 <script src="$hostBaseResourceUrl/aui/$auiVersion/js/aui-experimental.js"></script>
-#if ($appScriptUrls)
-  #foreach ($url in $appScriptUrls)
-  <script src="$url"></script>
-  #end
+#foreach ($url in $appScriptUrls)
+<script src="$url"></script>
 #end

File servlet-kit/src/main/resources/views/layout-tail-default.vm

-#if ($appScriptUrls)
-  #foreach ($url in $appScriptUrls)
-  <script src="$url"></script>
-  #end
+#foreach ($url in $appScriptUrls)
+<script src="$url"></script>
 #end

File test-plugin/src/main/java/servlets/MyAdminServlet.java

 package servlets;
 
 import com.atlassian.labs.remoteapps.api.annotation.ServiceReference;
-import com.atlassian.labs.remoteapps.api.service.RequestContext;
 import com.atlassian.labs.remoteapps.api.service.http.HostHttpClient;
 import com.atlassian.labs.remoteapps.api.service.http.Response;
+import com.atlassian.labs.remoteapps.kit.servlet.AbstractPageServlet;
+import com.atlassian.labs.remoteapps.kit.servlet.AppScripts;
 
-import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
-import static services.HttpUtils.renderHtml;
-
 @Singleton
-public class MyAdminServlet extends HttpServlet
+@AppScripts({"jquery-1.7", "my-admin"})
+public class MyAdminServlet extends AbstractPageServlet
 {
-    private final RequestContext requestContext;
-    private final HostHttpClient httpClient;
-
-    @Inject
-    public MyAdminServlet(
-            @ServiceReference RequestContext requestContext,
-            @ServiceReference HostHttpClient httpClient)
-    {
-        this.requestContext = requestContext;
-        this.httpClient = httpClient;
-    }
+    @ServiceReference
+    private HostHttpClient httpClient;
 
     @Override
-    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+    protected void doGet(HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException
     {
         final Map<String, Object> context = new HashMap<String, Object>();
-        context.put("consumerKey", requestContext.getClientKey());
-        context.put("baseUrl", requestContext.getHostBaseUrl());
-        execHostHttpRequests(context);
-        renderHtml(resp, "test-page.mu", context);
-    }
-
-    private void execHostHttpRequests(Map<String, Object> context)
-        throws ServletException, IOException
-    {
-        Response response = httpClient.newRequest(URI.create("/rest/remoteapptest/1/user")).get().claim();
+        Response response = httpClient.newRequest("/rest/remoteapptest/1/user").get().claim();
         context.put("httpGetStatus", response.getStatusCode());
         context.put("httpGetStatusText", response.getStatusText());
         context.put("httpGetContentType", response.getContentType());
         context.put("httpGetEntity", response.getEntity());
+        render(req, res, context);
     }
-
 }

File test-plugin/src/main/resources/public/my-admin.js

+(function ($, RA) {
+  // general api testing
+  RA.getUser(function(user) {
+    $("#user").text(user.fullName);
+    $("#userId").text(user.id);
+  });
+
+  RA.getLocation(function(location) {
+    $("#location").text(location);
+  });
+
+  // basic request api testing
+  function bindXhr(xhr) {
+    $("#client-http-status").text(xhr.status);
+    $("#client-http-status-text").text(xhr.statusText);
+    $("#client-http-content-type").text(xhr.getResponseHeader("content-type"));
+    $("#client-http-response-text").text(xhr.responseText);
+  }
+  RA.request("/rest/remoteapptest/1/user", {
+    success: function (data, statusText, xhr) {
+      $("#client-http-data").text(data);
+      bindXhr(xhr);
+    },
+    error: function (xhr) {
+      bindXhr(xhr);
+    }
+  });
+}(jQuery, RA));

File test-plugin/src/main/resources/test-page.mu

-<!doctype html>
-<html>
-    <head>
-        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-        <link rel="stylesheet" type="text/css" href="{{baseUrl}}/remoteapps/all.css">
-        <script src="{{baseUrl}}/remoteapps/all.js"></script>
-        <script>RA.init();</script>
-    </head>
-    <body>
-        <h2>It worked!</h2>
-
-        <h3>General Info</h3>
-        <div>
-            Message: <span id="message">Success</span>
-        </div>
-        <div>
-            Host Consumer Key: <span id="consumerKey">{{consumerKey}}</span>
-        </div>
-        <div>
-            Current user: <span id="user"></span>
-        </div>
-        <div>
-            Current user id: <span id="userId"></span>
-        </div>
-        <div>
-            Current location: <span id="location"></span>
-        </div>
-
-        <h3>HostHttpClient Response</h3>
-        <div>
-            Status: <span id="server-http-status">{{httpGetStatus}}</span>
-        </div>
-        <div>
-            Status text: <span id="server-http-status-text">{{httpGetStatusText}}</span>
-        </div>
-        <div>
-            Content-Type: <span id="server-http-content-type">{{httpGetContentType}}</span>
-        </div>
-        <div>
-            Entity: <span id="server-http-entity">{{httpGetEntity}}</span>
-        </div>
-
-        <h3>RA.request() Response</h3>
-        <div>
-            Status: <span id="client-http-status"></span>
-        </div>
-        <div>
-            Status text: <span id="client-http-status-text"></span>
-        </div>
-        <div>
-            Content-Type: <span id="client-http-content-type"></span>
-        </div>
-        <div>
-            Response text: <span id="client-http-response-text"></span>
-        </div>
-        <div>
-            Data: <span id="client-http-data"></span>
-        </div>
-
-        <h3>Links</h3>
-        <a href="">Reload Host Page</a><br>
-        <a href="/">Host Context Root</a><br>
-        <a href="foo">App-Relative Foo</a><br>
-        <a href="myAdmin/foo">Page-Relative Foo</a><br>
-
-        <h3>Images (Resize Test)</h3>
-        <img src="public/sandcastles.jpg">
-
-        <script src="public/jquery-1.7.min.js" type="text/javascript"></script>
-        <script type="text/javascript">
-          (function () {
-            // general api testing
-            RA.getUser(function(user) {
-              $("#user").text(user.fullName);
-              $("#userId").text(user.id);
-            });
-
-            RA.getLocation(function(location) {
-              $("#location").text(location);
-            });
-
-            // basic request api testing
-            function bindXhr(xhr) {
-              $("#client-http-status").text(xhr.status);
-              $("#client-http-status-text").text(xhr.statusText);
-              $("#client-http-content-type").text(xhr.getResponseHeader("content-type"));
-              $("#client-http-response-text").text(xhr.responseText);
-            }
-            RA.request("/rest/remoteapptest/1/user", {
-              success: function (data, statusText, xhr) {
-                $("#client-http-data").text(data);
-                bindXhr(xhr);
-              },
-              error: function (xhr, statusText, errorThrown) {
-                bindXhr(xhr);
-              }
-            });
-          }());
-        </script>
-    </body>
-</html>

File test-plugin/src/main/resources/views/my-admin.vm

+<h2>It worked!</h2>
+
+<h3>General Info</h3>
+<div>Message: <span id="message">Success</span></div>
+<div>Host Consumer Key: <span id="consumerKey">$clientKey</span></div>
+<div>Current user: <span id="user"></span></div>
+<div>Current user id: <span id="userId"></span></div>
+<div>Current location: <span id="location"></span></div>
+
+<h3>HostHttpClient Response</h3>
+<div>Status: <span id="server-http-status">$httpGetStatus</span></div>
+<div>Status text: <span id="server-http-status-text">$httpGetStatusText</span></div>
+<div>Content-Type: <span id="server-http-content-type">$httpGetContentType</span></div>
+<div>Entity: <span id="server-http-entity">$httpGetEntity</span></div>
+
+<h3>RA.request() Response</h3>
+<div>Status: <span id="client-http-status"></span></div>
+<div>Status text: <span id="client-http-status-text"></span></div>
+<div>Content-Type: <span id="client-http-content-type"></span></div>
+<div>Response text: <span id="client-http-response-text"></span></div>
+<div>Data: <span id="client-http-data"></span></div>
+
+<h3>Links</h3>
+<a href="">Reload Host Page</a><br>
+<a href="/">Host Context Root</a><br>
+<a href="foo">App-Relative Foo</a><br>
+<a href="myAdmin/foo">Page-Relative Foo</a><br>
+
+<h3>Images (Resize Test)</h3>
+<img src="public/sandcastles.jpg">