@Override
    public void generateSkinCssFile(DynamicSkinInstanceData data) {
        final String cssInstanceKey = getCssInstanceKey(data);
        synchronized (cssInstanceKey) {
            if (instanceKeysForExistingCss.contains(cssInstanceKey)) {
                /*
                 * Two or more threads needing the same CSS file managed to invoke
                 * this method.  An earlier thread has already generated the file
                 * we need.  Concurrency features of the CopyOnWriteArraySet
                 * (compiledCssFilepaths) guarantee that we will enter this if {}
                 * block (and exit) for a filePathname that's been successfully
                 * generated by another thread.
                 */
                return;
            }
            try {
                if (!cssSkinFailureCache.getKeysWithExpiryCheck().contains(cssInstanceKey)) {
                    createLessIncludeFile(data);
                    processLessFile(data);
                    if (!supportsRetainmentOfNonCurrentCss()) {
                        instanceKeysForExistingCss.clear();
                    }
                    instanceKeysForExistingCss.add(cssInstanceKey);
                } else {
                    // Though this should never happen except when developers are modifying the LESS
                    // files and make a mistake,
                    // if we previously tried to create the CSS file and failed for some reason,
                    // don't try to compile it
                    // again for a bit since the process is so processor intensive. It would
                    // virtually hang the uPortal
                    // service trying to compile a bad LESS file repeatedly on different threads.
                    logger.warn(
                            "Skipping generation of CSS file {} due to previous LESS compilation failures",
                            cssInstanceKey);
                }
            } catch (Exception e) {
                cssSkinFailureCache.put(new Element(cssInstanceKey, cssInstanceKey));
                throw new RuntimeException(
                        "Error compiling the LESS file to create:  " + cssInstanceKey, e);
            }
        }
    }
@ Override public void generateSkinCssFile ( DynamicSkinInstanceData data ) { final String cssInstanceKey = getCssInstanceKey ( data ) ; synchronized ( cssInstanceKey ) { if ( instanceKeysForExistingCss . contains ( cssInstanceKey ) ) { return ; } try { if ( ! cssSkinFailureCache . getKeysWithExpiryCheck ( ) . contains ( cssInstanceKey ) ) { createLessIncludeFile ( data ) ; processLessFile ( data ) ; if ( ! supportsRetainmentOfNonCurrentCss ( ) ) { instanceKeysForExistingCss . clear ( ) ; } instanceKeysForExistingCss . add ( cssInstanceKey ) ; } else { logger . warn ( "Skipping generation of CSS file {} due to previous LESS compilation failures" , cssInstanceKey ) ; } } catch ( Exception e ) { cssSkinFailureCache . put ( new Element ( cssInstanceKey , cssInstanceKey ) ) ; throw new RuntimeException ( "Error compiling the LESS file to create:  " + cssInstanceKey , e ) ; } } }
Creates the skin css file in a thread-safe manner that allows multiple different skin files
to be created simultaneously to handle large tenant situations where all the custom CSS files
were cleared away after a uPortal deploy.

<p>Since the less compilation phase is fairly slow (several seconds) and intensive, this
method will allow multiple threads to process different less compilations at the same time
but ensure the same output file will not be created multiple times. Also this method will not
let a bad LESS file cause repeated LESS compilations and completely take down the portal. The
bad file will be blacklisted for a period of time to limit performance impacts.

@see DynamicSkinService#generateSkinCssFile(DynamicSkinInstanceData)