forked from sheetjs/docs.sheetjs.com
		
	
		
			
	
	
		
			205 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			205 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|  | --- | ||
|  | title: Java + Nashorn | ||
|  | pagination_prev: demos/bigdata/index | ||
|  | pagination_next: solutions/input | ||
|  | --- | ||
|  | 
 | ||
|  | import Tabs from '@theme/Tabs'; | ||
|  | import TabItem from '@theme/TabItem'; | ||
|  | 
 | ||
|  | Nashorn is a JavaScript engine for Java.  It shipped with Java distributions | ||
|  | starting with Java 8 and was eventually removed in Java 15. The project was | ||
|  | spun off and a compatible standalone release is available for Java 15+. | ||
|  | 
 | ||
|  | The [Standalone scripts](/docs/getting-started/installation/standalone) can be | ||
|  | parsed and evaluated in a Nashorn context. | ||
|  | 
 | ||
|  | ## Integration Details
 | ||
|  | 
 | ||
|  | _Initialize Nashorn_ | ||
|  | 
 | ||
|  | `global` must be created from a Nashorn engine: | ||
|  | 
 | ||
|  | ```java | ||
|  | import javax.script.ScriptEngine; | ||
|  | import javax.script.ScriptEngineManager; | ||
|  | import java.nio.file.Files; | ||
|  | import java.nio.file.Paths; | ||
|  | import java.util.Scanner; | ||
|  | 
 | ||
|  | /* initialize nashorn engine */ | ||
|  | ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript"); | ||
|  | 
 | ||
|  | /* create global */ | ||
|  | engine.eval("var global = (function(){ return this; }).call(null);"); | ||
|  | ``` | ||
|  | 
 | ||
|  | _Load SheetJS Scripts_ | ||
|  | 
 | ||
|  | The main library can be loaded by reading the script from the file system and | ||
|  | evaluating in the Nashorn context: | ||
|  | 
 | ||
|  | ```java | ||
|  | engine.eval(new Scanner( | ||
|  |   SheetJS.class.getResourceAsStream("/xlsx.full.min.js") | ||
|  | ).useDelimiter("\\Z").next()); | ||
|  | ``` | ||
|  | 
 | ||
|  | To confirm the library is loaded, `XLSX.version` can be printed using the | ||
|  | Nashorn `print` built-in: | ||
|  | 
 | ||
|  | ```java | ||
|  | engine.eval("print('SheetJS Version ' + XLSX.version);"); | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Reading Files
 | ||
|  | 
 | ||
|  | Nashorn does not properly project `byte[]` into a JS array or `Int8Array`. The | ||
|  | recommended workaround is to copy the data in the JS context using the JS code: | ||
|  | 
 | ||
|  | ```js | ||
|  | function b2a(b) { | ||
|  |   var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length); | ||
|  |   /* `b` is similar to Int8Array (values in the range -128 .. 127 ) */ | ||
|  |   for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF; | ||
|  |   return out; | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | This function should be embedded in the Java code: | ||
|  | 
 | ||
|  | ```java | ||
|  | /* read spreadsheet bytes */ | ||
|  | engine.put("bytes", Files.readAllBytes(Paths.get(args[0]))); | ||
|  | 
 | ||
|  | /* convert signed byte array to JS Uint8Array or unsigned byte array */ | ||
|  | engine.eval( | ||
|  |   "function b2a(b) {" + | ||
|  |     "var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" + | ||
|  |     "for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" + | ||
|  |     "return out;" + | ||
|  |   "}" + | ||
|  |   "var u8a = b2a(bytes)" | ||
|  | ); | ||
|  | 
 | ||
|  | /* parse workbook */ | ||
|  | engine.eval("var wb = XLSX.read(u8a, {type: 'array'})"); | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Complete Example
 | ||
|  | 
 | ||
|  | :::note | ||
|  | 
 | ||
|  | This demo was last tested on 2023 March 27 using: | ||
|  | 
 | ||
|  | - OpenJDK 19.0.1  + Nashorn 15.4 standalone | ||
|  | - OpenJDK 11.0.18 + Official Nashorn | ||
|  | 
 | ||
|  | ::: | ||
|  | 
 | ||
|  | <Tabs groupId="java"> | ||
|  |   <TabItem value="stdlib" label="Java 8 - 14"> | ||
|  | 
 | ||
|  | Nashorn is available without additional dependencies | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  |   <TabItem value="standalone" label="Java 15+"> | ||
|  | 
 | ||
|  | 0) Download Nashorn and its dependencies: | ||
|  | 
 | ||
|  | ```bash | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/openjdk/nashorn/nashorn-core/15.4/nashorn-core-15.4.jar" | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/9.5/asm-9.5.jar" | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar" | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar" | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-analysis/9.5/asm-analysis-9.5.jar" | ||
|  | curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/9.5/asm-util-9.5.jar" | ||
|  | ``` | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  | </Tabs> | ||
|  | 
 | ||
|  | 1) Download the standalone script, shim script, and the test file: | ||
|  | 
 | ||
|  | <ul> | ||
|  | <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||
|  | <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li> | ||
|  | <li><a href="https://sheetjs.com/pres.xlsx">pres.xlsx</a></li> | ||
|  | </ul> | ||
|  | 
 | ||
|  | ```bash | ||
|  | curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js | ||
|  | curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js | ||
|  | curl -LO https://sheetjs.com/pres.xlsx | ||
|  | ``` | ||
|  | 
 | ||
|  | 2) Download [`SheetJSNashorn.java`](pathname:///nashorn/SheetJSNashorn.java): | ||
|  | 
 | ||
|  | ```bash | ||
|  | curl -LO https://docs.sheetjs.com/nashorn/SheetJSNashorn.java | ||
|  | ``` | ||
|  | 
 | ||
|  | 3) Build the sample class: | ||
|  | 
 | ||
|  | ```bash | ||
|  | javac SheetJSNashorn.java | ||
|  | ``` | ||
|  | 
 | ||
|  | This program tries to parse the file specified by the first argument | ||
|  | 
 | ||
|  | 4) Run the command directly: | ||
|  | 
 | ||
|  | <Tabs groupId="java"> | ||
|  |   <TabItem value="stdlib" label="Java 8 - 14"> | ||
|  | 
 | ||
|  | ```bash | ||
|  | java SheetJSNashorn pres.xlsx | ||
|  | ``` | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  |   <TabItem value="standalone" label="Java 15+"> | ||
|  | 
 | ||
|  | ```bash | ||
|  | java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar SheetJSNashorn pres.xlsx | ||
|  | ``` | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  | </Tabs> | ||
|  | 
 | ||
|  | 
 | ||
|  | 5) Assemble a Java Archive: | ||
|  | 
 | ||
|  | ```bash | ||
|  | jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js | ||
|  | ``` | ||
|  | 
 | ||
|  | 6) Verify the Java Archive. | ||
|  | 
 | ||
|  | Create new directory and copy the archives and test file: | ||
|  | 
 | ||
|  | ```bash | ||
|  | mkdir -p sheethorn | ||
|  | cp *.jar pres.xlsx sheethorn | ||
|  | cd sheethorn | ||
|  | ``` | ||
|  | 
 | ||
|  | Invoke the command in the archive: | ||
|  | 
 | ||
|  | <Tabs groupId="java"> | ||
|  |   <TabItem value="stdlib" label="Java 8 - 14"> | ||
|  | 
 | ||
|  | ```bash | ||
|  | java -cp .:SheetJSNashorn.jar SheetJSNashorn pres.xlsx | ||
|  | ``` | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  |   <TabItem value="standalone" label="Java 15+"> | ||
|  | 
 | ||
|  | ```bash | ||
|  | java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar:SheetJSNashorn.jar SheetJSNashorn pres.xlsx | ||
|  | ``` | ||
|  | 
 | ||
|  |   </TabItem> | ||
|  | </Tabs> | ||
|  | 
 |