8144841: Add a sample for pluggable dynalink linker for stream property on arrays and a REAMDE for linker samples
authorsundar
Tue, 08 Dec 2015 17:16:10 +0530
changeset 34548 44779bfb4c13
parent 34457 81a65a2faef3
child 34549 412a690d4414
8144841: Add a sample for pluggable dynalink linker for stream property on arrays and a REAMDE for linker samples Reviewed-by: mhaupt, attila
nashorn/samples/ArrayStreamLinkerExporter.java
nashorn/samples/BufferIndexingLinkerExporter.java
nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter
nashorn/samples/MissingMethodExample.java
nashorn/samples/README_dynalink.txt
nashorn/samples/array_stream.js
nashorn/samples/array_stream_linker.js
nashorn/samples/buffer_index.js
nashorn/samples/buffer_indexing_linker.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/ArrayStreamLinkerExporter.java	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.Guards;
+import jdk.dynalink.linker.support.Lookup;
+
+/**
+ * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
+ * This linker adds "stream" property to Java arrays. The appropriate Stream
+ * type object is returned for "stream" property on Java arrays. Note that
+ * the dynalink beans linker just adds "length" property and Java array objects
+ * don't have any other property. "stream" property does not conflict with anything
+ * else!
+ */
+public final class ArrayStreamLinkerExporter extends GuardingDynamicLinkerExporter {
+    static {
+        System.out.println("pluggable dynalink array stream linker loaded");
+    }
+
+    public static Object arrayToStream(Object array) {
+        if (array instanceof int[]) {
+            return IntStream.of((int[])array);
+        } else if (array instanceof long[]) {
+            return LongStream.of((long[])array);
+        } else if (array instanceof double[]) {
+            return DoubleStream.of((double[])array);
+        } else if (array instanceof Object[]) {
+            return Stream.of((Object[])array);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private static final MethodType GUARD_TYPE = MethodType.methodType(Boolean.TYPE, Object.class);
+    private static final MethodHandle ARRAY_TO_STREAM = Lookup.PUBLIC.findStatic(
+            ArrayStreamLinkerExporter.class, "arrayToStream",
+            MethodType.methodType(Object.class, Object.class));
+
+    @Override
+    public List<GuardingDynamicLinker> get() {
+        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
+        linkers.add(new TypeBasedGuardingDynamicLinker() {
+            @Override
+            public boolean canLinkType(final Class<?> type) {
+                return type == Object[].class || type == int[].class ||
+                       type == long[].class || type == double[].class;
+            }
+
+            @Override
+            public GuardedInvocation getGuardedInvocation(LinkRequest request,
+                LinkerServices linkerServices) throws Exception {
+                final Object self = request.getReceiver();
+                if (self == null || !canLinkType(self.getClass())) {
+                    return null;
+                }
+
+                CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                Operation op = desc.getOperation();
+                Object name = NamedOperation.getName(op);
+                boolean getProp = CompositeOperation.contains(
+                        NamedOperation.getBaseOperation(op),
+                        StandardOperation.GET_PROPERTY);
+                if (getProp && "stream".equals(name)) {
+                    return new GuardedInvocation(ARRAY_TO_STREAM,
+                        Guards.isOfClass(self.getClass(), GUARD_TYPE));
+                }
+
+                return null;
+            }
+        });
+        return linkers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/BufferIndexingLinkerExporter.java	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.CompositeOperation;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.Guards;
+import jdk.dynalink.linker.support.Lookup;
+
+/**
+ * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
+ * This linker adds array-like indexing and "length" property to nio Buffer objects.
+ */
+public final class BufferIndexingLinkerExporter extends GuardingDynamicLinkerExporter {
+    static {
+        System.out.println("pluggable dynalink buffer indexing linker loaded");
+    }
+
+    private static final MethodHandle BUFFER_LIMIT;
+    private static final MethodHandle BYTEBUFFER_GET;
+    private static final MethodHandle BYTEBUFFER_PUT;
+    private static final MethodHandle CHARBUFFER_GET;
+    private static final MethodHandle CHARBUFFER_PUT;
+    private static final MethodHandle SHORTBUFFER_GET;
+    private static final MethodHandle SHORTBUFFER_PUT;
+    private static final MethodHandle INTBUFFER_GET;
+    private static final MethodHandle INTBUFFER_PUT;
+    private static final MethodHandle LONGBUFFER_GET;
+    private static final MethodHandle LONGBUFFER_PUT;
+    private static final MethodHandle FLOATBUFFER_GET;
+    private static final MethodHandle FLOATBUFFER_PUT;
+    private static final MethodHandle DOUBLEBUFFER_GET;
+    private static final MethodHandle DOUBLEBUFFER_PUT;
+
+    // guards
+    private static final MethodHandle IS_BUFFER;
+    private static final MethodHandle IS_BYTEBUFFER;
+    private static final MethodHandle IS_CHARBUFFER;
+    private static final MethodHandle IS_SHORTBUFFER;
+    private static final MethodHandle IS_INTBUFFER;
+    private static final MethodHandle IS_LONGBUFFER;
+    private static final MethodHandle IS_FLOATBUFFER;
+    private static final MethodHandle IS_DOUBLEBUFFER;
+
+    private static final MethodType GUARD_TYPE;
+
+    static {
+        Lookup look = Lookup.PUBLIC;
+        BUFFER_LIMIT = look.findVirtual(Buffer.class, "limit", MethodType.methodType(int.class));
+        BYTEBUFFER_GET = look.findVirtual(ByteBuffer.class, "get",
+                MethodType.methodType(byte.class, int.class));
+        BYTEBUFFER_PUT = look.findVirtual(ByteBuffer.class, "put",
+                MethodType.methodType(ByteBuffer.class, int.class, byte.class));
+        CHARBUFFER_GET = look.findVirtual(CharBuffer.class, "get",
+                MethodType.methodType(char.class, int.class));
+        CHARBUFFER_PUT = look.findVirtual(CharBuffer.class, "put",
+                MethodType.methodType(CharBuffer.class, int.class, char.class));
+        SHORTBUFFER_GET = look.findVirtual(ShortBuffer.class, "get",
+                MethodType.methodType(short.class, int.class));
+        SHORTBUFFER_PUT = look.findVirtual(ShortBuffer.class, "put",
+                MethodType.methodType(ShortBuffer.class, int.class, short.class));
+        INTBUFFER_GET = look.findVirtual(IntBuffer.class, "get",
+                MethodType.methodType(int.class, int.class));
+        INTBUFFER_PUT = look.findVirtual(IntBuffer.class, "put",
+                MethodType.methodType(IntBuffer.class, int.class, int.class));
+        LONGBUFFER_GET = look.findVirtual(LongBuffer.class, "get",
+                MethodType.methodType(long.class, int.class));
+        LONGBUFFER_PUT = look.findVirtual(LongBuffer.class, "put",
+                MethodType.methodType(LongBuffer.class, int.class, long.class));
+        FLOATBUFFER_GET = look.findVirtual(FloatBuffer.class, "get",
+                MethodType.methodType(float.class, int.class));
+        FLOATBUFFER_PUT = look.findVirtual(FloatBuffer.class, "put",
+                MethodType.methodType(FloatBuffer.class, int.class, float.class));
+        DOUBLEBUFFER_GET = look.findVirtual(DoubleBuffer.class, "get",
+                MethodType.methodType(double.class, int.class));
+        DOUBLEBUFFER_PUT = look.findVirtual(DoubleBuffer.class, "put",
+                MethodType.methodType(DoubleBuffer.class, int.class, double.class));
+
+        GUARD_TYPE = MethodType.methodType(boolean.class, Object.class);
+        IS_BUFFER = Guards.isInstance(Buffer.class, GUARD_TYPE);
+        IS_BYTEBUFFER = Guards.isInstance(ByteBuffer.class, GUARD_TYPE);
+        IS_CHARBUFFER = Guards.isInstance(CharBuffer.class, GUARD_TYPE);
+        IS_SHORTBUFFER = Guards.isInstance(ShortBuffer.class, GUARD_TYPE);
+        IS_INTBUFFER = Guards.isInstance(IntBuffer.class, GUARD_TYPE);
+        IS_LONGBUFFER = Guards.isInstance(LongBuffer.class, GUARD_TYPE);
+        IS_FLOATBUFFER = Guards.isInstance(FloatBuffer.class, GUARD_TYPE);
+        IS_DOUBLEBUFFER = Guards.isInstance(DoubleBuffer.class, GUARD_TYPE);
+    }
+
+    // locate the first standard operation from the call descriptor
+    private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
+        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
+        if (base instanceof StandardOperation) {
+            return (StandardOperation)base;
+        } else if (base instanceof CompositeOperation) {
+            final CompositeOperation cop = (CompositeOperation)base;
+            for(int i = 0; i < cop.getOperationCount(); ++i) {
+                final Operation op = cop.getOperation(i);
+                if (op instanceof StandardOperation) {
+                    return (StandardOperation)op;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public List<GuardingDynamicLinker> get() {
+        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
+        linkers.add(new TypeBasedGuardingDynamicLinker() {
+            @Override
+            public boolean canLinkType(final Class<?> type) {
+                return Buffer.class.isAssignableFrom(type);
+            }
+
+            @Override
+            public GuardedInvocation getGuardedInvocation(LinkRequest request,
+                LinkerServices linkerServices) throws Exception {
+                final Object self = request.getReceiver();
+                if (self == null || !canLinkType(self.getClass())) {
+                    return null;
+                }
+
+                CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                StandardOperation op = getFirstStandardOperation(desc);
+                if (op == null) {
+                    return null;
+                }
+
+                switch (op) {
+                    case GET_ELEMENT:
+                        return linkGetElement(self);
+                    case SET_ELEMENT:
+                        return linkSetElement(self);
+                    case GET_PROPERTY: {
+                        Object name = NamedOperation.getName(desc.getOperation());
+                        if ("length".equals(name)) {
+                            return linkLength();
+                        }
+                    }
+                }
+
+                return null;
+            }
+        });
+        return linkers;
+    }
+
+    private static GuardedInvocation linkGetElement(Object self) {
+        MethodHandle method = null;
+        MethodHandle guard = null;
+        if (self instanceof ByteBuffer) {
+            method = BYTEBUFFER_GET;
+            guard = IS_BYTEBUFFER;
+        } else if (self instanceof CharBuffer) {
+            method = CHARBUFFER_GET;
+            guard = IS_CHARBUFFER;
+        } else if (self instanceof ShortBuffer) {
+            method = SHORTBUFFER_GET;
+            guard = IS_SHORTBUFFER;
+        } else if (self instanceof IntBuffer) {
+            method = INTBUFFER_GET;
+            guard = IS_INTBUFFER;
+        } else if (self instanceof LongBuffer) {
+            method = LONGBUFFER_GET;
+            guard = IS_LONGBUFFER;
+        } else if (self instanceof FloatBuffer) {
+            method = FLOATBUFFER_GET;
+            guard = IS_FLOATBUFFER;
+        } else if (self instanceof DoubleBuffer) {
+            method = DOUBLEBUFFER_GET;
+            guard = IS_DOUBLEBUFFER;
+        }
+
+        return method != null? new GuardedInvocation(method, guard) : null;
+    }
+
+    private static GuardedInvocation linkSetElement(Object self) {
+        MethodHandle method = null;
+        MethodHandle guard = null;
+        if (self instanceof ByteBuffer) {
+            method = BYTEBUFFER_PUT;
+            guard = IS_BYTEBUFFER;
+        } else if (self instanceof CharBuffer) {
+            method = CHARBUFFER_PUT;
+            guard = IS_CHARBUFFER;
+        } else if (self instanceof ShortBuffer) {
+            method = SHORTBUFFER_PUT;
+            guard = IS_SHORTBUFFER;
+        } else if (self instanceof IntBuffer) {
+            method = INTBUFFER_PUT;
+            guard = IS_INTBUFFER;
+        } else if (self instanceof LongBuffer) {
+            method = LONGBUFFER_PUT;
+            guard = IS_LONGBUFFER;
+        } else if (self instanceof FloatBuffer) {
+            method = FLOATBUFFER_PUT;
+            guard = IS_FLOATBUFFER;
+        } else if (self instanceof DoubleBuffer) {
+            method = DOUBLEBUFFER_PUT;
+            guard = IS_DOUBLEBUFFER;
+        }
+
+        return method != null? new GuardedInvocation(method, guard) : null;
+    }
+
+    private static GuardedInvocation linkLength() {
+        return new GuardedInvocation(BUFFER_LIMIT, IS_BUFFER);
+    }
+}
--- a/nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter	Thu Dec 03 19:04:39 2015 +0530
+++ b/nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter	Tue Dec 08 17:16:10 2015 +0530
@@ -1,3 +1,5 @@
 DOMLinkerExporter
 UnderscoreNameLinkerExporter
 MissingMethodLinkerExporter
+ArrayStreamLinkerExporter
+BufferIndexingLinkerExporter
--- a/nashorn/samples/MissingMethodExample.java	Thu Dec 03 19:04:39 2015 +0530
+++ b/nashorn/samples/MissingMethodExample.java	Tue Dec 08 17:16:10 2015 +0530
@@ -38,7 +38,7 @@
 
     @Override
     public Object doesNotUnderstand(String name, Object... args) {
-        // This dummy doesNotUnderstand just prints method name and args.
+        // This simple doesNotUnderstand just prints method name and args.
         // You can put useful method routing logic here.
         System.out.println("you called " + name);
         if (args.length != 0) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/README_dynalink.txt	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,52 @@
+In addition to samples for Nashorn javascript engine, this directory contains
+samples for Dynalink API (http://openjdk.java.net/jeps/276) as well. Dynalink
+linker samples require a jar file to be built and such jars be placed in the
+classpath of the jjs tool. Linker samples are named with the naming pattern
+"xyz_linker.js". These scripts build dynalink linker jar from java code and exec
+another jjs process with appropriate classpath set.
+
+Note: you need to build jdk9 forest and put "images/jdk/bin" in your PATH to use
+these scripts. This is because these scripts use javac to build dynalink jar and
+exec another jjs with classpath set! Alternatively, you can also manually build
+dynalink linker jars and invoke sample scripts by putting linker jar in jjs tool's
+classpath as well.
+
+Dynalink samples:
+
+* array_stream_linker.js
+
+This sample builds ArrayStreamLinkerExporter.java and uses it in a sample script
+called "array_stream.js". This linker adds "stream" property to Java array
+objects. The "stream" property returns appropriate Stream type for the given
+Java array (IntStream, DoubleStream ...).
+
+* buffer_indexing_linker.js
+
+This sample builds BufferIndexingLinkerExporter.java and uses it in a sample script
+called "buffer_index.js". This linker adds array-like indexed access, indexed assignment
+and "length" property to Java NIO Buffer objects. Script can treat NIO Buffer objects
+as if those are just array objects.
+
+* dom_linker.js
+
+This sample builds DOMLinkerExporter.java and uses it in a sample script
+called "dom_linker_gutenberg.js". This linker handles DOM Element objects to add
+properties to access child elements of a given element by child element tag name.
+This simplifies script access of parsed XML DOM Documents.
+
+* missing_method_linker.js
+
+This sample builds MissingMethodLinkerExporter.java and uses it in a sample script
+called "missing_method.js". This linker supports Smalltalk-style "doesNotUnderstand"
+calls on Java objects. i.e., A Java class can implement MissingMethodHandler interface
+with one method named "doesNotUnderstand". When script accesses a method on such
+object and if that method does not exist in the Java class (or any of it's supertypes),
+then "doesNotUnderstand" method is invoked.
+
+* underscore_linker.js
+
+This sample builds UnderscoreNameLinkerExporter.java and uses it in a sample script
+called "underscore.js". This linker converts underscore separated names to Camel Case
+names (as used in Java APIs). You can call Java APIs using Ruby-like naming convention
+and this linker converts method names to CamelCase!
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/array_stream.js	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,54 @@
+# Usage: jjs -cp array_stream_linker.jar array_stream.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script depends on array stream dynalink linker
+// to work as expected. Without that linker in jjs classpath,
+// this script will fail to run.
+
+// Object[] and then Stream
+var s = Java.to(["hello", "world"]).stream
+s.map(function(s) s.toUpperCase()).forEach(print)
+
+// IntStream
+var is = Java.to([3, 56, 4, 23], "int[]").stream
+print(is.map(function(x) x*x).sum())
+
+// DoubleStream
+var arr = [];
+for (var i = 0; i < 100; i++)
+    arr.push(Math.random())
+
+var ds = Java.to(arr, "double[]").stream
+print(ds.summaryStatistics())
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/array_stream_linker.js	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,49 @@
+#! array stream linker example
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script assumes you've built jdk9 or using latest
+// jdk9 image and put the 'bin' directory in the PATH
+
+$EXEC.throwOnError=true
+
+// compile ArrayStreamLinkerExporter
+`javac -cp ../dist/nashorn.jar ArrayStreamLinkerExporter.java`
+
+// make a jar file out of pluggable linker
+`jar cvf array_stream_linker.jar ArrayStreamLinkerExporter*.class META-INF/`
+
+// run a sample script that uses pluggable linker
+// but make sure classpath points to the pluggable linker jar!
+
+`jjs -cp array_stream_linker.jar array_stream.js`
+print($OUT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/buffer_index.js	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,65 @@
+# Usage: jjs -cp buffer_indexing_linker.jar buffer_index.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script depends on buffer indexing dynalink linker. Without that
+// linker in classpath, this script will fail to run properly.
+
+function str(buf) {
+    var s = ''
+    for (var i = 0; i < buf.length; i++)
+        s += buf[i] + ","
+    return s
+}
+
+var ByteBuffer = Java.type("java.nio.ByteBuffer")
+var bb = ByteBuffer.allocate(10)
+for (var i = 0; i < bb.length; i++)
+    bb[i] = i*i
+print(str(bb))
+
+var CharBuffer = Java.type("java.nio.CharBuffer")
+var cb = CharBuffer.wrap("hello world")
+print(str(cb))
+
+var RandomAccessFile = Java.type("java.io.RandomAccessFile")
+var raf = new RandomAccessFile("buffer_index.js", "r")
+var chan = raf.getChannel()
+var fileSize = chan.size()
+var buf = ByteBuffer.allocate(fileSize)
+chan.read(buf)
+chan.close()
+
+var str = ''
+for (var i = 0; i < buf.length; i++)
+    str += String.fromCharCode(buf[i])
+print(str)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/buffer_indexing_linker.js	Tue Dec 08 17:16:10 2015 +0530
@@ -0,0 +1,49 @@
+# buffer indexing linker example
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This script assumes you've built jdk9 or using latest
+// jdk9 image and put the 'bin' directory in the PATH
+
+$EXEC.throwOnError=true
+
+// compile BufferIndexingLinkerExporter
+`javac -cp ../dist/nashorn.jar BufferIndexingLinkerExporter.java`
+
+// make a jar file out of pluggable linker
+`jar cvf buffer_indexing_linker.jar BufferIndexingLinkerExporter*.class META-INF/`
+
+// run a sample script that uses pluggable linker
+// but make sure classpath points to the pluggable linker jar!
+
+`jjs -cp buffer_indexing_linker.jar buffer_index.js`
+print($OUT)