ProjectImageServlet.java 9.46 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.cq.projects.api.Project
 *  com.day.cq.dam.api.Asset
 *  com.day.cq.dam.api.Rendition
 *  com.day.cq.wcm.api.designer.Style
 *  com.day.cq.wcm.commons.AbstractImageServlet
 *  com.day.cq.wcm.commons.AbstractImageServlet$ImageContext
 *  com.day.cq.wcm.foundation.AdaptiveImageHelper
 *  com.day.cq.wcm.foundation.AdaptiveImageHelper$Quality
 *  com.day.cq.wcm.foundation.Image
 *  com.day.image.Layer
 *  javax.jcr.RepositoryException
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.projects.impl.servlet;

import com.adobe.cq.projects.api.Project;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.Rendition;
import com.day.cq.wcm.api.designer.Style;
import com.day.cq.wcm.commons.AbstractImageServlet;
import com.day.cq.wcm.foundation.AdaptiveImageHelper;
import com.day.cq.wcm.foundation.Image;
import com.day.image.Layer;
import java.awt.Dimension;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.List;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Adobe CQ Project Image Reference Modification Servlet", description="Render the image associated with a project in a variety of dimensions and qualities")
@Service
@Properties(value={@Property(name="sling.servlet.resourceTypes", value={"cq/gui/components/projects/admin/card/projectcard"}, propertyPrivate=1), @Property(name="sling.servlet.selectors", value={"image,channel"}, propertyPrivate=1), @Property(name="sling.servlet.extensions", value={"jpg", "jpeg", "png", "gif"}, propertyPrivate=1)})
public class ProjectImageServlet
extends AbstractImageServlet {
    private static final long serialVersionUID = 1;
    private static final Logger log = LoggerFactory.getLogger(ProjectImageServlet.class);
    @Property(label="Image Quality", description="Quality must be a double between 0.0 and 1.0", value={"0.82"})
    private static final String PROPERTY_IMAGE_QUALITY = "image.quality";
    private double imageQualityFromOsgiConfig;
    @Property(value={"319x319"}, label="Supported Resolutions", description="List of resolutions this component is permitted to generate.")
    private static final String PROPERTY_SUPPORTED_RESOLUTIONS = "image.supported.resolutions";
    private List<Dimension> supportedDimensions = new ArrayList<Dimension>();

    protected void activate(ComponentContext componentContext) {
        Dictionary properties = componentContext.getProperties();
        this.setImageQualityFromOsgiConfig(PropertiesUtil.toString(properties.get("image.quality"), (String)Double.toString(AdaptiveImageHelper.Quality.MEDIUM.getQualityValue())));
        String[] supportedResolutionsArray = PropertiesUtil.toStringArray(properties.get("image.supported.resolutions"));
        if (supportedResolutionsArray != null && supportedResolutionsArray.length > 0) {
            for (String resolution : supportedResolutionsArray) {
                String[] widthAndHeight = resolution.split("x");
                if (widthAndHeight.length != 2) continue;
                try {
                    int width = Integer.parseInt(widthAndHeight[0]);
                    int height = Integer.parseInt(widthAndHeight[1]);
                    this.supportedDimensions.add(new Dimension(width, height));
                    continue;
                }
                catch (NumberFormatException ex) {
                    // empty catch block
                }
            }
        }
    }

    protected boolean isDimensionSupported(int width, int height) {
        Iterator<Dimension> iterator = this.getSupportedDimensionsIterator();
        Dimension dimension = new Dimension(width, height);
        while (iterator.hasNext()) {
            if (!dimension.equals(iterator.next())) continue;
            return true;
        }
        return false;
    }

    protected Iterator<Dimension> getSupportedDimensionsIterator() {
        return this.supportedDimensions.iterator();
    }

    protected Layer createLayer(AbstractImageServlet.ImageContext imageContext) throws RepositoryException, IOException {
        int height;
        Resource coverResource;
        SlingHttpServletRequest request = imageContext.request;
        String[] selectors = request.getRequestPathInfo().getSelectors();
        if (selectors.length < 3 || selectors.length > 4 || !this.isInteger(selectors[1]) || !this.isInteger(selectors[2])) {
            log.error("Expected a width and height selector.");
            return null;
        }
        int width = Integer.parseInt(selectors[1]);
        if (!this.isDimensionSupported(width, height = Integer.parseInt(selectors[2]))) {
            log.error("Unsupported dimensions requested: {} x {}.", (Object)width, (Object)height);
            return null;
        }
        Resource projectResource = imageContext.resource;
        Project project = (Project)projectResource.adaptTo(Project.class);
        Resource resource = coverResource = project != null ? project.getProjectCover() : null;
        if (project == null || coverResource == null) {
            log.error("This project does not have an image associated with it; drawing a placeholder.");
            return AdaptiveImageHelper.renderScaledPlaceholderImage((int)width, (int)height);
        }
        Asset asset = (Asset)coverResource.adaptTo(Asset.class);
        Rendition original = asset.getOriginal();
        Image image = new Image((Resource)original);
        if (image.getFileNodePath() == null) {
            log.error("The image associated with this page does not have a valid file reference; drawing a placeholder.");
            return AdaptiveImageHelper.renderScaledPlaceholderImage((int)width, (int)height);
        }
        Rendition rendition = asset.getOriginal();
        ProjectImageHelper adaptiveAdaptiveImageComponent = new ProjectImageHelper(rendition.getStream());
        return adaptiveAdaptiveImageComponent.scaleThisImage(image, width, height, imageContext.style);
    }

    protected void writeLayer(SlingHttpServletRequest request, SlingHttpServletResponse response, AbstractImageServlet.ImageContext context, Layer layer) throws IOException, RepositoryException {
        double quality;
        String[] selectors = request.getRequestPathInfo().getSelectors();
        if (selectors.length == 4) {
            String imageQualitySelector = selectors[3];
            quality = this.getRequestedImageQuality(imageQualitySelector);
        } else {
            quality = this.getImageQualityFromOsgiConfig();
        }
        this.writeLayer(request, response, context, layer, quality);
    }

    private double getRequestedImageQuality(String imageQualitySelector) {
        AdaptiveImageHelper.Quality newQuality = AdaptiveImageHelper.getQualityFromString((String)imageQualitySelector);
        if (newQuality != null) {
            return newQuality.getQualityValue();
        }
        return this.getImageQualityFromOsgiConfig();
    }

    private void setImageQualityFromOsgiConfig(String imageQuality) {
        double newQuality;
        try {
            newQuality = Double.parseDouble(imageQuality);
            if (newQuality > 1.0 || newQuality < 0.0) {
                newQuality = AdaptiveImageHelper.Quality.MEDIUM.getQualityValue();
            }
        }
        catch (NumberFormatException ex) {
            log.error("Could not set imageQuality to: [" + imageQuality + "] because it is not a double.");
            newQuality = AdaptiveImageHelper.Quality.MEDIUM.getQualityValue();
        }
        this.imageQualityFromOsgiConfig = newQuality;
    }

    private double getImageQualityFromOsgiConfig() {
        return this.imageQualityFromOsgiConfig;
    }

    protected String getImageType() {
        return "image/jpeg";
    }

    private boolean isInteger(String string) {
        try {
            Integer.parseInt(string);
        }
        catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    class ProjectImageHelper
    extends AdaptiveImageHelper {
        private InputStream stream;

        public ProjectImageHelper(InputStream stream) {
            this.stream = stream;
        }

        public Layer applyStyleDataToImage(Image image, Style style) throws RepositoryException, IOException {
            Layer layer = new Layer(this.stream);
            image.loadStyleData(style);
            image.crop(layer);
            image.rotate(layer);
            return layer;
        }
    }

}