private void buildComponentSourceHTML() throws IOException { StringBuilder sb = new StringBuilder(); // Sort components by classNames, so order is always the same for debugging List<ConfiguredComponent> comps = new ArrayList<ConfiguredComponent>(application.getComponents()); Collections.sort(comps); if (isDebug()) { Set<String> classNamesDone = new HashSet<String>(); for (ConfiguredComponent cc : comps) { if (!Authorizations.isConfiguredComponentAuthorized(cc, context.getRequest())) { continue; } if (!classNamesDone.contains(cc.getClassName())) { classNamesDone.add(cc.getClassName()); if (cc.getViewerComponent() != null && cc.getViewerComponent().getSources() != null) { for (File f : cc.getViewerComponent().getSources()) { String url = new ForwardResolution(ComponentActionBean.class, "source") .addParameter("app", name) .addParameter("version", version) .addParameter("className", cc.getClassName()) .addParameter("file", f.getName()) .getUrl(context.getLocale()); sb.append(" <script type=\"text/javascript\" src=\""); sb.append(HtmlUtil.encode(context.getServletContext().getContextPath() + url)); sb.append("\"></script>\n"); } } } } } else { // If not debugging, create a single script tag with all source // for all components for the application for a minimal number of HTTP requests // The ComponentActionBean supports conditional HTTP requests using // Last-Modified. // Create a hash value that will change when the classNames used // in the application change, so that a browser will not use a // previous version from cache with other contents. int hash = 0; Set<String> classNamesDone = new HashSet<String>(); for (ConfiguredComponent cc : comps) { if (!Authorizations.isConfiguredComponentAuthorized(cc, context.getRequest())) { continue; } if (!classNamesDone.contains(cc.getClassName())) { hash = hash ^ cc.getClassName().hashCode(); } else { classNamesDone.add(cc.getClassName()); } } if (user != null) { // Update component sources when roles of user change hash = hash ^ getRolesCachekey(context.getRequest()); // Update component sources when roles of configured components // may have changed hash = hash ^ (int) application.getAuthorizationsModified().getTime(); } String url = new ForwardResolution(ComponentActionBean.class, "source") .addParameter("app", name) .addParameter("version", version) .addParameter("minified", true) .addParameter("hash", hash) .getUrl(context.getLocale()); sb.append(" <script type=\"text/javascript\" src=\""); sb.append(HtmlUtil.encode(context.getServletContext().getContextPath() + url)); sb.append("\"></script>\n"); } componentSourceHTML = sb.toString(); }