1 10 package org.mmbase.module.builders; 11 12 import java.util.*; 13 import org.mmbase.cache.BlobCache; 14 import org.mmbase.util.magicfile.MagicFile; 15 import org.mmbase.util.images.*; 16 import org.mmbase.module.core.*; 17 import org.mmbase.util.logging.*; 18 import org.mmbase.util.functions.*; 19 20 28 public abstract class AbstractImages extends AbstractServletBuilder { 29 30 private static final Logger log = Logging.getLoggerInstance(AbstractImages.class); 31 32 public final static Parameter[] HEIGHT_PARAMETERS = Parameter.EMPTY; 33 public final static Parameter[] WIDTH_PARAMETERS = Parameter.EMPTY; 34 public final static Parameter[] DIMENSION_PARAMETERS = Parameter.EMPTY; 35 36 37 public static final String FIELD_ITYPE = "itype"; 38 public static final String FIELD_FILESIZE = "filesize"; 39 public static final String FIELD_HEIGHT = "height"; 40 public static final String FIELD_WIDTH = "width"; 41 42 protected static BlobCache handleCache = new BlobCache(300) { public String getName() { return "ImageHandles"; } 44 public String getDescription() { return "Handles of Images (number -> handle)"; } 45 }; 46 static { 47 handleCache.putCache(); 48 } 49 53 abstract protected static class CKeyCache extends org.mmbase.cache.Cache { 54 protected CKeyCache(int i) { 55 super(i); 56 } 57 61 62 void remove(int originalNodeNumber) { 63 String prefix = "" + originalNodeNumber; 64 if (log.isDebugEnabled()) { 65 log.debug("removing " + prefix); 66 } 67 Iterator entries = entrySet().iterator(); 68 while (entries.hasNext()) { 69 Map.Entry entry = (Map.Entry)entries.next(); 70 String key = (String )entry.getKey(); 71 if (log.isDebugEnabled()) { 72 log.debug("checking " + key); 73 } 74 if (key.startsWith(prefix)) { 75 if (log.isDebugEnabled()) { 80 log.debug("removing " + key + " " + get(key)); 81 } 82 entries.remove(); 83 } 84 85 } 86 } 87 88 void removeCacheNumber(int icacheNumber) { 89 Iterator entries = entrySet().iterator(); 90 while (entries.hasNext()) { 91 Map.Entry entry = (Map.Entry) entries.next(); 92 Object value = entry.getValue(); 93 if (value instanceof ByteFieldContainer) { 94 ByteFieldContainer bf = (ByteFieldContainer) value; 95 if (bf.number == icacheNumber) { 96 entries.remove(); 97 } 98 } else if (value instanceof Integer ) { 99 Integer i = (Integer ) value; 100 if (i.intValue() == icacheNumber) { 101 entries.remove(); 102 } 103 } 104 105 } 106 } 107 } 108 109 protected BlobCache getBlobCache(String fieldName) { 110 if (fieldName.equals(Imaging.FIELD_HANDLE)) { 111 return handleCache; 112 } else { 113 return super.getBlobCache(fieldName); 114 } 115 } 116 117 protected String getAssociation() { 118 return "images"; 119 } 120 protected String getDefaultPath() { 121 return "/img.db"; 122 } 123 124 128 abstract protected String getGUIIndicatorWithAlt(MMObjectNode node, String title, Parameters a); 129 130 134 protected String getSGUIIndicatorForNode(MMObjectNode node, Parameters a) { 135 return getGUIIndicatorWithAlt(node, "*", a); } 137 138 141 protected String getSGUIIndicator(MMObjectNode node, Parameters a) { 142 String field = a.getString("field"); 143 if (field.equals(Imaging.FIELD_HANDLE) || field.equals("")) { 144 return getSGUIIndicatorForNode(node, a); 145 } 146 return getSuperGUIIndicator(field, node); 148 } 149 150 151 protected final Set IMAGE_HANDLE_FIELDS = Collections.unmodifiableSet(new HashSet(Arrays.asList(new String [] {FIELD_FILESIZE, FIELD_ITYPE, FIELD_HEIGHT, FIELD_WIDTH}))); 152 protected Set getHandleFields() { 154 return IMAGE_HANDLE_FIELDS; 155 } 156 157 160 public String getMimeType(MMObjectNode node) { 161 String ext = getImageFormat(node); 162 if (log.isDebugEnabled()) { 163 log.debug("Getting mimetype for node " + node.getNumber() + " " + ext); 164 } 165 if (ext.equals("")) { 166 ext = getDefaultImageType(); 167 } else if (ext.startsWith("x-")) { 168 ext = ext.substring(2); 169 } 170 return Imaging.getMimeTypeByExtension(ext); 171 } 172 173 176 protected boolean storesDimension() { 177 return hasField(FIELD_WIDTH) && hasField(FIELD_HEIGHT) && 178 ! getField(FIELD_WIDTH).isVirtual() && ! getField(FIELD_HEIGHT).isVirtual(); 179 } 180 183 protected boolean storesFileSize() { 184 return hasField(FIELD_FILESIZE) && ! getField(FIELD_FILESIZE).isVirtual(); 185 } 186 189 protected boolean storesImageType() { 190 return hasField(FIELD_ITYPE) && ! getField(FIELD_ITYPE).isVirtual(); 191 } 192 193 194 197 protected Dimension getDimensionForEmptyHandle(MMObjectNode node) { 198 log.warn("Cannot get dimension of node with no 'handle' " + node + " (stores " + storesDimension() + ")"); 199 return Dimension.UNDETERMINED; 200 } 201 204 protected Dimension getDimension(MMObjectNode node) { 205 if (storesDimension()) { 206 int width = node.getIntValue(FIELD_WIDTH); 207 int height = node.getIntValue(FIELD_HEIGHT); 208 if (width >= 0 && height > 0 ) { 209 return new Dimension(width, height); 210 } 211 } 212 Dimension dim; 213 byte[] data = node.getByteValue(Imaging.FIELD_HANDLE); 214 if (data == null || data.length == 0) { 215 dim = getDimensionForEmptyHandle(node); 216 } else { 217 ImageInformer ii = Factory.getImageInformer(); 218 try { 219 dim = ii.getDimension(data); 220 log.debug("Found dimension " + dim); 221 } catch (Exception ioe) { 222 log.error(ioe); 223 dim = Dimension.UNDETERMINED; 224 } 225 } 226 227 if (! dim.valid()) return dim; 228 229 if (storesDimension()) { 230 int width = node.getIntValue(FIELD_WIDTH); 231 int height = node.getIntValue(FIELD_HEIGHT); 232 if (width != dim.getWidth() || height != dim.getHeight()) { node.setValue(FIELD_WIDTH, dim.getWidth()); 234 node.setValue(FIELD_HEIGHT, dim.getHeight()); 235 if (!node.isNew()) { 236 node.commit(); 237 } 238 } 239 } else { 240 log.warn("Requested dimension on image object without height / width fields, this may be heavy on resources!"); 241 } 242 243 return dim; 244 } 245 246 247 protected int getFileSize(MMObjectNode node) { 248 if (storesFileSize()) { 249 int size = node.getIntValue(FIELD_FILESIZE); 250 if (size >= 0) { 251 return size; 252 } 253 } 254 byte[] data = node.getByteValue(Imaging.FIELD_HANDLE); 255 if (data == null) return -1; 256 if (storesFileSize()) { 257 node.setValue(FIELD_FILESIZE, data.length); 258 if (!node.isNew()) { 259 node.commit(); 260 } 261 } else { 262 log.warn("Requested filesize on image object without filesize fields, this may be heavy on resources!"); 263 } 264 return data.length; 265 } 266 267 268 271 protected String getDefaultImageType() { 272 return "jpg"; 273 } 274 275 279 protected String getImageFormat(MMObjectNode node) { 280 String itype = null; 281 if (storesImageType()) { 282 itype = node.getStringValue(FIELD_ITYPE); 283 int slashPos = itype.indexOf("/"); 284 if (slashPos > -1) { 285 MagicFile magicFile = MagicFile.getInstance(); 286 String fixedIType = magicFile.mimeTypeToExtension(itype); 287 if ("".equals(fixedIType)) { 288 fixedIType = itype.substring(slashPos + 1); 289 log.warn("Could not find extension for mimetype " + itype + ", guessing " + fixedIType); 290 } 291 log.warn("Found an odd itype " + itype + " on node " + node.getNumber() + " (should be " + fixedIType + "?)"); 292 itype = fixedIType; 293 node.setValue(FIELD_ITYPE, itype); 294 if (!node.isNew()) { 295 node.commit(); 296 } 297 } 298 } 299 300 if ((itype == null || itype.equals("")) && ! node.isNull(Imaging.FIELD_HANDLE) ) { 303 log.debug("Determining itype for " + node.getNumber()); 304 itype = ""; 305 try { 306 MagicFile magicFile = MagicFile.getInstance(); 307 String mimeType = magicFile.getMimeType(node.getByteValue(Imaging.FIELD_HANDLE)); 308 if (!mimeType.equals(MagicFile.FAILED)) { 309 if (mimeType.startsWith("image/")) { 311 itype = mimeType.substring(6); 312 log.debug("set itype to " + itype); 313 } else { 314 log.warn("Mimetype " + mimeType + " is not an image type"); 315 int pos = mimeType.indexOf('/'); 316 itype = mimeType.substring(pos + 1); 317 } 318 } else { 319 log.warn(MagicFile.FAILED); 320 itype = getDefaultImageType(); 321 } 322 } catch (Exception e) { 323 log.warn("Error while determining image mimetype : " + Logging.stackTrace(e)); 324 } 325 if (storesImageType()) { 326 log.debug("Found itype " + itype + " storing that"); 327 node.setValue(FIELD_ITYPE, itype); 328 if (!node.isNew()) { 329 node.commit(); 330 } 331 } else { 332 log.debug("Doesn't store"); 333 } 334 } 335 return itype; 336 } 337 338 protected void checkHandle(MMObjectNode node) { 340 super.checkHandle(node); 341 if (storesFileSize()) { 342 getFileSize(node); 343 } 344 if (storesDimension()) { 345 getDimension(node); 346 } 347 if (storesImageType()) { 348 getImageFormat(node); 349 } 350 } 351 352 353 354 358 359 protected Object executeFunction(MMObjectNode node, String function, List args) { 360 if (function.equals("mimetype")) { 361 return getMimeType(node); 362 } else if (function.equals("format")) { 363 return getImageFormat(node); 364 } else if ("width".equals(function)) { 365 return new Integer (getDimension(node).getWidth()); 366 } else if ("height".equals(function)) { 367 return new Integer (getDimension(node).getHeight()); 368 } else if ("dimension".equals(function)) { 369 return getDimension(node); 370 } else { 371 return super.executeFunction(node, function, args); 372 } 373 } 374 375 } 376 | Popular Tags |