GuideThemeServiceImpl.java 17.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.jcr.JcrUtil
 *  javax.jcr.Binary
 *  javax.jcr.Node
 *  javax.jcr.PathNotFoundException
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Value
 *  javax.jcr.ValueFactory
 *  org.apache.commons.io.IOUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.jackrabbit.commons.JcrUtils
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.commons.json.JSONException
 *  org.apache.sling.commons.json.JSONObject
 *  org.apache.sling.resourcemerger.api.ResourceMergerService
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.aemds.guide.service.impl;

import com.adobe.aemds.guide.service.GuideException;
import com.adobe.aemds.guide.service.GuideThemeService;
import com.adobe.aemds.guide.themes.CSSObject;
import com.adobe.aemds.guide.themes.CSSProperty;
import com.adobe.aemds.guide.themes.Selector;
import com.day.cq.commons.jcr.JcrUtil;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.resourcemerger.api.ResourceMergerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
@Component(immediate=1, metatype=0, label="Adaptive Form Theme Service", description="Service to aid Adaptive Form Theme Authoring")
@Service(value={GuideThemeService.class})
public class GuideThemeServiceImpl
implements GuideThemeService {
    private Logger logger = LoggerFactory.getLogger(GuideThemeService.class);
    @Reference
    private ResourceMergerService resourceMergerService;

    @Override
    public long createUpdateTheme(String themeContentPath, ResourceResolver resourceResolver, JSONObject themeJson, long clientModifiedTime) throws GuideException {
        if (resourceResolver == null) {
            throw new GuideException("Invalid user session.");
        }
        Session session = (Session)resourceResolver.adaptTo(Session.class);
        long modTime = 0;
        try {
            if (themeContentPath != null && session.nodeExists(themeContentPath)) {
                Node originalRenditionNode;
                Node themeContentNode = session.getNode(themeContentPath);
                Node themeNode = themeContentNode.getParent();
                String clientLibPath = themeContentNode.getProperty("metadata/clientlibRef").getString();
                if (themeContentNode.hasNode("renditions/original/jcr:content")) {
                    originalRenditionNode = themeContentNode.getNode("renditions/original/jcr:content");
                    Property lastModOnServerProperty = originalRenditionNode.getProperty("jcr:lastModified");
                    Calendar lastModOnServer = lastModOnServerProperty.getDate();
                    long lastModOnServerTime = lastModOnServer.getTimeInMillis();
                    if (lastModOnServerTime != clientModifiedTime) {
                        throw new GuideException("Stale session: Refresh the page to continue.");
                    }
                } else {
                    throw new GuideException("Error in updating theme specifications. The theme " + themeNode.getPath() + " does not exist. You need to first create the theme from AEM Forms UI: ");
                }
                Binary binary = session.getValueFactory().createBinary((InputStream)new ByteArrayInputStream(themeJson.toString().getBytes()));
                originalRenditionNode.setProperty("jcr:data", binary);
                Calendar modifiedTime = Calendar.getInstance();
                modTime = modifiedTime.getTimeInMillis();
                originalRenditionNode.setProperty("jcr:lastModified", modifiedTime);
                if (themeContentNode.hasProperty("metadata/clientlibRef")) {
                    HashSet<String> relatedAssets = new HashSet<String>();
                    String cssString = this.getCssDefinitionAndRelatedAssetsFromJson(resourceResolver, themeJson, relatedAssets);
                    this.updateClientLibForTheme(session, themeNode.getName(), cssString, clientLibPath);
                    if (themeContentNode.hasNode("metadata")) {
                        Node themeMetadataNode = themeContentNode.getNode("metadata");
                        if (relatedAssets.size() > 0) {
                            try {
                                for (String assetID : relatedAssets) {
                                    if (session.nodeExists(assetID)) continue;
                                    relatedAssets.remove(assetID);
                                }
                                String[] references = relatedAssets.toArray(new String[0]);
                                themeMetadataNode.setProperty("images", references);
                            }
                            catch (RepositoryException e) {
                                this.logger.error("Error in updating Theme dependencies.", (Throwable)e);
                            }
                        } else {
                            themeContentNode.setProperty("images", (Value)null);
                        }
                    }
                } else {
                    throw new GuideException("Error in updating theme specifications. Unable to find the location to create theme clientlib.");
                }
                session.save();
            }
        }
        catch (PathNotFoundException e) {
            throw new GuideException((Exception)e);
        }
        catch (RepositoryException re) {
            throw new GuideException((Exception)re);
        }
        return modTime;
    }

    @Override
    public String getThemeJson(Resource themeResource) throws GuideException {
        Node node = (Node)themeResource.adaptTo(Node.class);
        Session session = (Session)themeResource.getResourceResolver().adaptTo(Session.class);
        try {
            Node originalContentNode = JcrUtil.createPath((String)(node.getPath() + "/jcr:content/renditions/original/jcr:content"), (String)"nt:file", (Session)session);
            Property themeJsonProperty = originalContentNode.getProperty("jcr:data");
            InputStream is = themeJsonProperty.getBinary().getStream();
            BufferedInputStream bin = new BufferedInputStream(is);
            String themeJsonString = null;
            try {
                themeJsonString = IOUtils.toString((InputStream)bin);
                bin.close();
                is.close();
            }
            catch (IOException e) {
                this.logger.error("IOException during getting theme JSON", (Throwable)e);
            }
            if (themeJsonProperty != null) {
                themeJsonString = themeJsonProperty.getString();
            }
            try {
                JSONObject themeJson = new JSONObject(themeJsonString);
                long lastModOnServer = 0;
                if (originalContentNode.hasProperty("jcr:lastModified")) {
                    Property lastModOnProperty = originalContentNode.getProperty("jcr:lastModified");
                    Calendar lastModifiedDate = lastModOnProperty.getDate();
                    lastModOnServer = lastModifiedDate.getTimeInMillis();
                }
                themeJson.put("lastModifiedTime", lastModOnServer);
                themeJsonString = themeJson.toString(2);
            }
            catch (JSONException e) {
                this.logger.error("Unable to parse JSON object", (Throwable)e);
            }
            return themeJsonString;
        }
        catch (PathNotFoundException e) {
            this.logger.error("Theme definition not found at: " + themeResource.getPath(), (Throwable)e);
        }
        catch (RepositoryException re) {
            this.logger.error("Unable to load theme definition from: " + themeResource.getPath(), (Throwable)re);
        }
        return null;
    }

    @Override
    public boolean updateThemeConfig(ResourceResolver resourceResolver, String themeContentPath, JSONObject configJson) throws GuideException {
        if (resourceResolver == null) {
            throw new GuideException("Invalid user session.");
        }
        Session session = (Session)resourceResolver.adaptTo(Session.class);
        try {
            if (themeContentPath != null && session.nodeExists(themeContentPath)) {
                Node themeContentNode = session.getNode(themeContentPath);
                Node themeNode = themeContentNode.getParent();
                if (themeContentNode.hasProperty("metadata/clientlibRef")) {
                    String clientlibLoc = themeContentNode.getProperty("metadata/clientlibRef").getString();
                    Node clientlibNode = session.getNode(clientlibLoc + "/" + themeContentNode.getParent().getName());
                    if (configJson.has("baseClientlibCategory") && !configJson.getString("baseClientlibCategory").isEmpty()) {
                        clientlibNode.setProperty("dependencies", new String[]{configJson.getString("baseClientlibCategory")});
                    } else if (clientlibNode.hasProperty("dependencies")) {
                        clientlibNode.setProperty("dependencies", (Value)null);
                    }
                } else {
                    return false;
                }
                if (themeContentNode.hasNode("metadata")) {
                    Node themeMetadata = themeContentNode.getNode("metadata");
                    if (configJson.has("configuredFormPath") && !configJson.getString("configuredFormPath").isEmpty()) {
                        String formPath = configJson.getString("configuredFormPath");
                        themeMetadata.setProperty("formRef", formPath);
                    } else {
                        Resource defaultForm = resourceResolver.getResource("fd/af/themes/default");
                        themeMetadata.setProperty("formRef", defaultForm.getPath());
                    }
                } else {
                    return false;
                }
                session.save();
                return true;
            }
        }
        catch (PathNotFoundException e) {
            throw new GuideException((Exception)e);
        }
        catch (RepositoryException e) {
            throw new GuideException((Exception)e);
        }
        catch (JSONException e) {
            throw new GuideException((Exception)e);
        }
        return false;
    }

    @Override
    public String getCSSDefinitionFromJson(ResourceResolver resourceResolver, JSONObject themeJson) {
        return this.getCssDefinitionAndRelatedAssetsFromJson(resourceResolver, themeJson, null);
    }

    private String getCssDefinitionAndRelatedAssetsFromJson(ResourceResolver resourceResolver, JSONObject themeJson, Set<String> relatedAssets) {
        Boolean extractRelatedAssets = relatedAssets != null;
        CSSObject cssObject = new CSSObject(new CSSObject.SelectorProvider(){

            @Override
            public Selector getCSSRule(Resource selectorStyleRes, List<CSSProperty> cssProperties, Resource stateStyleRes, JSONObject htmlAttrs) {
                Selector selector = null;
                ValueMap resourceProps = stateStyleRes.getValueMap();
                String selectorString = (String)resourceProps.get("cssSelector", (Object)"");
                if (selectorString.equals("")) {
                    GuideThemeServiceImpl.this.logger.error("Unable to retrieve CSS selector string for: " + stateStyleRes.getPath());
                    return null;
                }
                selector = new Selector(selectorString, "", cssProperties);
                return selector;
            }
        }, extractRelatedAssets);
        HashMap<String, Integer> breakPointMap = new HashMap<String, Integer>();
        try {
            if (themeJson.has("rawCss")) {
                cssObject.setRawCss(themeJson.getString("rawCss"));
            }
            JSONObject breakpointMetaNode = themeJson.getJSONObject("breakpoints");
            Iterator breakpointNamesIterator = breakpointMetaNode.keys();
            while (breakpointNamesIterator.hasNext()) {
                String breakpointName = (String)breakpointNamesIterator.next();
                JSONObject breakpointProperties = (JSONObject)breakpointMetaNode.get(breakpointName);
                Integer breakpointMaxValue = (Integer)breakpointProperties.get("max");
                if (breakpointMaxValue < 0) {
                    breakpointMaxValue = Integer.MAX_VALUE;
                }
                breakPointMap.put(breakpointName, breakpointMaxValue);
            }
        }
        catch (JSONException e) {
            this.logger.error("unable to generate breakpoints information. Using a default one only", (Throwable)e);
            breakPointMap.put("default", Integer.MAX_VALUE);
        }
        cssObject.setBreakpointInfo(breakPointMap);
        String cssString = "";
        try {
            if (themeJson.has("components")) {
                JSONObject componentsNode = (JSONObject)themeJson.get("components");
                JSONObject components = (JSONObject)componentsNode.get("items");
                Iterator componentsIterator = components.keys();
                while (componentsIterator.hasNext()) {
                    String componentPath = (String)componentsIterator.next();
                    String styleConfigPath = componentPath + "/cq:themeConfig";
                    Resource styleConfigRes = resourceResolver.getResource(styleConfigPath);
                    Resource styleConfigMergedRes = this.resourceMergerService.getMergedResource(styleConfigRes);
                    cssObject.addComponentStyles(components.getJSONObject(componentPath), styleConfigMergedRes, null);
                }
            }
        }
        catch (JSONException e) {
            this.logger.error("unable to read component information from theme. aborting", (Throwable)e);
        }
        if (relatedAssets != null) {
            relatedAssets.addAll(cssObject.getReferredImages());
        }
        cssString = cssObject.generateCSSString(false, null);
        return cssString;
    }

    private long getClientLibModifiedTime(Session session, String clientLibName, String clientLibPath) throws RepositoryException {
        long modTime = 0;
        clientLibPath = clientLibPath + "/" + clientLibName;
        if (session != null && session.nodeExists(clientLibPath)) {
            Node clientLibNode = session.getNode(clientLibPath);
            Node cssTxtNode = clientLibNode.getNode("css.txt");
            Calendar lastModifiedTime = JcrUtils.getLastModified((Node)cssTxtNode);
            modTime = lastModifiedTime.getTimeInMillis();
        }
        return modTime;
    }

    private long updateClientLibForTheme(Session session, String clientLibName, String cssString, String clientLibPath) throws RepositoryException {
        long modTime = 0;
        clientLibPath = clientLibPath + "/" + clientLibName;
        if (session != null && session.nodeExists(clientLibPath)) {
            Node clientLibNode = session.getNode(clientLibPath);
            Node contentNode = clientLibNode.getNode("css/theme.css/jcr:content");
            Binary binary = session.getValueFactory().createBinary((InputStream)new ByteArrayInputStream(cssString.getBytes()));
            contentNode.setProperty("jcr:data", binary);
            Node cssTxtNode = clientLibNode.getNode("css.txt");
            Calendar currentTime = Calendar.getInstance();
            modTime = currentTime.getTimeInMillis();
            JcrUtils.setLastModified((Node)cssTxtNode, (Calendar)currentTime);
            session.save();
        } else {
            this.logger.error("Unable to find clientlib at location {}", (Object)clientLibPath);
        }
        return modTime;
    }

    protected void bindResourceMergerService(ResourceMergerService resourceMergerService) {
        this.resourceMergerService = resourceMergerService;
    }

    protected void unbindResourceMergerService(ResourceMergerService resourceMergerService) {
        if (this.resourceMergerService == resourceMergerService) {
            this.resourceMergerService = null;
        }
    }

}