// TODO avoid tmp file and build image online with another action
 protected String createTmpFile(PMContext ctx) throws ConverterException {
   FileOutputStream fos = null;
   try {
     final PMSecurityUser user = ctx.getUser();
     byte[] value = (byte[]) ctx.getFieldValue();
     if (value == null) {
       return null;
     }
     final String filename = user.getUsername() + "." + getConfig("type", "png");
     final String dir = "webapps/pm/cache/";
     final File directory = new File(dir);
     directory.mkdirs();
     final File tmpfile = new File(dir + filename);
     fos = new FileOutputStream(tmpfile);
     fos.write(value);
     return filename;
   } catch (Exception ex) {
     throw new ConverterException(ex);
   } finally {
     try {
       if (fos != null) {
         fos.close();
       }
     } catch (IOException ex) {
       throw new ConverterException(ex);
     }
   }
 }
 @Override
 public String visualize(PMContext ctx) throws ConverterException {
   Object p = ctx.getFieldValue();
   if (p == null) {
     p = getValue(ctx.getEntityInstance(), ctx.getField());
   }
   final String value = normalize((p == null) ? "" : p.toString());
   ctx.setFieldValue(value);
   return super.visualize("string_converter.jsp?ml=" + getConfig("max-length"));
 }
 @Override
 public Object build(PMContext ctx) throws ConverterException {
   try {
     String value = (String) ctx.getFieldValue();
     if (value != null && !"".equals(value.trim())) {
       return getDateFormat().parse((String) value);
     }
   } catch (ParseException e) {
     throw new ConverterException(
         MessageFactory.error(ctx.getEntity(), ctx.getField(), "date.converter.invalid.value"));
   }
   return null;
 }
 @Override
 public Object build(PMContext ctx) throws ConverterException {
   final PMStrutsContext c = (PMStrutsContext) ctx;
   final Object value = ctx.getFieldValue();
   if (withNull() && (value == null || value.equals(""))) {
     return null;
   } else {
     return (value != null) ? value.toString() : null;
   }
 }
 @Override
 public Object visualize(PMContext ctx) throws ConverterException {
   final String filename = createTmpFile(ctx);
   ctx.put(
       PM_VOID_TEXT,
       "<img src='"
           + PMEntitySupport.getInstance().getContext_path()
           + "/cache/"
           + filename
           + "' alt='x' />");
   return "void.jsp?";
 }
 @Override
 public String visualize(PMContext ctx) throws ConverterException {
   try {
     final Date o = (Date) ctx.getFieldValue();
     return super.visualize(
         "date_converter.jsp?lang="
             + getConfig("lang", "en")
             + "&format="
             + normalize(javaToJavascriptDateFormat(getFormatString()))
             + "&value="
             + getDateFormat().format(o));
   } catch (Exception e) {
     return super.visualize(
         "date_converter.jsp?lang="
             + getConfig("lang", "en")
             + "&format="
             + normalize(javaToJavascriptDateFormat(getFormatString()))
             + "&value="
             + getDateFormat().format(new Date()));
   }
 }