Vojtech Szocs has posted comments on this change. Change subject: userportal, webadmin: branding support. ......................................................................
Patch Set 19: (11 inline comments) Thanks for addressing all of my comments, Alex. There are still some open comments, please go over them and let me know what you think. > Guys, we must start to realize the the project is more than single > technology, it is integration of multiple components and technologies. > Writing that 'files are not in place' is just like writing that some java > class, CSS or html are not in place. Maybe it's just me, I need to switch my mind-set to accept the fact that compiled GWT application isn't self-sufficient, i.e. might depend on external resources. So I get your point, Alon. .................................................... File frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/branding/BrandingManager.java Line 132: ObjectNode node = new ObjectMapper().createObjectNode(); Line 133: for (Map.Entry<String, String> entry : keyValues.entrySet()) { Line 134: node.put(entry.getKey(), entry.getValue()); Line 135: } Line 136: return node.size() > 0 ? node.toString() : null; Thanks, I'm OK with current approach, assuming client-side code (dynamic constants) always checks for presence of message object (not null). Line 137: } Line 138: Line 139: /** Line 140: * Get the root path of the branding files. .................................................... File frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/branding/BrandingTheme.java Line 113: * @param brandingRootPath The root of the path to the branding theme, Line 114: * @param brandingVersion The version to load, if the version don't match the load will fail. Line 115: * @return {@code true} if successfully loaded, {@code false} otherwise. Line 116: */ Line 117: public boolean load(final String brandingPath, final File brandingRootPath, final int brandingVersion) { I still don't understand why it's better to have arguments in load() vs. final fields set up inside constructor. BrandingTheme class is meant to load branding resources like this: - instantiate - call load() method - if successful, class contains loaded resources, store its reference somewhere Calling load() is therefore one-time operation, load() isn't supposed to be called more than once on given instance with different parameters. From class perspective, this makes brandingPath, brandingRootPath and brandingVersion conceptually immutable parameters. Also, from design perspective, It's always good to reduce class mutability (state that can be modified) if possible. (Currently, load() acts both as setter for these parameters + logic for actual load operation.) To summarize: - conceptually immutable parameters should be implemented as final fields - conceptually mutable parameters should be implemented as method parameters Long story short: I suggest to use final fields instead of method parameters in this particular case. Line 118: path = brandingPath.substring( Line 119: brandingRootPath.getAbsolutePath(). Line 120: length()); Line 121: filePath = brandingPath; Line 124: try { Line 125: propertiesFile = new FileInputStream(brandingPath Line 126: + "/" + BRANDING_PROPERTIES_NAME); //$NON-NLS-1$ Line 127: brandingProperties.load(propertiesFile); Line 128: available = brandingVersion == getVersion(); Well, I'd rather prefer following implementation: - init brandingProperties via Properties.load - modify getVersion to be private and accept Properties argument Also, some questions: - are there any callers for getVersion outside this class? - are there any callers for isAvailable outside this class? (I recommend having getters only when they are needed) Line 129: if (!available) { Line 130: log.warn("Unable to load branding theme, mismatched version: " //$NON-NLS-1$ Line 131: + getVersion() + " wanted version: " + brandingVersion); //$NON-NLS-1$ Line 132: } Line 229: new URL[] { Line 230: themeDirectory.toURI().toURL() }); Line 231: result = ResourceBundle.getBundle( Line 232: brandingProperties.getProperty(MESSAGES_KEY). Line 233: replaceAll("\\.properties", ""), //$NON-NLS-1$ //$NON-NLS-2$ > What is the problem with replaceAll? Example - branding.properties file contains: messages=my.messages.properties.whatever.properties After doing replaceAll, you would end up using "my.messages.whatever" instead of "my.messages.properties.whatever" -> you should remove ".properties" suffix only. So instead of replaceAll, you should use String.lastIndexOf and do substring to cut out the part without suffix. Line 234: locale, Line 235: urlLoader); Line 236: } catch (IOException e) { Line 237: // Unable to load messages resource bundle. .................................................... File frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/BrandingServlet.java Line 104: * @return A full absolute path for the passed in path. Line 105: */ Line 106: String getFullPath(final String path) { Line 107: String result = null; Line 108: if (path != null && ServletUtils.isSane(path)) { OK, I see your point. I guess that for the purpose of "isSane" checking, it doesn't matter if we pass only a portion of the path vs. full (real requested) path, assuming the branding root path is safe. Line 109: // Return a result relative to the branding root path. Line 110: result = brandingManager.getBrandingRootPath().getAbsolutePath() + path; Line 111: } else { Line 112: log.error("The path \"" + path + "\" is not sane"); //$NON-NLS-1$ //$NON-NLS-2$ .................................................... File frontend/webadmin/modules/frontend/src/main/resources/META-INF/resources/GwtHostPage.jsp Line 8: <meta name="gwt:property" content="locale=${requestScope['locale']}"> Line 9: <c:if test="${requestScope['brandingStyle'] != null}"> Line 10: <c:forEach items="${requestScope['brandingStyle']}" var="theme"> Line 11: <c:if test="${theme.getThemeStyleSheet(requestScope['applicationType']) != null}"> Line 12: <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/${requestScope['theme']}${theme.path}/${theme.getThemeStyleSheet(requestScope['applicationType'])}"> I guess output HTML indentation isn't that important in comparison to JSP code readability, plus in future we might consider trimming JSP whitespace anyway. Line 13: </c:if> Line 14: </c:forEach> Line 15: </c:if> Line 16: <script type="text/javascript"> .................................................... File frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/DynamicConstants.java Line 34: dictionary = null; Line 35: try { Line 36: dictionary = Dictionary.getDictionary(MESSAGES_DICTIONARY_NAME); Line 37: } catch (MissingResourceException mre) { Line 38: // Do nothing, the dictionary doesn't exist. You're right, in this case its normal for dictionary to be null. Line 39: } Line 40: } Line 41: Line 42: /** .................................................... File frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/dialog/tab/DialogTab.java Line 30: Line 31: interface Style extends CssResource { Line 32: String obrand_active(); Line 33: Line 34: String inactive(); OK, but just because downstream branding package doesn't override "inactive" style, it doesn't mean other branding package wouldn't want to override it. For me, "active" and "inactive" are conceptually closely related, so it makes sense to externalize them both for consistency, but for now I'm OK with current approach. Line 35: } Line 36: Line 37: @UiField Line 38: FocusPanel tabContainer; .................................................... File frontend/webadmin/modules/userportal-gwtp/src/main/webapp/WEB-INF/web.xml Line 1: <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Line 2: xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> Line 3: Line 4: <display-name>oVirt UserPortal UI</display-name> Line 5: <!-- Filters --> For Java source code, we should always use 4-space instead of TAB chars. For XML, I'm not sure, most XMLs contain TAB chars. (engine-code-format.xml for Eclipse affects only Java sources) I'd say both 4-space and TABs are allowed for XMLs, so it's up to you. Line 6: <filter> Line 7: <filter-name>LocaleFilter</filter-name> Line 8: <filter-class>org.ovirt.engine.core.utils.servlet.LocaleFilter</filter-class> Line 9: </filter> .................................................... File frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/MainSectionView.ui.xml Line 1 Line 2 Line 3 Line 4 Line 5 OK, then we can also delete defines.css file. .................................................... File frontend/webadmin/modules/webadmin/src/main/webapp/WEB-INF/web.xml Line 4: <display-name>oVirt WebAdmin UI</display-name> Line 5: <!-- Filters --> Line 6: <filter> Line 7: <filter-name>LocaleFilter</filter-name> Line 8: <filter-class>org.ovirt.engine.core.utils.servlet.LocaleFilter</filter-class> I forgot about this in my first review, please remove this as this should go into web-fragment.xml file. Line 9: </filter> Line 10: <filter-mapping> Line 11: <filter-name>LocaleFilter</filter-name> Line 12: <url-pattern>/webadmin/*</url-pattern> -- To view, visit http://gerrit.ovirt.org/13181 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: comment Gerrit-Change-Id: I4a8a426ce7d688d33c5ae2b70632c836843106b2 Gerrit-PatchSet: 19 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Alexander Wels <aw...@redhat.com> Gerrit-Reviewer: Alex Lourie <alou...@redhat.com> Gerrit-Reviewer: Alexander Wels <aw...@redhat.com> Gerrit-Reviewer: Alon Bar-Lev <alo...@redhat.com> Gerrit-Reviewer: Barak Azulay <bazu...@redhat.com> Gerrit-Reviewer: Daniel Erez <de...@redhat.com> Gerrit-Reviewer: Einav Cohen <eco...@redhat.com> Gerrit-Reviewer: Eyal Edri <ee...@redhat.com> Gerrit-Reviewer: Itamar Heim <ih...@redhat.com> Gerrit-Reviewer: Kanagaraj M <kmayi...@redhat.com> Gerrit-Reviewer: Michal Skrivanek <michal.skriva...@redhat.com> Gerrit-Reviewer: Moran Goldboim <mgold...@redhat.com> Gerrit-Reviewer: Ofer Schreiber <oschr...@redhat.com> Gerrit-Reviewer: Sahina Bose <sab...@redhat.com> Gerrit-Reviewer: Sandro Bonazzola <sbona...@redhat.com> Gerrit-Reviewer: Vojtech Szocs <vsz...@redhat.com> Gerrit-Reviewer: Yair Zaslavsky <yzasl...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches