ImageServerComponent.java 15.5 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.scene7.is.image_server.ISConfig
 *  com.scene7.is.image_server.ImageConverter
 *  com.scene7.is.image_server.ImageServerProxy
 *  com.scene7.is.image_server.TiffMd5sum
 *  com.scene7.is.image_server.image_info.ImageInfo
 *  com.scene7.is.scalautil.javautil.CollectionUtil
 *  com.scene7.is.scalautil.javautil.Conversions
 *  com.scene7.is.scalautil.net.NetUtil
 *  com.scene7.is.scalautil.service.ArgSpec
 *  com.scene7.is.scalautil.service.ArgSpec$ArgValue
 *  com.scene7.is.scalautil.service.ArgSpec$CommandArg
 *  com.scene7.is.scalautil.service.ArgSpec$Param
 *  com.scene7.is.util.ObjectUtil
 *  com.scene7.is.util.callbacks.Option
 *  com.scene7.is.util.collections.CollectionUtil
 *  com.scene7.is.util.text.ParsingException
 *  com.scene7.is.util.text.parsers.IntegerParser
 *  org.apache.commons.io.IOUtils
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Deactivate
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.resource.LoginException
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ResourceResolverFactory
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.wrappers.ValueMapDecorator
 *  org.apache.sling.settings.SlingSettingsService
 *  org.jetbrains.annotations.NotNull
 *  org.jetbrains.annotations.Nullable
 *  org.osgi.framework.BundleContext
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 *  scala.collection.Seq
 *  scala.collection.immutable.Range
 */
package com.adobe.cq.dam.s7imaging.impl.is;

import com.scene7.is.image_server.ISConfig;
import com.scene7.is.image_server.ImageConverter;
import com.scene7.is.image_server.ImageServerProxy;
import com.scene7.is.image_server.TiffMd5sum;
import com.scene7.is.image_server.image_info.ImageInfo;
import com.scene7.is.scalautil.javautil.Conversions;
import com.scene7.is.scalautil.net.NetUtil;
import com.scene7.is.scalautil.service.ArgSpec;
import com.scene7.is.util.ObjectUtil;
import com.scene7.is.util.callbacks.Option;
import com.scene7.is.util.collections.CollectionUtil;
import com.scene7.is.util.text.ParsingException;
import com.scene7.is.util.text.parsers.IntegerParser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.settings.SlingSettingsService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.collection.Seq;
import scala.collection.immutable.Range;

@Service(value={ImageServerComponent.class})
@Component(label="Adobe CQ Scene7 ImageServer", metatype=1)
public class ImageServerComponent {
    @Property(label="enabled", boolValue={0}, description="Enables/Disables Scene7 Dynamic Media Imaging")
    private static final String Enabled = "enabled";
    @Property(label="TcpPort", description="Port number to use for communication with ImageServer process. If left blank the port is automatically chosen")
    private static final String PropTcpPort = ISConfig.name((ArgSpec.CommandArg)ISConfig.TcpPort());
    @Property(label="AllowRemoteAccess", boolValue={0}, description="Allow or disallow remote access to ImageServer process. If false image server will only listen on localhost")
    private static final String PropAllowRemoteAccess = ISConfig.name((ArgSpec.CommandArg)ISConfig.AllowRemoteAccess());
    @Property(label="MaxRenderRgnPixels", description="Maximum size in megapixels that will be rendered.")
    private static final String PropMaxRenderRgnPixels = ISConfig.name((ArgSpec.CommandArg)ISConfig.MaxRenderRgnPixels());
    @Property(label="MaxMessageSize", description="Maximum message size in MBytes that will be delivered.")
    private static final String PropMaxMessageSize = ISConfig.name((ArgSpec.CommandArg)ISConfig.MaxMessageSize());
    @Property(label="RandomAccessUrlTimeout", intValue={20}, description="Timeout value for how long in seconds the ImageServer will wait for the JCR to respond to a ranged tile request.")
    private static final String PropRandomAccessUrlTimeout = ISConfig.name((ArgSpec.CommandArg)ISConfig.RandomAccessUrlTimeout());
    private static final int NUMBER_OF_IS_INSTANCES = 2;
    @Nullable
    private ImageConverter imageConverter = null;
    @Nullable
    private ImageInfo imageInfo = null;
    @Nullable
    private TiffMd5sum tiffMd5sum = null;
    private static final Range PORT_RANGE = Conversions.range((int)57345, (int)57455);
    private static final String LOCAL_HOST = "localhost";
    private static String host = "localhost";
    private static final String CONF_FILE = File.separator + "conf" + File.separator + "is.conf";
    private static final Logger LOGGER = LoggerFactory.getLogger(ImageServerComponent.class);
    private List<ImageServerProxy> imageServers = CollectionUtil.arrayList((int)10);
    @Reference
    private SlingSettingsService slingSettings;
    @Reference
    private ResourceResolverFactory resolverFactory;
    private List<Integer> isPorts = CollectionUtil.arrayList((int)10);
    private static final String PN_DYNAMIC_MEDIA_ENABLED = "dynamicMediaEnabled";
    private static final String DYNAMIC_MEDIA_CONFIG_PATH = "/etc/dam/dynamicmediaconfig";

    @NotNull
    public ImageConverter imageConverter() {
        if (!this.isEnabled()) {
            throw new AssertionError((Object)"imageConverter is not available when Dynamic Media is disabled");
        }
        return (ImageConverter)ObjectUtil.notNull((Object)this.imageConverter);
    }

    @NotNull
    public ImageInfo imageInfo() {
        if (!this.isEnabled()) {
            throw new AssertionError((Object)"imageInfo is not available when Dynamic Media is disabled");
        }
        return (ImageInfo)ObjectUtil.notNull((Object)this.imageInfo);
    }

    @NotNull
    public TiffMd5sum tiffMd5sum() {
        if (!this.isEnabled()) {
            throw new AssertionError((Object)"tiffMd5sum is not available when Dynamic Media is disabled");
        }
        return (TiffMd5sum)ObjectUtil.notNull((Object)this.tiffMd5sum);
    }

    public Integer[] getPort() {
        return this.isPorts.toArray(new Integer[this.isPorts.size()]);
    }

    public String getHost() {
        return host;
    }

    public boolean isEnabled() {
        return !this.isPorts.isEmpty();
    }

    @Activate
    protected void activate(ComponentContext ctx) {
        String componentName = (String)ctx.getProperties().get("component.name");
        if (!this.isDynamicMediaEnabled(ctx)) {
            LOGGER.info("Skipping " + componentName + " because Dynamic Media is disabled");
            return;
        }
        File isHome = ctx.getBundleContext().getDataFile("image-server");
        this.imageConverter = new ImageConverter(isHome);
        this.imageInfo = new ImageInfo(isHome);
        this.tiffMd5sum = new TiffMd5sum(isHome);
        Dictionary config = ctx.getProperties();
        this.createImageServerProxy(isHome, config, componentName);
    }

    private Seq<ArgSpec.ArgValue> buildArgs(Dictionary<String, Object> config, File isHome, int port) {
        List args = CollectionUtil.list();
        args.add(ImageServerComponent.arg(ISConfig.Log(), new File(this.slingSettings.getSlingHomePath() + "/logs/ImageServer.log")));
        args.add(ImageServerComponent.arg(ISConfig.CacheServerUrl(), this.slingSettings.getSlingHome()));
        args.add(ImageServerComponent.arg(ISConfig.RootPath(), new File(isHome, "images")));
        for (Boolean v222 /* !! */  : ImageServerComponent.getBoolean(config, PropAllowRemoteAccess)) {
            args.add(ImageServerComponent.arg(ISConfig.AllowRemoteAccess(), v222 /* !! */ ));
        }
        for (Boolean v222 /* !! */  : ImageServerComponent.getInt(config, PropMaxMessageSize)) {
            args.add(ImageServerComponent.arg(ISConfig.MaxMessageSize(), v222 /* !! */ ));
        }
        for (Boolean v222 /* !! */  : ImageServerComponent.getInt(config, PropMaxRenderRgnPixels)) {
            args.add(ImageServerComponent.arg(ISConfig.MaxRenderRgnPixels(), v222 /* !! */ ));
        }
        for (Boolean v222 /* !! */  : ImageServerComponent.getInt(config, PropRandomAccessUrlTimeout)) {
            args.add(ImageServerComponent.arg(ISConfig.RandomAccessUrlTimeout(), v222 /* !! */ ));
        }
        args.add(ImageServerComponent.arg(ISConfig.TcpPort(), port));
        return com.scene7.is.scalautil.javautil.CollectionUtil.toSeq((Collection)args);
    }

    private void createImageServerProxy(File isHome, Dictionary<String, Object> config, String componentName) {
        Properties isProperties = this.readConfProperties();
        host = isProperties.getProperty("is.host", "localhost");
        if (!host.equals("localhost")) {
            LOGGER.info("Skipping start of IS server as host is specified as :" + host);
            return;
        }
        this.isPorts = this.resolvePorts(config, 2);
        Iterator<Integer> i$ = this.isPorts.iterator();
        while (i$.hasNext()) {
            int port = i$.next();
            LOGGER.info("Starting " + componentName + " on port " + port + " in '" + isHome + "'");
            Seq<ArgSpec.ArgValue> args = this.buildArgs(config, isHome, port);
            ImageServerProxy proxy = new ImageServerProxy(isHome, args);
            proxy.start();
            this.imageServers.add(proxy);
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private Properties readConfProperties() {
        Properties properties;
        File conf = new File(this.slingSettings.getSlingHomePath() + CONF_FILE);
        properties = new Properties();
        BufferedReader bufferedReader = null;
        try {
            if (conf.isFile()) {
                bufferedReader = new BufferedReader(new FileReader(conf));
                properties.load(bufferedReader);
            }
        }
        catch (IOException e) {
            LOGGER.error("Failed to create conf " + conf.getPath(), (Throwable)e);
        }
        finally {
            IOUtils.closeQuietly((Reader)bufferedReader);
        }
        return properties;
    }

    @Deactivate
    protected void deactivate(ComponentContext ctx) {
        LOGGER.info("Stopping " + ctx.getProperties().get("component.name"));
        for (ImageServerProxy v : this.imageServers) {
            v.stop();
        }
    }

    private static <T> ArgSpec.ArgValue arg(ArgSpec.Param<T> key, T value) {
        return ISConfig.apply(key, value);
    }

    private static Option<Integer> getInt(Dictionary<String, Object> conf, String key) {
        Object tmpVal = conf.get(key);
        if (tmpVal == null) {
            return Option.none();
        }
        if (tmpVal instanceof Integer) {
            return Option.some((Object)((Integer)tmpVal));
        }
        String value = tmpVal.toString();
        if (value == null || value.isEmpty()) {
            return Option.none();
        }
        try {
            return Option.some((Object)IntegerParser.integerParser().parse(value));
        }
        catch (ParsingException e) {
            throw new IllegalArgumentException("Error parsing integer property: '" + key + "' = '" + value + "'", (Throwable)e);
        }
    }

    private static Option<Boolean> getBoolean(Dictionary<String, Object> conf, String key) {
        return Option.some((Object)((Boolean)conf.get(key)));
    }

    private List<Integer> resolvePorts(Dictionary<String, Object> props, int cnt) {
        Iterator i$ = ImageServerComponent.getInt(props, PropTcpPort).iterator();
        if (i$.hasNext()) {
            int v = (Integer)i$.next();
            return Collections.unmodifiableList(CollectionUtil.listOf((Object[])new Integer[]{v}));
        }
        return com.scene7.is.scalautil.javautil.CollectionUtil.asJavaIntList((Seq)NetUtil.findFreePorts((Range)PORT_RANGE, (int)cnt));
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private boolean isDynamicMediaEnabled(ComponentContext ctx) {
        boolean bl;
        if (((Boolean)ObjectUtil.notNull((Object)((Boolean)ctx.getProperties().get("enabled")), (Object)Boolean.FALSE)).booleanValue()) {
            return true;
        }
        String SUB_SERVICE_NAME = "dmreplicateonmodify";
        Map<String, String> authInfo = Collections.singletonMap("sling.service.subservice", "dmreplicateonmodify");
        ResourceResolver resolver = this.resolverFactory.getServiceResourceResolver(authInfo);
        try {
            bl = ImageServerComponent.isDynamicMediaEnabled(resolver);
        }
        catch (Throwable var6_7) {
            try {
                resolver.close();
                throw var6_7;
            }
            catch (LoginException e) {
                throw new AssertionError((Object)e);
            }
        }
        resolver.close();
        return bl;
    }

    public static boolean isDynamicMediaEnabled(ResourceResolver resolver) {
        ValueMap configProperties = ImageServerComponent.getDynamicMediaConfigurationProperties(resolver);
        return (Boolean)configProperties.get("dynamicMediaEnabled", (Object)false);
    }

    private static ValueMap getDynamicMediaConfigurationProperties(ResourceResolver resolver) {
        ValueMap configProps = null;
        try {
            Resource dmConfigResource = resolver.getResource("/etc/dam/dynamicmediaconfig");
            configProps = (ValueMap)dmConfigResource.adaptTo(ValueMap.class);
        }
        catch (Exception e) {
            LOGGER.error("Could not read the Dynamic Media configuration from node /etc/dam/dynamicmediaconfig", (Throwable)e);
        }
        if (configProps == null) {
            configProps = new ValueMapDecorator(Collections.emptyMap());
        }
        return configProps;
    }

    protected void bindSlingSettings(SlingSettingsService slingSettingsService) {
        this.slingSettings = slingSettingsService;
    }

    protected void unbindSlingSettings(SlingSettingsService slingSettingsService) {
        if (this.slingSettings == slingSettingsService) {
            this.slingSettings = null;
        }
    }

    protected void bindResolverFactory(ResourceResolverFactory resourceResolverFactory) {
        this.resolverFactory = resourceResolverFactory;
    }

    protected void unbindResolverFactory(ResourceResolverFactory resourceResolverFactory) {
        if (this.resolverFactory == resourceResolverFactory) {
            this.resolverFactory = null;
        }
    }
}