fixes issue 36843: js defaults containing Dates fail in JRE8
authorCarlos Aristu <carlos.aristu@openbravo.com>
Fri, 15 Sep 2017 13:00:13 +0200
changeset 32917 02d89be55b57
parent 32701 7fafd2a9f24b
child 32918 f7d032aa5982
fixes issue 36843: js defaults containing Dates fail in JRE8

In Java 8 JavaScript engine was changed from Rhino to Nashorn. JavaScript Dates evaluated in server, returned a java.util.Date in Rhino, but with Nashorn they are evaluated to jdk.nashorn.internal.objects.NativeDate.

This change caused a ClassCastException in JRE8 when invoking the methods of OBBindings which receive a java.util.Date as an argument. To fix the problem those methods have been overloaded by receiving an Object as argument. Therefore these methods will be invoked when working with JRE8, and we use reflection to retrieve the time information avoiding using classes which are not supported in JRE7.
modules/org.openbravo.client.application/src/org/openbravo/client/application/OBBindings.java
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/OBBindings.java	Wed Sep 13 06:39:31 2017 +0000
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/OBBindings.java	Fri Sep 15 13:00:13 2017 +0200
@@ -11,13 +11,14 @@
  * under the License.
  * The Original Code is Openbravo ERP.
  * The Initial Developer of the Original Code is Openbravo SLU
- * All portions are Copyright (C) 2010-2013 Openbravo SLU
+ * All portions are Copyright (C) 2010-2017 Openbravo SLU
  * All Rights Reserved.
  * Contributor(s):  ______________________________________.
  ************************************************************************
  */
 package org.openbravo.client.application;
 
+import java.lang.reflect.Method;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
@@ -25,13 +26,15 @@
 
 import javax.servlet.http.HttpSession;
 
-import org.apache.log4j.Logger;
+import org.openbravo.base.exception.OBException;
 import org.openbravo.base.util.Check;
 import org.openbravo.base.util.OBClassLoader;
 import org.openbravo.base.weld.WeldUtils;
 import org.openbravo.dal.core.OBContext;
 import org.openbravo.dal.service.OBDal;
 import org.openbravo.service.json.JsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * JS - Java binding to use in JavaScript expressions.
@@ -40,7 +43,7 @@
  */
 public class OBBindings {
 
-  private Logger log = Logger.getLogger(OBBindings.class);
+  private static final Logger log = LoggerFactory.getLogger(OBBindings.class);
 
   private OBContext context;
   private Map<String, String> requestMap;
@@ -173,14 +176,38 @@
     return dateFormat.format(d);
   }
 
+  public String formatDate(Object d) {
+    return formatDate(getTimeFromNashornNativeDate(d));
+  }
+
+  private Date getTimeFromNashornNativeDate(Object d) {
+    // Since Java 8, Nashorn is the Javascript engine used by default. When returning Javascript
+    // Date objects to Java the java.util.Date class is no longer used but
+    // jdk.nashorn.internal.objects.NativeDate is used instead.
+    // We need to use reflection to access to the time information contained in such class. Thus, we
+    // avoid the usage of unsupported classes in Java 7.
+    try {
+      Method m = d.getClass().getMethod("callMember", String.class, Object[].class);
+      long localTime = ((Double) m.invoke(d, "getTime", null)).longValue();
+      return new Date(localTime);
+    } catch (Exception ex) {
+      log.error("Error getting javascript date from object {} of class {}", d, d.getClass()
+          .getName());
+      throw new OBException(ex.getMessage(), ex);
+    }
+  }
+
   public String formatDateTime(Date d) {
     return dateTimeFormat.format(d);
   }
 
+  public String formatDateTime(Object d) {
+    return formatDateTime(getTimeFromNashornNativeDate(d));
+  }
+
   public Date parseDate(String date) {
     try {
-      Date result = dateFormat.parse(date);
-      return result;
+      return dateFormat.parse(date);
     } catch (Exception e) {
       log.error("Error parsing string date " + date + " with format: " + dateFormat, e);
     }
@@ -219,6 +246,10 @@
     return df.format(d);
   }
 
+  public String formatDate(Object d, String format) {
+    return formatDate(getTimeFromNashornNativeDate(d), format);
+  }
+
   public Date parseDate(String date, String format) {
     Check.isNotNull(format, "Format is a required parameter");
     try {