From 615c6e65c4df99490062759a577cb7408f66996b Mon Sep 17 00:00:00 2001 From: michaeloffner Date: Wed, 14 Dec 2022 11:36:17 +0100 Subject: [PATCH] improve caching for 12 Monkeys Coder and reading application settings --- build.number | 4 +- .../image/coder/AImageIOInterface.java | 114 +++++++++++++----- .../lucee/extension/image/coder/Coder.java | 30 +++-- .../extension/image/coder/MultiCoder.java | 1 - .../image/coder/TwelveMonkeysCoder.java | 13 -- .../extension/image/util/CommonUtil.java | 15 ++- .../lucee/extension/image/util/Images.java | 37 +----- 7 files changed, 118 insertions(+), 96 deletions(-) diff --git a/build.number b/build.number index 439c6a8..9901f37 100644 --- a/build.number +++ b/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Tue Dec 13 19:51:32 CET 2022 -build.number=23 +#Wed Dec 14 11:30:33 CET 2022 +build.number=24 diff --git a/source/java/src/org/lucee/extension/image/coder/AImageIOInterface.java b/source/java/src/org/lucee/extension/image/coder/AImageIOInterface.java index 431b754..bcefd88 100644 --- a/source/java/src/org/lucee/extension/image/coder/AImageIOInterface.java +++ b/source/java/src/org/lucee/extension/image/coder/AImageIOInterface.java @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -528,11 +529,13 @@ protected static class Codec { private final Class _writer; private final Class readerSpi; private final Class writerSpi; - private final Class[] readerConstructor; - private final Class[] writerConstructor; + private final Class[] readerConstructorArgs; + private final Class[] writerConstructorArgs; + public int writer = -1; + public int reader = -1; public Codec(String[] formatNames, String[] suffixes, String[] mimeTypes, Class reader, Class writer, - Class readerSpi, Class writerSpi, Class[] readerConstructor, Class[] writerConstructor) { + Class readerSpi, Class writerSpi, Class[] readerConstructorArgs, Class[] writerConstructorArgs) { super(); this.formatNames = formatNames == null ? new String[0] : formatNames; this.suffixes = suffixes == null ? new String[0] : suffixes; @@ -541,8 +544,8 @@ public Codec(String[] formatNames, String[] suffixes, String[] mimeTypes, Class< this._writer = writer; this.readerSpi = readerSpi; this.writerSpi = writerSpi; - this.readerConstructor = readerConstructor; - this.writerConstructor = writerConstructor; + this.readerConstructorArgs = readerConstructorArgs; + this.writerConstructorArgs = writerConstructorArgs; } protected static void newInstance(Map codecs, String[] formatNames, String[] suffixes, String[] mimeTypes, Class reader, @@ -661,27 +664,30 @@ public boolean canDecodeInput(Object source) throws IOException { @Override public ImageReader createReaderInstance(Object extension) throws IOException { try { + // javax.imageio.spi.ImageReaderSpi - Constructor constr; - Class[] constrArgs = codec.readerConstructor; - try { + Class[] constrArgs = codec.readerConstructorArgs; - constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 1 ? constrArgs : READ_CONSTR1); - constr.setAccessible(true); - return constr.newInstance(this); + if (codec.reader == 0) return createReaderInstance0(constrArgs); + if (codec.reader == 1) return createReaderInstance1(constrArgs); + if (codec.reader == 2) return createReaderInstance2(constrArgs); + ImageReader ir; + try { + ir = createReaderInstance1(constrArgs); + codec.reader = 1; + return ir; } catch (NoSuchMethodException nsme) { try { - constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 2 ? constrArgs : READ_CONSTR2); - constr.setAccessible(true); - return constr.newInstance(this, getDelegateImageReader()); - + ir = createReaderInstance2(constrArgs); + codec.reader = 2; + return ir; } catch (NoSuchMethodException nsme2) { - constr = clazz.getDeclaredConstructor(READ_CONSTR0); - constr.setAccessible(true); - return constr.newInstance(); + ir = createReaderInstance0(constrArgs); + codec.reader = 0; + return ir; } } } @@ -690,6 +696,27 @@ public ImageReader createReaderInstance(Object extension) throws IOException { } } + public ImageReader createReaderInstance0(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(READ_CONSTR0); + constr.setAccessible(true); + return constr.newInstance(); + } + + public ImageReader createReaderInstance1(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 1 ? constrArgs : READ_CONSTR1); + constr.setAccessible(true); + return constr.newInstance(this); + } + + public ImageReader createReaderInstance2(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 2 ? constrArgs : READ_CONSTR2); + constr.setAccessible(true); + return constr.newInstance(this, getDelegateImageReader()); + } + @Override public String getDescription(Locale locale) { return "Lucee impl to handle OSGi enviroment"; @@ -835,30 +862,30 @@ public boolean canEncodeImage(ImageTypeSpecifier type) { @Override public ImageWriter createWriterInstance(Object extension) throws IOException { - try { - Constructor constr; - Class[] constrArgs = codec.writerConstructor; + Class[] constrArgs = codec.writerConstructorArgs; - try { - constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 1 ? constrArgs : WRITE_CONSTR1); - constr.setAccessible(true); - return constr.newInstance(constrArgs != null && constrArgs.length == 1 ? null : this); + if (codec.writer == 0) return createWriterInstance0(constrArgs); + if (codec.writer == 1) return createWriterInstance1(constrArgs); + if (codec.writer == 2) return createWriterInstance2(constrArgs); + ImageWriter iw; + try { + iw = createWriterInstance1(constrArgs); + codec.writer = 1; + return iw; } catch (NoSuchMethodException nsme) { - nsme.printStackTrace(); try { - constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 2 ? constrArgs : WRITE_CONSTR2); - constr.setAccessible(true); - return constr.newInstance(constrArgs != null && constrArgs.length == 2 ? null : this, getDelegateImageWriter()); + iw = createWriterInstance2(constrArgs); + codec.writer = 2; + return iw; } catch (NoSuchMethodException nsme2) { - nsme2.printStackTrace(); - constr = clazz.getDeclaredConstructor(WRITE_CONSTR0); - constr.setAccessible(true); - return constr.newInstance(); + iw = createWriterInstance0(constrArgs); + codec.writer = 3; + return iw; } } } @@ -867,6 +894,27 @@ public ImageWriter createWriterInstance(Object extension) throws IOException { } } + private ImageWriter createWriterInstance0(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(WRITE_CONSTR0); + constr.setAccessible(true); + return constr.newInstance(); + } + + private ImageWriter createWriterInstance1(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 1 ? constrArgs : WRITE_CONSTR1); + constr.setAccessible(true); + return constr.newInstance(constrArgs != null && constrArgs.length == 1 ? null : this); + } + + private ImageWriter createWriterInstance2(Class[] constrArgs) + throws IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Constructor constr = clazz.getDeclaredConstructor(constrArgs != null && constrArgs.length == 2 ? constrArgs : WRITE_CONSTR2); + constr.setAccessible(true); + return constr.newInstance(constrArgs != null && constrArgs.length == 2 ? null : this, getDelegateImageWriter()); + } + @Override public String getDescription(Locale locale) { return "Lucee impl to handle OSGi enviroment"; diff --git a/source/java/src/org/lucee/extension/image/coder/Coder.java b/source/java/src/org/lucee/extension/image/coder/Coder.java index 77ae57f..1fb436c 100644 --- a/source/java/src/org/lucee/extension/image/coder/Coder.java +++ b/source/java/src/org/lucee/extension/image/coder/Coder.java @@ -24,7 +24,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.lucee.extension.image.Image; import org.lucee.extension.image.util.CommonUtil; @@ -32,6 +34,7 @@ import lucee.commons.io.log.Log; import lucee.commons.io.res.Resource; import lucee.commons.lang.types.RefInteger; +import lucee.loader.engine.CFMLEngine; import lucee.loader.engine.CFMLEngineFactory; import lucee.runtime.PageContext; import lucee.runtime.config.Config; @@ -39,19 +42,24 @@ public abstract class Coder { - private static Coder instance; + private static Map instances = new ConcurrentHashMap<>(); protected Coder() { } public static Coder getInstance(PageContext pc) { - if (true || instance == null) { - Config config = CFMLEngineFactory.getInstance().getThreadConfig(); - Log log = config == null ? null : config.getLog("application"); + CFMLEngine eng = CFMLEngineFactory.getInstance(); + + StringBuilder sb = new StringBuilder(); + Set coders = CommonUtil.getCoders(sb, pc); + long hash = eng.getStringUtil().create64BitHash(sb.toString()); + Coder instance = instances.get(hash); + if (instance == null) { + Config config = eng.getThreadConfig(); + Log log = config == null ? null : config.getLog("application"); MultiCoder mc = new MultiCoder(); - Set coders = CommonUtil.getCoders(pc); if (coderAllowed(coders, "JDeli")) add(mc, "org.lucee.extension.image.coder.JDeliCoder", log); if (coderAllowed(coders, "Gotson")) add(mc, "org.lucee.extension.image.coder.GotsonCoder", log); if (coderAllowed(coders, "Aspose")) add(mc, "org.lucee.extension.image.coder.AsposeCoder", log); @@ -60,8 +68,7 @@ public static Coder getInstance(PageContext pc) { if (coderAllowed(coders, "Lucee")) add(mc, "org.lucee.extension.image.coder.LuceeCoder", log); if (coderAllowed(coders, "ApacheImaging")) add(mc, "org.lucee.extension.image.coder.ApacheImagingCoder", log); if (coderAllowed(coders, "JAI")) add(mc, "org.lucee.extension.image.coder.JAICoder", log); - - instance = mc; + instances.put(hash, instance = mc); } return instance; } @@ -82,7 +89,6 @@ private static void add(MultiCoder mc, String className, Log log) { } catch (Exception e) { if (log != null) log.error("image", e); - // else e.printStackTrace(); } } @@ -109,9 +115,11 @@ private static void add(MultiCoder mc, String className, Log log) { public abstract void write(Image img, Resource destination, String format, float quality, boolean noMeta) throws IOException; public static Log log() { - // FUTURE PageContext pc = CFMLEngineFactory.getInstance().getThreadPageContext(); - // FUTURE if(pc!=null)pc.getLog("application"); - Config config = CFMLEngineFactory.getInstance().getThreadConfig(); + return log(null); + } + + public static Log log(PageContext pc) { + Config config = pc != null ? pc.getConfig() : CFMLEngineFactory.getInstance().getThreadConfig(); if (config != null) return config.getLog("application"); return null; } diff --git a/source/java/src/org/lucee/extension/image/coder/MultiCoder.java b/source/java/src/org/lucee/extension/image/coder/MultiCoder.java index 2db9650..5a3bef9 100644 --- a/source/java/src/org/lucee/extension/image/coder/MultiCoder.java +++ b/source/java/src/org/lucee/extension/image/coder/MultiCoder.java @@ -176,7 +176,6 @@ public void write(Image img, Resource destination, String format, float quality, write(img, destination, format, quality, noMeta, null); } catch (IOException e) { - e.printStackTrace(); throw e; } } diff --git a/source/java/src/org/lucee/extension/image/coder/TwelveMonkeysCoder.java b/source/java/src/org/lucee/extension/image/coder/TwelveMonkeysCoder.java index 3c33210..039679a 100644 --- a/source/java/src/org/lucee/extension/image/coder/TwelveMonkeysCoder.java +++ b/source/java/src/org/lucee/extension/image/coder/TwelveMonkeysCoder.java @@ -1,12 +1,8 @@ package org.lucee.extension.image.coder; -import java.io.IOException; - import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; -import org.lucee.extension.image.util.print; - import com.twelvemonkeys.imageio.plugins.bmp.BMPImageReaderSpi; import com.twelvemonkeys.imageio.plugins.bmp.BMPImageWriterSpi; import com.twelvemonkeys.imageio.plugins.bmp.ICOImageReader; @@ -25,15 +21,6 @@ public class TwelveMonkeysCoder extends AImageIOInterface { public TwelveMonkeysCoder() { - - try { - print.e(new WebPImageReaderSpi().createReaderInstance()); - } - catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - Codec.newInstanceSpi(codecs, new String[] { "bmp", "BMP" }, new String[] { "bmp", "rle" }, new String[] { "image/bmp", "image/x-bmp", "image/vnd.microsoft.bitmap" }, BMPImageReaderSpi.class, BMPImageWriterSpi.class); // Codec.newInstance(codecs, new String[] { "bmp", "BMP" }, new String[] { "bmp", "rle" }, new diff --git a/source/java/src/org/lucee/extension/image/util/CommonUtil.java b/source/java/src/org/lucee/extension/image/util/CommonUtil.java index 5a5e0f0..1d537ef 100644 --- a/source/java/src/org/lucee/extension/image/util/CommonUtil.java +++ b/source/java/src/org/lucee/extension/image/util/CommonUtil.java @@ -11,6 +11,7 @@ import javax.imageio.stream.ImageInputStream; import org.lucee.extension.image.Image; +import org.lucee.extension.image.coder.Coder; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -33,6 +34,7 @@ public class CommonUtil { private static final String _8220 = String.valueOf((char) 8220); private static Map members; + private static BIF GetApplicationSettings; public static String unwrap(String str) { if (str == null) return ""; @@ -263,14 +265,16 @@ public static void close(ImageInputStream iis) { } } - public static Set getCoders(PageContext pc) { + public static Set getCoders(StringBuilder sb, PageContext pc) { Set result = null; try { CFMLEngine eng = CFMLEngineFactory.getInstance(); if (pc == null) pc = eng.getThreadPageContext(); if (pc == null) return null; - BIF bif = eng.getClassUtil().loadBIF(pc, "lucee.runtime.functions.system.GetApplicationSettings"); - Struct sct = (Struct) bif.invoke(pc, new Object[] { Boolean.TRUE }); + if (GetApplicationSettings == null) { + GetApplicationSettings = eng.getClassUtil().loadBIF(pc, "lucee.runtime.functions.system.GetApplicationSettings"); + } + Struct sct = (Struct) GetApplicationSettings.invoke(pc, new Object[] { Boolean.TRUE }); Object o = sct.get("image", null); if (o instanceof Struct) { Struct image = (Struct) o; @@ -283,13 +287,14 @@ public static Set getCoders(PageContext pc) { for (String c: coders) { if (Util.isEmpty(c, true)) continue; if (result == null) result = new HashSet<>(); - result.add(c.trim().toLowerCase()); + sb.append(c = c.trim().toLowerCase()).append(';'); + result.add(c); } } } } catch (Exception e) { - e.printStackTrace(); + Coder.log(pc); } return result; diff --git a/source/java/src/org/lucee/extension/image/util/Images.java b/source/java/src/org/lucee/extension/image/util/Images.java index 2d59384..ff27966 100644 --- a/source/java/src/org/lucee/extension/image/util/Images.java +++ b/source/java/src/org/lucee/extension/image/util/Images.java @@ -1,12 +1,13 @@ package org.lucee.extension.image.util; -import java.io.FileNotFoundException; -import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.apache.commons.codec.binary.Base64; +import org.lucee.extension.image.coder.Coder; + +import lucee.commons.io.log.Log; public class Images { @@ -43,7 +44,9 @@ public class Images { images.put(f.getName().trim().toLowerCase(), Base64.decodeBase64((String) f.get(null))); } catch (Exception e) { - e.printStackTrace(); + Log log = Coder.log(); + if (log != null) log.error("image", e); + else e.printStackTrace(); } } // print.e(images.keySet()); @@ -52,32 +55,4 @@ public class Images { public static byte[] getImage(String format) { return images.get(format.toLowerCase()); } - - /* - * File[] files = new File("/Users/mic/Test/test-cfconfig/webapps/ROOT/formats").listFiles(); - * - * for (File f: files) { int index = f.getName().lastIndexOf('.'); String name = - * f.getName().substring(0, index); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - * Util.copy(new FileInputStream(f), baos, true, true); print.e("byte[] " + name + " = new "); - * print.e(baos.toByteArray()); print.e(";"); } if (true) return; - */ - public static void main(String[] args) throws FileNotFoundException, IOException { - print.e(getImage("gif")); - } - /* - * File f = new File("/Users/mic/Test/test-cfconfig/webapps/ROOT/formats/dcx.dcx"); int index = - * f.getName().lastIndexOf('.'); String name = f.getName().substring(0, index); - * ByteArrayOutputStream baos = new ByteArrayOutputStream(); Util.copy(new FileInputStream(f), baos, - * true, true); print.e("public static byte[] " + name + " = new "); print.e(baos.toByteArray()); - * print.e(";"); - */ - - // byte to base64 - /* - * for (Map.Entry e: images.entrySet()) { - * - * String b64 = Base64.encodeBase64String(e.getValue()); - * - * print.e("public static String " + e.getKey() + " = \"" + b64 + "\""); } - */ }