MyFaces Trinidad
  1. MyFaces Trinidad
  2. TRINIDAD-2235

Skinning: stable names for generated style sheets

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0.2-core
    • Component/s: Skinning
    • Labels:
      None

      Description

      For this recently logged Trinidad issue:

      TRINIDAD-2234 Pregeneration of skin style sheets

      We plan to add a skin pregeneration feature in order to support cases where skin style sheets are hosted on a separate host/domain (eg. CDN use cases).

      One issue with this is that the names of the generated style sheet files are not produced in a stable manner.

      For example, a skin that contains the following locale-specific definition:

      @locale ja, cz, ko

      { ... }

      May share a generated .css file across Japanese, Chinese and Korean end users. The name of this generated style sheet depends on which locale is specified when the style sheet is first generated. If the style sheet is generated in response from a request for a Korean-locale user, the file name will include the "ko" locale token. This file will then be shared by Japanese, Chinese and Korean end users. However, if the server is subsequently bounced and the first post-bounce request is from a Japanese end user, the file will be re-generated with the "ja" token.

      As a result of this behavior, file names are not predictable across runs. This lack of predictability makes it difficult to determine which variants of style sheets should be pregenerated. In the above example, although ja/cz/ko users could/should share a single generated style sheet, we would need to pregenerate 3 style sheets just to be sure that we can handle all possible request orderings. However:

      a) This will result in an explosion of generated style sheets. And...
      b) This does not work well for range-based variants, such as agent versions.

      A better solution would be to enhance the way that Trinidad skinning derives names for generated style sheets. Trinidad skinning should provide a solution where style sheet names are produced in a predictable, stable, repeatable (after a server bounce) way.

        Activity

        Hide
        Andy Schwartz added a comment -

        The patch for TRINIDAD-2234:

        https://issues.apache.org/jira/secure/attachment/12517604/trinidad-skin-pregen.patch

        Provides the solution for this issue as well.

        The javadoc for the new StableNameUtils class describes this solution:

        /**

        • This class serves one purpose: it provides a replacement for NameUtils.getContextName()
        • that produces "stable" file names. This ensures that generated style sheets will be
        • named in a consistent manner that is not dependent on the order in which requests arrives.
        • With NameUtils.getContextName(), a skin that contains the following locale-specific
        • definition:
        • @locale ja, cz, ko { ... }
        • May share a generated .css file across Japanese, Chinese and Korean end users. The name
        • of this generated style sheet depends on which locale is specified when the style sheet is
        • first generated. For example, if the style sheet is generated in response from a request
        • for a Korean-locale user, the file name will include the "ko" locale token. This file
        • will then be shared by Japanese, Chinese and Korean end users. However, if the server is
        • subsequently bounced and the first post-bounce request is from a Japanese end user, the file
        • will be re-generated with the "ja" token.
        • As a result of this behavior, file names are not predictable across runs. The lack of
        • stable file names makes it difficult/impossible to support use cases where we want to
        • share generated style sheets across applications - eg. by pregenerating style sheets
        • and deploying them to some common server (or a CDN).
        • StableNameUtils.getContextName() solves this problem by producing names for generated
        • style sheet files that are not dependent on request ordering.
        • The file names produced by StableNameUtils.getContextName() are broken up into three
        • major sections:
        • 1. The skin identifier.
        • 2. Variant identifiers (eg. agent, locale, etc...)
        • 3. Contextual identifiers (eg. portlet vs. servlet)
        • These major sections are separated by double dashes ("--").
        • Within each major section, minor subsections appear in a predictable order, separated
        • by single dashs ("-").
        • The skin identifier section (section #1) contains the following subsections:
        • <id>-<hash>
        • Where:
        • - id: the skin id. Note that the skin id itself may include dash characters
        • (eg. "simple-desktop").
        • - hash: a hash of the skin contents
        • The variant identifiers section (section #2) contains the following subsections:
        • <platform><agent><version><locale><direction>-<accessibility>
        • Where:
        • - platform: the platform name (eg. linux, windows, iphone)
        • - agent: the agent name (eg. ie, gecko, safari)
        • - version: the agent version (eg. 7, 1.9.2, 534)
        • - locale: the locale (eg. en, en_US, ja).
        • - direction: the reading direction (ltr|rtl)
        • - accessibility: accessibility profile preferences (hc|lf|hclf for high contrast|
        • large fonts|high contrast + large fonts).
        • These fields all support two additional values:
        • - Default: in the event that no @-rule variant is expicitly matched, only default styles
        • (ie. styles that apply to all requests) are included in the generated style sheet.
        • The token "d" is used to identify this case. For example, if the skin does not
        • define any @locale rules, the locale portion of the file name will be "d".
        • - Multiple: In some cases it is not possible to determine a unique value
        • for a particular variant, because only @-rules that specify multiple values
        • are matched. The token "x" is used to identify such cases. For example, if the
        • skin defines a single @locale rule matching the ja, cz, and ko locales, the
        • locale portion of the file name for generated style sheets corresponding to these
        • locales will be "x".
        • The contextual identifiers section (section #3) contains the following subsections:
        • - container type: identifies whether the application is hosted within a servlet or
        • portlet (s|p).
        • - request type: identifies whether the style sheet is used for a secure or non-secure
        • request (s|n).
        • - style class type: identifies whether the style sheet is generated with compressed or
        • uncompressed style classes (c|u).
        • In case where skins are pregenerated and shared across applications, it may be necessary
        • to write regular expressions against the above format in order to rewrite style sheet
        • uris to point to some other host. When doing so, the following recommendations should
        • be observed:
        • - The identifier section contains a variable number of subsection separators: skin
        • ids may contain dashes. As such, when writing regular expressions that target items
        • in the subsequent major sections, it is best to anchor these regular expressions
        • to the major section separators (double-dash).
        • - In the future it is possible that new subsections may need to be added to the
        • variant or contextual identifier sections. If the need for additional
        • information arises, new subsections will be added at the end of the appropriate
        • major section. As such, regular expressions should be written in a way that they
        • can tolerate new subsections later appearing at the end of each major section.
          */

        Note that although the primary goal is to ensure that generated style sheet file names remain stable across runs/servers, another important goal is that the resulting names should be easily targeted by regular expressions. This will allow specific subsets of generated style sheet uris to be rewritten to point to some other server (eg. to a CDN).

        Show
        Andy Schwartz added a comment - The patch for TRINIDAD-2234 : https://issues.apache.org/jira/secure/attachment/12517604/trinidad-skin-pregen.patch Provides the solution for this issue as well. The javadoc for the new StableNameUtils class describes this solution: /** This class serves one purpose: it provides a replacement for NameUtils.getContextName() that produces "stable" file names. This ensures that generated style sheets will be named in a consistent manner that is not dependent on the order in which requests arrives. With NameUtils.getContextName(), a skin that contains the following locale-specific definition: @locale ja, cz, ko { ... } May share a generated .css file across Japanese, Chinese and Korean end users. The name of this generated style sheet depends on which locale is specified when the style sheet is first generated. For example, if the style sheet is generated in response from a request for a Korean-locale user, the file name will include the "ko" locale token. This file will then be shared by Japanese, Chinese and Korean end users. However, if the server is subsequently bounced and the first post-bounce request is from a Japanese end user, the file will be re-generated with the "ja" token. As a result of this behavior, file names are not predictable across runs. The lack of stable file names makes it difficult/impossible to support use cases where we want to share generated style sheets across applications - eg. by pregenerating style sheets and deploying them to some common server (or a CDN). StableNameUtils.getContextName() solves this problem by producing names for generated style sheet files that are not dependent on request ordering. The file names produced by StableNameUtils.getContextName() are broken up into three major sections: 1. The skin identifier. 2. Variant identifiers (eg. agent, locale, etc...) 3. Contextual identifiers (eg. portlet vs. servlet) These major sections are separated by double dashes ("--"). Within each major section, minor subsections appear in a predictable order, separated by single dashs ("-"). The skin identifier section (section #1) contains the following subsections: <id>-<hash> Where: - id: the skin id. Note that the skin id itself may include dash characters (eg. "simple-desktop"). - hash: a hash of the skin contents The variant identifiers section (section #2) contains the following subsections: <platform> <agent> <version> <locale> <direction>-<accessibility> Where: - platform: the platform name (eg. linux, windows, iphone) - agent: the agent name (eg. ie, gecko, safari) - version: the agent version (eg. 7, 1.9.2, 534) - locale: the locale (eg. en, en_US, ja). - direction: the reading direction (ltr|rtl) - accessibility: accessibility profile preferences (hc|lf|hclf for high contrast| large fonts|high contrast + large fonts). These fields all support two additional values: - Default: in the event that no @-rule variant is expicitly matched, only default styles (ie. styles that apply to all requests) are included in the generated style sheet. The token "d" is used to identify this case. For example, if the skin does not define any @locale rules, the locale portion of the file name will be "d". - Multiple: In some cases it is not possible to determine a unique value for a particular variant, because only @-rules that specify multiple values are matched. The token "x" is used to identify such cases. For example, if the skin defines a single @locale rule matching the ja, cz, and ko locales, the locale portion of the file name for generated style sheets corresponding to these locales will be "x". The contextual identifiers section (section #3) contains the following subsections: - container type: identifies whether the application is hosted within a servlet or portlet (s|p). - request type: identifies whether the style sheet is used for a secure or non-secure request (s|n). - style class type: identifies whether the style sheet is generated with compressed or uncompressed style classes (c|u). In case where skins are pregenerated and shared across applications, it may be necessary to write regular expressions against the above format in order to rewrite style sheet uris to point to some other host. When doing so, the following recommendations should be observed: - The identifier section contains a variable number of subsection separators: skin ids may contain dashes. As such, when writing regular expressions that target items in the subsequent major sections, it is best to anchor these regular expressions to the major section separators (double-dash). - In the future it is possible that new subsections may need to be added to the variant or contextual identifier sections. If the need for additional information arises, new subsections will be added at the end of the appropriate major section. As such, regular expressions should be written in a way that they can tolerate new subsections later appearing at the end of each major section. */ Note that although the primary goal is to ensure that generated style sheet file names remain stable across runs/servers, another important goal is that the resulting names should be easily targeted by regular expressions. This will allow specific subsets of generated style sheet uris to be rewritten to point to some other server (eg. to a CDN).
        Hide
        Andy Schwartz added a comment -

        Stable style sheet names committed in to Trinidad trunk in r1303525.

        See TRINIDAD-2234 for the patch.

        Note that stable names are enabled by default - no new public configuration/context parameter API has been added.

        Show
        Andy Schwartz added a comment - Stable style sheet names committed in to Trinidad trunk in r1303525. See TRINIDAD-2234 for the patch. Note that stable names are enabled by default - no new public configuration/context parameter API has been added.

          People

          • Assignee:
            Andy Schwartz
            Reporter:
            Andy Schwartz
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development