diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java index 643f57c7c..49cd427d8 100644 --- a/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/PlatformDetector.java @@ -124,7 +124,6 @@ public class PlatformDetector { if (OS.isAndroid()) { return "google"; } - //如果if条件全部不符合,就会陷入死循环,代码存在风险 //throw new UnsatisfiedLinkError("Unsupported vendor: " + getName()); return null; @@ -286,10 +285,10 @@ public class PlatformDetector { if (value.matches("^(sparcv9|sparc64)$")) { return "sparc_64"; } - if (value.matches("^(arm|arm32)$")) { + if (value.matches("^(arm|arm32)$") || value.startsWith("armv7")) { return "arm_32"; } - if ("aarch64".equals(value)) { + if ("aarch64".equals(value) || value.startsWith("armv8")) { return "aarch_64"; } if (value.matches("^(ppc|ppc32)$")) { @@ -317,4 +316,4 @@ public class PlatformDetector { } return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", ""); } -} \ No newline at end of file +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java new file mode 100644 index 000000000..035c5b06b --- /dev/null +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/SignatureProvider.java @@ -0,0 +1,5 @@ +package com.eclipsesource.v8; + +public interface SignatureProvider { + public byte[] getSignature(String uri); +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java index 077ff6de1..511f522bf 100644 --- a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.eclipsesource.v8.inspector.V8InspectorDelegate; import com.eclipsesource.v8.utils.V8Executor; import com.eclipsesource.v8.utils.V8Map; import com.eclipsesource.v8.utils.V8Runnable; @@ -47,6 +48,7 @@ public class V8 extends V8Object { private Map data = null; private final V8Locker locker; + private SignatureProvider signatureProvider = null; private long objectReferences = 0; private long v8RuntimePtr = 0; private List resources = null; @@ -162,6 +164,10 @@ public class V8 extends V8Object { return runtime; } + public void setSignatureProvider(final SignatureProvider signatureProvider) { + this.signatureProvider = signatureProvider; + } + /** * Adds a ReferenceHandler to track when new V8Objects are created. * @@ -276,6 +282,20 @@ public class V8 extends V8Object { objectHandle = _getGlobalObject(v8RuntimePtr); } + public long createInspector(final V8InspectorDelegate inspectorDelegate, final String contextName) { + return _createInspector(v8RuntimePtr, inspectorDelegate, contextName); + } + + public void dispatchProtocolMessage(final long V8InspectorPtr, final String protocolMessage) { + checkThread(); + _dispatchProtocolMessage(v8RuntimePtr, V8InspectorPtr, protocolMessage); + } + + public void schedulePauseOnNextStatement(final long V8InspectorPtr, final String reason) { + checkThread(); + _schedulePauseOnNextStatement(v8RuntimePtr, V8InspectorPtr, reason); + } + /** * Returns an UNDEFINED constant. * @@ -670,16 +690,51 @@ public class V8 extends V8Object { * Primitives will be boxed. * * @param script The script to execute. - * @param scriptName The name of the script + * @param uri The name of the script + * + * @return The result of the script as a Java Object. + */ + public Object executeScript(final String script, final String uri) { + checkThread(); + checkScript(script); + return executeScript(getV8RuntimePtr(), UNKNOWN, script, uri, 0); + } + + /** + * Executes a JS Script on this runtime and returns the result as a Java Object. + * Primitives will be boxed. + * + * @param script The script to execute. + * @param uri The name of the script * @param lineNumber The line number that is considered to be the first line of * the script. Typically 0, but could be set to another value for exception stack trace purposes. * * @return The result of the script as a Java Object. */ - public Object executeScript(final String script, final String scriptName, final int lineNumber) { + public Object executeScript(final String script, final String uri, final int lineNumber) { + checkThread(); + checkScript(script); + return executeScript(getV8RuntimePtr(), UNKNOWN, script, uri, lineNumber); + } + + /** + * Executes a JS Script module on this runtime and returns the result as a Java Object. + * Primitives will be boxed. + * + * If the script does not match the signature (as verified with the public key) then a + * V8SecurityException will be thrown. + * + * @param script The signed script to execute + * @param modulePrefix The module prefix + * @param modulePostfix The module postfix + * @param uri The name of the script + * + * @return The result of the script as a Java Object. + */ + public Object executeModule(final String script, final String modulePrefix, final String modulePostfix, final String uri) { checkThread(); checkScript(script); - return executeScript(getV8RuntimePtr(), UNKNOWN, script, scriptName, lineNumber); + return executeScript(getV8RuntimePtr(), UNKNOWN, modulePrefix + script + modulePostfix, uri, 0); } /** @@ -755,7 +810,7 @@ public class V8 extends V8Object { * * @return The unique build ID of the Native library. */ - public long getBuildID() { + public static long getBuildID() { return _getBuildID(); } @@ -1321,6 +1376,10 @@ public class V8 extends V8Object { _addArrayNullItem(v8RuntimePtr, arrayHandle); } + protected String getConstructorName(final long v8RuntimePtr, final long objectHandle) { + return _getConstructorName(v8RuntimePtr, objectHandle); + } + protected int getType(final long v8RuntimePtr, final long objectHandle) { return _getType(v8RuntimePtr, objectHandle); } @@ -1409,6 +1468,12 @@ public class V8 extends V8Object { private native long _createIsolate(String globalAlias); + private native long _createInspector(long v8RuntimePtr, final V8InspectorDelegate inspectorDelegate, final String contextName); + + private native void _dispatchProtocolMessage(final long v8RuntimePtr, long v8InspectorPtr, final String protocolMessage); + + private native void _schedulePauseOnNextStatement(final long v8RuntimePtr, long v8InspectorPtr, final String reason); + private native int _executeIntegerScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber); private native double _executeDoubleScript(long v8RuntimePtr, final String script, final String scriptName, final int lineNumber); @@ -1519,6 +1584,8 @@ public class V8 extends V8Object { private native void _setPrototype(long v8RuntimePtr, long objectHandle, long prototypeHandle); + private native String _getConstructorName(long v8RuntimePtr, long objectHandle); + private native int _getType(long v8RuntimePtr, long objectHandle); private native int _getType(long v8RuntimePtr, long objectHandle, final int index, final int length); @@ -1581,7 +1648,7 @@ public class V8 extends V8Object { private native long _getGlobalObject(final long v8RuntimePtr); - private native long _getBuildID(); + private native static long _getBuildID(); private native static void _startNodeJS(final long v8RuntimePtr, final String fileName); diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8OutOfMemoryError.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8OutOfMemoryError.java new file mode 100644 index 000000000..29084a341 --- /dev/null +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8OutOfMemoryError.java @@ -0,0 +1,17 @@ +package com.eclipsesource.v8; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-11-26 + */ +public class V8OutOfMemoryError extends V8RuntimeException { + + V8OutOfMemoryError(final String message) { + super(message); + } + + V8OutOfMemoryError() { + super(); + } +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java index d22042580..0804bf9e4 100644 --- a/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/V8Value.java @@ -143,6 +143,17 @@ abstract public class V8Value implements Releasable { } } + /** + * Returns a constructor name of the V8 Value. + * + * @return The V8Value constructor name as a string. + */ + public String getConstructorName() { + v8.checkThread(); + v8.checkReleased(); + return v8.getConstructorName(v8.getV8RuntimePtr(), objectHandle); + } + /** * Determines if this value is undefined. * diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java new file mode 100644 index 000000000..de1d9b50a --- /dev/null +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/DebuggerConnectionListener.java @@ -0,0 +1,7 @@ +package com.eclipsesource.v8.inspector; + +public interface DebuggerConnectionListener { + public void onDebuggerConnected(); + + public void onDebuggerDisconnected(); +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java new file mode 100644 index 000000000..2034fcd38 --- /dev/null +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8Inspector.java @@ -0,0 +1,67 @@ +package com.eclipsesource.v8.inspector; + +import java.util.ArrayList; +import java.util.List; + +import com.eclipsesource.v8.V8; +import com.eclipsesource.v8.V8Object; + +public class V8Inspector { + + private V8 runtime; + private long inspectorPtr = 0; + private boolean waitingForConnection = true; + private List debuggerConnectionListeners; + + protected V8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate, final String contextName) { + this.runtime = runtime; + inspectorPtr = runtime.createInspector(inspectorDelegate, contextName); + debuggerConnectionListeners = new ArrayList(); + } + + public static V8Inspector createV8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate, final String contextName) { + return new V8Inspector(runtime, inspectorDelegate, contextName); + } + + public static V8Inspector createV8Inspector(final V8 runtime, final V8InspectorDelegate inspectorDelegate) { + return new V8Inspector(runtime, inspectorDelegate, null); + } + + public void dispatchProtocolMessage(final String protocolMessage) { + try { + runtime.dispatchProtocolMessage(inspectorPtr, protocolMessage); + if (waitingForConnection) { + verifyDebuggerConnection(protocolMessage); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void addDebuggerConnectionListener(final DebuggerConnectionListener listener) { + debuggerConnectionListeners.add(listener); + } + + public void removeDebuggerConnectionListener(final DebuggerConnectionListener listener) { + debuggerConnectionListeners.remove(listener); + } + + private void verifyDebuggerConnection(final String protocolMessage) { + V8Object json = null; + try { + json = runtime.executeObjectScript("JSON.parse(JSON.stringify(" + protocolMessage + "))"); + if (json.getString("method").equals("Runtime.runIfWaitingForDebugger")) { + waitingForConnection = false; + runtime.schedulePauseOnNextStatement(inspectorPtr, ""); + for (DebuggerConnectionListener listener : debuggerConnectionListeners) { + listener.onDebuggerConnected(); + } + } + } finally { + if (json != null) { + json.close(); + } + } + } + +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java new file mode 100644 index 000000000..c799dcc24 --- /dev/null +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/inspector/V8InspectorDelegate.java @@ -0,0 +1,7 @@ +package com.eclipsesource.v8.inspector; + +public interface V8InspectorDelegate { + public void onResponse(String message); + + public void waitFrontendMessageOnPause(); +} diff --git a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java index b7e2b6c27..881a22983 100644 --- a/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java +++ b/fine-j2v8/src/main/java/com/eclipsesource/v8/utils/V8Executor.java @@ -125,9 +125,6 @@ public class V8Executor extends Thread { if (scriptResult instanceof Releasable) { ((Releasable) scriptResult).release(); } - if (scriptResult instanceof Releasable) { - ((Releasable) scriptResult).release(); - } } while (!forceTerminating && longRunning) { synchronized (this) { diff --git a/fine-j2v8/src/main/resources/libj2v8-linux-aarch_64.so b/fine-j2v8/src/main/resources/libj2v8-linux-aarch_64.so old mode 100644 new mode 100755 index ddada8e21..ab205d45f Binary files a/fine-j2v8/src/main/resources/libj2v8-linux-aarch_64.so and b/fine-j2v8/src/main/resources/libj2v8-linux-aarch_64.so differ diff --git a/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so b/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so old mode 100644 new mode 100755 index d79071d5f..59057358e Binary files a/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so and b/fine-j2v8/src/main/resources/libj2v8-linux-x86_64.so differ diff --git a/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib b/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib old mode 100644 new mode 100755 index 1271ae1fd..17092f7e8 Binary files a/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib and b/fine-j2v8/src/main/resources/libj2v8-macosx-x86_64.dylib differ diff --git a/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll b/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll old mode 100644 new mode 100755 index 16dc9feb3..578ce7d96 Binary files a/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll and b/fine-j2v8/src/main/resources/libj2v8-windows-x86_64.dll differ diff --git a/fine-j2v8/src/main/resources/libj2v8_win32_x86.dll b/fine-j2v8/src/main/resources/libj2v8_win32_x86.dll deleted file mode 100644 index 02eb0538f..000000000 Binary files a/fine-j2v8/src/main/resources/libj2v8_win32_x86.dll and /dev/null differ diff --git a/fine-log4j/src/main/java/com/fr/third/apache/log4j/DailyRollingFileAppender.java b/fine-log4j/src/main/java/com/fr/third/apache/log4j/DailyRollingFileAppender.java index e23b4bb85..7b4088fa0 100644 --- a/fine-log4j/src/main/java/com/fr/third/apache/log4j/DailyRollingFileAppender.java +++ b/fine-log4j/src/main/java/com/fr/third/apache/log4j/DailyRollingFileAppender.java @@ -24,6 +24,7 @@ import com.fr.third.apache.log4j.spi.LoggingEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; import java.io.InterruptedIOException; import java.text.SimpleDateFormat; @@ -301,79 +302,95 @@ public class DailyRollingFileAppender extends FileAppender { return TOP_OF_TROUBLE; // Deliberately head for trouble... } - /** - Rollover the current file to a new file. - */ - void rollOver() throws IOException { + /** + * Rollover the current file to a new file. + */ + void rollOver() throws IOException { - /* Compute filename, but only if datePattern is specified */ - if (datePattern == null) { - errorHandler.error("Missing DatePattern option in rollOver()."); - return; - } + /* Compute filename, but only if datePattern is specified */ + if (datePattern == null) { + errorHandler.error("Missing DatePattern option in rollOver()."); + return; + } - String datedFilename = fileName+sdf.format(now)+COMPRESS_SUFFIX; - // It is too early to roll over because we are still within the - // bounds of the current interval. Rollover will occur once the - // next interval is reached. - if (scheduledFilename.equals(datedFilename)) { - return; - } + String datedFilename = fileName + sdf.format(now) + COMPRESS_SUFFIX; + // It is too early to roll over because we are still within the + // bounds of the current interval. Rollover will occur once the + // next interval is reached. + if (scheduledFilename.equals(datedFilename)) { + return; + } - // close current file, and compress it to datedFilename - this.closeFile(); + // close current file, and compress it to datedFilename + this.closeFile(); - File target = new File(scheduledFilename); - if (target.exists()) { - target.delete(); - } + File target = new File(scheduledFilename); + if (target.exists()) { + target.delete(); + } - File file = new File(fileName); - boolean result = false; - - FileInputStream fis = null; - FileOutputStream fos = null; - GZIPOutputStream gzos = null; - try { - fis = new FileInputStream(file); - fos = new FileOutputStream(target); - gzos = new GZIPOutputStream(fos); - byte[] inbuf = new byte[8102]; - int n; - - while ((n = fis.read(inbuf)) != -1) { - gzos.write(inbuf, 0, n); + File file = new File(fileName); + boolean isGzipSuccess = false; + + try (FileInputStream fis = new FileInputStream(file); + FileOutputStream fos = new FileOutputStream(target); + GZIPOutputStream gzos = new GZIPOutputStream(fos);) { + byte[] inbuf = new byte[8102]; + int n; + + while ((n = fis.read(inbuf)) != -1) { + gzos.write(inbuf, 0, n); + } + isGzipSuccess = true; + } catch (Exception e) { + LogLog.error("Compress " + fileName + " to " + scheduledFilename + " failed."); + LogLog.error(e.getMessage(), e); } - result = true; - } catch (Exception e){ - LogLog.error("Compress " + fileName + " to " + scheduledFilename + " failed."); - LogLog.error(e.getMessage(), e); - } finally { - if(gzos!=null) { - gzos.close(); + + boolean isDeleteSuccess = true; + if (isGzipSuccess) { + isDeleteSuccess = file.delete(); + LogLog.debug(fileName + " -> " + scheduledFilename); + } else { + LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "]."); + } + + try { + // This will also close the file. This is OK since multiple + // close operations are safe. + this.setFile(fileName, true, this.bufferedIO, this.bufferSize); + } catch (IOException e) { + errorHandler.error("setFile(" + fileName + ", true) call failed."); } - if (fis != null) { - fis.close(); + if(!isDeleteSuccess){ + synchronized (this) { + if (scheduledFilename.equals(datedFilename)) { + return; + } + LogLog.debug("file delete failed, empty it."); + emptyFile(file); + scheduledFilename = datedFilename; + } + }else { + scheduledFilename = datedFilename; } } - if(result) { - file.delete(); - LogLog.debug(fileName +" -> "+ scheduledFilename); - } else { - LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"]."); - } - try { - // This will also close the file. This is OK since multiple - // close operations are safe. - this.setFile(fileName, true, this.bufferedIO, this.bufferSize); - } - catch(IOException e) { - errorHandler.error("setFile("+fileName+", true) call failed."); + /** + * @param file empty file + */ + private static void emptyFile(File file) { + try(FileWriter fileWriter = new FileWriter(file)) { + if (!file.exists()) { + file.createNewFile(); + } + fileWriter.write(""); + fileWriter.flush(); + } catch (IOException e) { + LogLog.debug("empty file failed:" + e.getMessage() + e); + } } - scheduledFilename = datedFilename; - } /** * This method differentiates DailyRollingFileAppender from its