Codebase list invokebinder / 6c5e5ee
Update upstream source from tag 'upstream/1.12' Update to upstream version '1.12' with Debian dir efd1ae69ef130b1016ffd377cf779cd7bcb1549b Jérôme Charaoui 1 year, 6 months ago
27 changed file(s) with 1213 addition(s) and 116 deletion(s). Raw diff Collapse all Expand all
0 distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
00 language: java
1 matrix:
2 include:
3 - os: linux
4 arch: amd64
5 jdk: openjdk11
6 - os: linux
7 arch: ppc64le
8 jdk: openjdk11
+234
-0
mvnw less more
0 #!/bin/sh
1 # ----------------------------------------------------------------------------
2 # Licensed to the Apache Software Foundation (ASF) under one
3 # or more contributor license agreements. See the NOTICE file
4 # distributed with this work for additional information
5 # regarding copyright ownership. The ASF licenses this file
6 # to you under the Apache License, Version 2.0 (the
7 # "License"); you may not use this file except in compliance
8 # with the License. You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing,
13 # software distributed under the License is distributed on an
14 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 # KIND, either express or implied. See the License for the
16 # specific language governing permissions and limitations
17 # under the License.
18 # ----------------------------------------------------------------------------
19
20 # ----------------------------------------------------------------------------
21 # Maven2 Start Up Batch script
22 #
23 # Required ENV vars:
24 # ------------------
25 # JAVA_HOME - location of a JDK home dir
26 #
27 # Optional ENV vars
28 # -----------------
29 # M2_HOME - location of maven2's installed home dir
30 # MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 # e.g. to debug Maven itself, use
32 # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 # ----------------------------------------------------------------------------
35
36 if [ -z "$MAVEN_SKIP_RC" ] ; then
37
38 if [ -f /etc/mavenrc ] ; then
39 . /etc/mavenrc
40 fi
41
42 if [ -f "$HOME/.mavenrc" ] ; then
43 . "$HOME/.mavenrc"
44 fi
45
46 fi
47
48 # OS specific support. $var _must_ be set to either true or false.
49 cygwin=false;
50 darwin=false;
51 mingw=false
52 case "`uname`" in
53 CYGWIN*) cygwin=true ;;
54 MINGW*) mingw=true;;
55 Darwin*) darwin=true
56 #
57 # Look for the Apple JDKs first to preserve the existing behaviour, and then look
58 # for the new JDKs provided by Oracle.
59 #
60 if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
61 #
62 # Apple JDKs
63 #
64 export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
65 fi
66
67 if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
68 #
69 # Apple JDKs
70 #
71 export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
72 fi
73
74 if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
75 #
76 # Oracle JDKs
77 #
78 export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
79 fi
80
81 if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
82 #
83 # Apple JDKs
84 #
85 export JAVA_HOME=`/usr/libexec/java_home`
86 fi
87 ;;
88 esac
89
90 if [ -z "$JAVA_HOME" ] ; then
91 if [ -r /etc/gentoo-release ] ; then
92 JAVA_HOME=`java-config --jre-home`
93 fi
94 fi
95
96 if [ -z "$M2_HOME" ] ; then
97 ## resolve links - $0 may be a link to maven's home
98 PRG="$0"
99
100 # need this for relative symlinks
101 while [ -h "$PRG" ] ; do
102 ls=`ls -ld "$PRG"`
103 link=`expr "$ls" : '.*-> \(.*\)$'`
104 if expr "$link" : '/.*' > /dev/null; then
105 PRG="$link"
106 else
107 PRG="`dirname "$PRG"`/$link"
108 fi
109 done
110
111 saveddir=`pwd`
112
113 M2_HOME=`dirname "$PRG"`/..
114
115 # make it fully qualified
116 M2_HOME=`cd "$M2_HOME" && pwd`
117
118 cd "$saveddir"
119 # echo Using m2 at $M2_HOME
120 fi
121
122 # For Cygwin, ensure paths are in UNIX format before anything is touched
123 if $cygwin ; then
124 [ -n "$M2_HOME" ] &&
125 M2_HOME=`cygpath --unix "$M2_HOME"`
126 [ -n "$JAVA_HOME" ] &&
127 JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
128 [ -n "$CLASSPATH" ] &&
129 CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
130 fi
131
132 # For Migwn, ensure paths are in UNIX format before anything is touched
133 if $mingw ; then
134 [ -n "$M2_HOME" ] &&
135 M2_HOME="`(cd "$M2_HOME"; pwd)`"
136 [ -n "$JAVA_HOME" ] &&
137 JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
138 # TODO classpath?
139 fi
140
141 if [ -z "$JAVA_HOME" ]; then
142 javaExecutable="`which javac`"
143 if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
144 # readlink(1) is not available as standard on Solaris 10.
145 readLink=`which readlink`
146 if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
147 if $darwin ; then
148 javaHome="`dirname \"$javaExecutable\"`"
149 javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
150 else
151 javaExecutable="`readlink -f \"$javaExecutable\"`"
152 fi
153 javaHome="`dirname \"$javaExecutable\"`"
154 javaHome=`expr "$javaHome" : '\(.*\)/bin'`
155 JAVA_HOME="$javaHome"
156 export JAVA_HOME
157 fi
158 fi
159 fi
160
161 if [ -z "$JAVACMD" ] ; then
162 if [ -n "$JAVA_HOME" ] ; then
163 if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
164 # IBM's JDK on AIX uses strange locations for the executables
165 JAVACMD="$JAVA_HOME/jre/sh/java"
166 else
167 JAVACMD="$JAVA_HOME/bin/java"
168 fi
169 else
170 JAVACMD="`which java`"
171 fi
172 fi
173
174 if [ ! -x "$JAVACMD" ] ; then
175 echo "Error: JAVA_HOME is not defined correctly." >&2
176 echo " We cannot execute $JAVACMD" >&2
177 exit 1
178 fi
179
180 if [ -z "$JAVA_HOME" ] ; then
181 echo "Warning: JAVA_HOME environment variable is not set."
182 fi
183
184 CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
185
186 # For Cygwin, switch paths to Windows format before running java
187 if $cygwin; then
188 [ -n "$M2_HOME" ] &&
189 M2_HOME=`cygpath --path --windows "$M2_HOME"`
190 [ -n "$JAVA_HOME" ] &&
191 JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
192 [ -n "$CLASSPATH" ] &&
193 CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
194 fi
195
196 # traverses directory structure from process work directory to filesystem root
197 # first directory with .mvn subdirectory is considered project base directory
198 find_maven_basedir() {
199 local basedir=$(pwd)
200 local wdir=$(pwd)
201 while [ "$wdir" != '/' ] ; do
202 if [ -d "$wdir"/.mvn ] ; then
203 basedir=$wdir
204 break
205 fi
206 wdir=$(cd "$wdir/.."; pwd)
207 done
208 echo "${basedir}"
209 }
210
211 # concatenates all lines of a file
212 concat_lines() {
213 if [ -f "$1" ]; then
214 echo "$(tr -s '\n' ' ' < "$1")"
215 fi
216 }
217
218 export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
219 MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
220
221 # Provide a "standardized" way to retrieve the CLI args that will
222 # work with both Windows and non-Windows executions.
223 MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
224 export MAVEN_CMD_LINE_ARGS
225
226 WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
227
228 exec "$JAVACMD" \
229 $MAVEN_OPTS \
230 -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
231 "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
232 ${WRAPPER_LAUNCHER} $MAVEN_CMD_LINE_ARGS
233
22 <groupId>com.headius</groupId>
33 <artifactId>invokebinder</artifactId>
44 <packaging>bundle</packaging>
5 <version>1.7</version>
5 <version>1.12</version>
66 <name>invokebinder</name>
77 <url>http://maven.apache.org</url>
88
5050 <Export-Package>com.headius.invokebinder.*</Export-Package>
5151 </instructions>
5252 </configuration>
53 <!-- https://issues.apache.org/jira/browse/FELIX-5698 -->
54 <dependencies>
55 <dependency>
56 <groupId>biz.aQute.bnd</groupId>
57 <artifactId>biz.aQute.bndlib</artifactId>
58 <version>5.2.0</version>
59 </dependency>
60 </dependencies>
5361 </plugin>
5462 <plugin>
5563 <groupId>org.apache.maven.plugins</groupId>
5664 <artifactId>maven-compiler-plugin</artifactId>
57 <version>2.0.2</version>
65 <version>3.7.0</version>
66 <executions>
67 <execution>
68 <id>default-compile</id>
69 <configuration>
70 <includes>
71 <include>module-info.java</include>
72 </includes>
73 <release>9</release>
74 </configuration>
75 </execution>
76 <execution>
77 <id>base-compile</id>
78 <goals>
79 <goal>compile</goal>
80 </goals>
81 <configuration>
82 <excludes>
83 <exclude>module-info.java</exclude>
84 </excludes>
85 </configuration>
86 </execution>
87 </executions>
5888 <configuration>
5989 <source>1.7</source>
6090 <target>1.7</target>
61 <encoding>${project.build.sourceEncoding}</encoding>
6291 </configuration>
6392 </plugin>
6493 <plugin>
6998 <encoding>${project.build.sourceEncoding}</encoding>
7099 </configuration>
71100 </plugin>
101 <plugin>
102 <artifactId>maven-javadoc-plugin</artifactId>
103 <version>3.2.0</version>
104 <configuration>
105 <source>8</source>
106 </configuration>
107 </plugin>
72108 </plugins>
73109 </build>
74110
76112 <dependency>
77113 <groupId>junit</groupId>
78114 <artifactId>junit</artifactId>
79 <version>4.9</version>
115 <version>4.13.1</version>
80116 <scope>test</scope>
81117 </dependency>
82118 </dependencies>
3333 import java.lang.invoke.MethodHandle;
3434 import java.lang.invoke.MethodHandles;
3535 import java.lang.invoke.MethodType;
36 import java.lang.invoke.VarHandle;
3637 import java.lang.reflect.Method;
37 import java.util.ArrayList;
3838 import java.util.Arrays;
39 import java.util.LinkedList;
3940 import java.util.List;
4041 import java.util.ListIterator;
4142 import java.util.logging.Logger;
6768 public class Binder {
6869
6970 private final Logger logger = Logger.getLogger("Invoke Binder");
70 private final List<Transform> transforms = new ArrayList<>();
71 private final List<MethodType> types = new ArrayList<>();
71 private final List<Transform> transforms = new LinkedList<>();
72 private final List<MethodType> types = new LinkedList<>();
7273 private final MethodType start;
7374 private final MethodHandles.Lookup lookup;
7475
879880 }
880881
881882 /**
883 * Box all incoming arguments from the given position onward into the given array type.
884 *
885 * @param index the index from which to start boxing args
886 * @param type the array type into which the args will be boxed
887 * @param collector a function to use for collecting the arguments
888 * @return a new Binder
889 */
890 public Binder collect(int index, Class<?> type, MethodHandle collector) {
891 return new Binder(this, new Collect(type(), index, type, collector));
892 }
893
894 /**
882895 * Box a range of incoming arguments into the given array type.
883896 *
884897 * @param index the index from which to start boxing args
891904 }
892905
893906 /**
907 * Box a range of incoming arguments into the given array type using the given constructor to construct the array.
908 *
909 * The collector signature should match (T1, ..., Tn) where T is the type of the arguments being collected and n
910 * is the number of arguments being collected.
911 *
912 * @param index the index from which to start boxing args
913 * @param count the count of arguments to box
914 * @param type the array type into which the args will be boxed
915 * @param collector a function to use for collecting the arguments
916 * @return a new Binder
917 */
918 public Binder collect(int index, int count, Class<?> type, MethodHandle collector) {
919 return new Binder(this, new Collect(type(), index, count, type, collector));
920 }
921
922 /**
894923 * Box all incoming arguments from the given position onward into the given array type.
895924 * This version accepts a variable number of incoming arguments.
896925 *
926955 return new Binder(this, new Fold(function));
927956 }
928957
958 /**
959 * Process the incoming arguments using the given handle, leaving the argument list
960 * unmodified.
961 *
962 * @param function the function that will process the incoming arguments. Its
963 * signature must match the current signature's arguments exactly.
964 * @return a new Binder
965 */
929966 public Binder foldVoid(MethodHandle function) {
930967 if (type().returnType() == void.class) {
931968 return fold(function);
9831020 }
9841021
9851022 /**
986 * Filter incoming arguments, starting at the given index, replacing each with the
987 * result of calling the associated function in the given list.
1023 * Filter incoming arguments, from the given index, replacing each with the
1024 * result of calling the associated function in the given list. Note that
1025 * the order in which the filters are applied is undefined; OpenJDK produces
1026 * handles that execute them in reverse order.
1027 *
1028 * @see #filterForward(int, MethodHandle...)
9881029 *
9891030 * @param index the index of the first argument to filter
9901031 * @param functions the array of functions to transform the arguments
9921033 */
9931034 public Binder filter(int index, MethodHandle... functions) {
9941035 return new Binder(this, new Filter(index, functions));
1036 }
1037
1038 /**
1039 * Filter incoming arguments, from the given index, replacing each with the
1040 * result of calling the associated function in the given list. This version
1041 * guarantees left-to-right evaluation of filter functions, potentially at
1042 * the cost of a more complex handle tree.
1043 *
1044 * @param index the index of the first argument to filter
1045 * @param functions the array of functions to transform the arguments
1046 * @return a new Binder
1047 */
1048 public Binder filterForward(int index, MethodHandle... functions) {
1049 Binder filtered = this;
1050
1051 for (int i = 0; i < functions.length; i++) {
1052 filtered = filtered.filter(index + i, functions[i]);
1053 }
1054
1055 return filtered;
9951056 }
9961057
9971058 /**
15231584 return invoke(MethodHandles.arrayElementSetter(type().parameterType(0)));
15241585 }
15251586
1587 /**
1588 * Apply the chain of transforms and bind them to a volatile array element set.
1589 *
1590 * @see Binder#arraySet()
1591 * @see VarHandle#setVolatile(Object...)
1592 */
1593 public MethodHandle arraySetVolatile() {
1594 return arrayAccess(VarHandle.AccessMode.SET_VOLATILE);
1595 }
1596
1597 /**
1598 * Apply the chain of transforms and bind them to a release-fenced array element set.
1599 *
1600 * @see Binder#arraySet()
1601 * @see VarHandle#setRelease(Object...)
1602 */
1603 public MethodHandle arraySetAcquire() {
1604 return arrayAccess(VarHandle.AccessMode.SET_RELEASE);
1605 }
1606
1607 /**
1608 * Apply the chain of transforms and bind them to an opaque (no ordering guarantee) array element set.
1609 *
1610 * @see Binder#arraySet()
1611 * @see VarHandle#setVolatile(Object...)
1612 */
1613 public MethodHandle arraySetOpaque() {
1614 return arrayAccess(VarHandle.AccessMode.SET_OPAQUE);
1615 }
1616
15261617
15271618 /**
15281619 * Apply the chain of transforms and bind them to an array element get. The signature
15331624 */
15341625 public MethodHandle arrayGet() {
15351626 return invoke(MethodHandles.arrayElementGetter(type().parameterType(0)));
1627 }
1628
1629 /**
1630 * Apply the chain of transforms and bind them to a volatile array element get.
1631 *
1632 * @see Binder#arrayGet()
1633 * @see VarHandle#getVolatile(Object...)
1634 */
1635 public MethodHandle arrayGetVolatile() {
1636 return arrayAccess(VarHandle.AccessMode.GET_VOLATILE);
1637 }
1638
1639 /**
1640 * Apply the chain of transforms and bind them to an acquire-fenced array element get.
1641 *
1642 * @see Binder#arrayGet()
1643 * @see VarHandle#getAcquire(Object...)
1644 */
1645 public MethodHandle arrayGetAcquire() {
1646 return arrayAccess(VarHandle.AccessMode.GET_ACQUIRE);
1647 }
1648
1649 /**
1650 * Apply the chain of transforms and bind them to an opaque (no ordering guarantee) array element get.
1651 *
1652 * @see Binder#arrayGet()
1653 * @see VarHandle#getVolatile(Object...)
1654 */
1655 public MethodHandle arrayGetOpaque() {
1656 return arrayAccess(VarHandle.AccessMode.GET_OPAQUE);
1657 }
1658
1659 /**
1660 * Apply the chain of transforms and bind them to an array varhandle operation. The
1661 * signature at the endpoint must match the VarHandle access type passed in.
1662 */
1663 public MethodHandle arrayAccess(VarHandle.AccessMode mode) {
1664 return invoke(MethodHandles.arrayElementVarHandle(type().parameterType(0)).toMethodHandle(mode));
15361665 }
15371666
15381667 /**
15591688 return invoke(MethodHandles.invoker(start));
15601689 }
15611690
1691 /**
1692 * Produce Java code that would perform equivalent operations to this binder.
1693 *
1694 * @return Java code for the handle adaptations this Binder would produce.
1695 */
1696 public String toJava(MethodType incoming) {
1697 StringBuilder builder = new StringBuilder();
1698 boolean second = false;
1699 for (Transform transform : transforms) {
1700 if (second) builder.append('\n');
1701 second = true;
1702 builder.append(transform.toJava(incoming));
1703 }
1704 return builder.toString();
1705 }
1706
15621707 }
787787 return offsets;
788788 }
789789
790 @Override
791 public boolean equals(Object o) {
792 if (this == o) return true;
793 if (o == null || getClass() != o.getClass()) return false;
794
795 Signature signature = (Signature) o;
796
797 if (!methodType.equals(signature.methodType)) return false;
798
799 return Arrays.equals(argNames, signature.argNames);
800 }
801
802 @Override
803 public int hashCode() {
804 int result = methodType.hashCode();
805 result = 31 * result + Arrays.hashCode(argNames);
806 return result;
807 }
790808 }
852852 return new SmartBinder(this, newSignature, binder.collect(index, signature().argCount() - (newSignature.argCount() - 1), Array.newInstance(signature().argType(index), 0).getClass()));
853853 }
854854
855 /**
856 * Collect arguments matching namePattern into an trailing array argument
857 * named outName, using collector to construct the array object.
858 *
859 * The collector signature should match (T1, ..., Tn) where T is the type of the arguments being collected and n
860 * is the number of arguments being collected.
861 *
862 * The namePattern is a standard regular expression.
863 *
864 * @param outName the name of the new array argument
865 * @param namePattern a pattern with which to match arguments for collecting
866 * @param collector a function to use for collecting the arguments
867 * @return a new SmartBinder with the collect applied
868 */
869 public SmartBinder collect(String outName, String namePattern, MethodHandle collector) {
870 int index = signature().argOffsets(namePattern);
871
872 assert index >= 0 : "no arguments matching " + namePattern + " found in signature " + signature();
873
874 Signature newSignature = signature().collect(outName, namePattern);
875
876 return new SmartBinder(this, newSignature, binder.collect(index, signature().argCount() - (newSignature.argCount() - 1), Array.newInstance(signature().argType(index), 0).getClass(), collector));
877 }
878
855879 ///////////////////////////////////////////////////////////////////////////
856880 // CASTS, based on MethodHandles.explicitCastArguments and MethodHandle.asType.
857881 ///////////////////////////////////////////////////////////////////////////
11641188
11651189 return new SmartBinder(newSig, newBinder);
11661190 }
1191
1192 /**
1193 * @see Binder#tryFinally(MethodHandle)
1194 */
1195 public SmartBinder tryFinally(MethodHandle post) {
1196 return new SmartBinder(this, signature(), binder.tryFinally(post));
1197 }
11671198 }
0 package com.headius.invokebinder;
1
2 /**
3 * Utilities used by InvokeBinder classes.
4 */
5 public class Util {
6 public static boolean IS_JAVA9;
7
8 static {
9 boolean isJava9;
10 try {
11 Class.forName("java.lang.Module");
12 isJava9 = true;
13 } catch (Exception e) {
14 isJava9 = false;
15 }
16 IS_JAVA9 = isJava9;
17 }
18
19 public static boolean isJava9() {
20 return IS_JAVA9;
21 }
22 }
5353 public String toString() {
5454 return "cast args to " + type;
5555 }
56
57 public String toJava(MethodType incoming) {
58 StringBuilder builder = new StringBuilder("handle = MethodHandles.explicitCastArguments(handle, ");
59 buildClassArguments(builder, type.parameterArray());
60 builder.append(");");
61 return builder.toString();
62 }
63
5664 }
2525 */
2626 public class Catch extends Transform {
2727
28 public static final String EXCEPTION_HANDLER_JAVA = "<exception handler>";
2829 private final Class<? extends Throwable> throwable;
2930 private final MethodHandle function;
3031
4445 public String toString() {
4546 return "catch exception type " + throwable + " using " + function;
4647 }
48
49 public String toJava(MethodType incoming) {
50 StringBuilder builder = new StringBuilder("handle = MethodHandles.catchException(handle, ");
51 buildClassArgument(builder, throwable);
52 builder.append(", ").append(EXCEPTION_HANDLER_JAVA).append(");");
53 return builder.toString();
54 }
4755 }
1717 import com.headius.invokebinder.Binder;
1818
1919 import java.lang.invoke.MethodHandle;
20 import java.lang.invoke.MethodHandles;
2021 import java.lang.invoke.MethodType;
2122
2223 /**
2324 * An argument-boxing transform with a fixed incoming size.
2425 *
25 * Equivalent call: MethodHandle.asCollector(Class, int)
26 * Equivalent call: MethodHandle.asCollector(Class, int) or MethodHandles.collectArguments
2627 */
2728 public class Collect extends Transform {
2829
3031 private final int index;
3132 private final int count;
3233 private final Class<?> arrayType;
34 private final MethodHandle collector;
3335
3436 public Collect(MethodType source, int index, Class<?> arrayType) {
3537 this.source = source;
3638 this.index = index;
3739 this.count = source.parameterCount() - index;
3840 this.arrayType = arrayType;
41 this.collector = null;
42 }
43
44 public Collect(MethodType source, int index, Class<?> arrayType, MethodHandle collector) {
45 this.source = source;
46 this.index = index;
47 this.count = source.parameterCount() - index;
48 this.arrayType = arrayType;
49 this.collector = collector;
3950 }
4051
4152 public Collect(MethodType source, int index, int count, Class<?> arrayType) {
4354 this.index = index;
4455 this.count = count;
4556 this.arrayType = arrayType;
57 this.collector = null;
58 }
59
60 public Collect(MethodType source, int index, int count, Class<?> arrayType, MethodHandle collector) {
61 this.source = source;
62 this.index = index;
63 this.count = count;
64 this.arrayType = arrayType;
65 this.collector = collector;
4666 }
4767
4868 public MethodHandle up(MethodHandle target) {
49 if (index + count == source.parameterCount()) {
69 if (onlyTail()) {
5070 // fast path for tail args
51 return target.asCollector(arrayType, count);
52 } else {
53 int[] movePermute = new int[source.parameterCount()];
54 int[] moveBackPermute = new int[target.type().parameterCount()];
55 // pre
56 for (int i = 0; i < index; i++) {
57 movePermute[i] = i;
58 moveBackPermute[i] = i;
71 if (collector == null) {
72 return target.asCollector(arrayType, count);
5973 }
6074
61 // post
62 int shifted = 0;
63 for (int i = index; i + count < movePermute.length; i++, shifted++) movePermute[i] = i + count;
64 for (int i = index; i + 1 < moveBackPermute.length; i++) moveBackPermute[i + 1] = i;
75 return MethodHandles.collectArguments(target, index, collector);
76 } else {
77 Permutes permutes = buildPermutes(source, target.type());
6578
66 // collected args
67 for (int i = index + shifted; i < movePermute.length; i++) movePermute[i] = i - shifted;
68 moveBackPermute[index] = moveBackPermute.length - 1;
79 Binder binder = preparePermuteBinder(permutes);
80 return binder.invoke(target);
81 }
82 }
6983
70 return Binder.from(source)
71 .permute(movePermute)
72 .collect(source.parameterCount() - count, arrayType)
73 .permute(moveBackPermute)
74 .invoke(target);
75 }
84 private Binder preparePermuteBinder(Permutes permutes) {
85 return Binder.from(source)
86 .permute(permutes.movePermute)
87 .collect(source.parameterCount() - count, arrayType, collector)
88 .permute(permutes.moveBackPermute);
7689 }
7790
7891 public MethodType down(MethodType type) {
95108 public String toString() {
96109 return "collect at " + index + " into " + arrayType.getName();
97110 }
111
112 public String toJava(MethodType incoming) {
113 StringBuilder builder = new StringBuilder();
114 if (onlyTail()) {
115 if (collector == null) {
116 builder.append("handle = handle.asCollector(");
117 buildClassArgument(builder, arrayType);
118 builder
119 .append(", ")
120 .append(count)
121 .append(");");
122 } else {
123 builder.append("handle = MethodHandles.collectArguments(");
124
125 builder
126 .append("handle, ")
127 .append(count)
128 .append(", ");
129
130 buildClassArgument(builder, arrayType);
131
132 builder.append(");");
133 }
134 } else {
135 Permutes permutes = buildPermutes(source, incoming);
136
137 Binder binder = preparePermuteBinder(permutes);
138 return binder.toJava(incoming);
139 }
140 return builder.toString();
141 }
142
143 private boolean onlyTail() {
144 return index + count == source.parameterCount();
145 }
146
147 private static class Permutes {
148 private final int[] movePermute;
149 private final int[] moveBackPermute;
150
151 private Permutes(MethodType source, MethodType target, int index, int count) {
152 movePermute = new int[source.parameterCount()];
153 moveBackPermute = new int[target.parameterCount()];
154 // pre
155 for (int i = 0; i < index; i++) {
156 movePermute[i] = i;
157 moveBackPermute[i] = i;
158 }
159
160 // post
161 int shifted = 0;
162 for (int i = index; i + count < movePermute.length; i++, shifted++) movePermute[i] = i + count;
163 for (int i = index; i + 1 < moveBackPermute.length; i++) moveBackPermute[i + 1] = i;
164
165 // collected args
166 for (int i = index + shifted; i < movePermute.length; i++) movePermute[i] = i - shifted;
167 moveBackPermute[index] = moveBackPermute.length - 1;
168 }
169 }
170
171 private Permutes buildPermutes(MethodType source, MethodType target) {
172 return new Permutes(source, target, index, count);
173 }
98174 }
5252 public String toString() {
5353 return "convert args to " + type;
5454 }
55
56 public String toJava(MethodType incoming) {
57 String methodTypeJava = generateMethodType(type);
58
59 if (incoming.returnType() == void.class) {
60 return "handle = MethodHandles.explicitCastArguments(handle.asType(" + methodTypeJava + ", " + methodTypeJava + ");";
61 }
62
63 return "handle = handle.asType(" + methodTypeJava + ");";
64 }
5565 }
4545 public String toString() {
4646 return "drop " + Arrays.toString(types) + " at " + position;
4747 }
48
49 public String toJava(MethodType incoming) {
50 StringBuilder builder = new StringBuilder("handle = MethodHandles.dropArguments(handle, ");
51
52 builder.append(position).append(", ");
53 buildClassArguments(builder, types);
54 builder.append(");");
55
56 return builder.toString();
57 }
4858 }
2525 * Equivalent call: MethodHandles.filterArguments(MethodHandle, int, MethodHandle...).
2626 */
2727 public class Filter extends Transform {
28
2928 private final int index;
3029 private final MethodHandle[] functions;
30
31 public static final String FILTER_FUNCTIONS_JAVA = "<filter functions>";
3132
3233 public Filter(int index, MethodHandle... functions) {
3334 this.index = index;
4849 public String toString() {
4950 return "fold args from " + index + " with " + Arrays.toString(functions);
5051 }
52
53 public String toJava(MethodType incoming) {
54 return "handle = MethodHandles.filterArguments(handle, " + index + ", " + FILTER_FUNCTIONS_JAVA + ");";
55 }
5156 }
2626 * Equivalent call: MethodHandles.filterReturn(MethodHandle, MethodHandle).
2727 */
2828 public class FilterReturn extends Transform {
29 private final MethodHandle function;
2930
30 private final MethodHandle function;
31 public static final String FILTER_FUNCTION_JAVA = "<filter function>";
3132
3233 public FilterReturn(MethodHandle function) {
3334 this.function = function;
5253 public String toString() {
5354 return "filter return with " + function;
5455 }
56
57 public String toJava(MethodType incoming) {
58 return "handle = MethodHandles.filterReturnValue(handle, " + FILTER_FUNCTION_JAVA + ");";
59 }
5560 }
2424 * Equivalent call: MethodHandles.foldArguments(MethodHandle, MethodHandle).
2525 */
2626 public class Fold extends Transform {
27 private final MethodHandle function;
2728
28 private final MethodHandle function;
29 public static final String FOLD_FUNCTION_JAVA = "<fold function>";
2930
3031 public Fold(MethodHandle function) {
3132 this.function = function;
4344 public String toString() {
4445 return "fold args with " + function;
4546 }
47
48 public String toJava(MethodType incoming) {
49 return "handle = MethodHandles.foldArguments(handle, " + FOLD_FUNCTION_JAVA + ");";
50 }
4651 }
106106 return "insert " + Arrays.toString(types()) + " at " + position;
107107 }
108108
109 public String toJava(MethodType incoming) {
110 StringBuilder builder = new StringBuilder("handle = MethodHandles.insertArguments(handle, ");
111 builder
112 .append(position)
113 .append(", ");
114
115 // we cast all arguments since natural type will frequently be wrong
116 boolean second = false;
117 for (int i = 0; i < types.length; i++) {
118 if (second) builder.append(", ");
119 second = true;
120
121 buildClassCast(builder, types[i]);
122 if (types[i].isPrimitive()) {
123 buildPrimitiveJava(builder, values[i]);
124 } else {
125 builder.append("value").append(i + 1);
126 }
127 }
128 builder.append(");");
129
130 return builder.toString();
131 }
132
109133 private Class<?>[] types() {
110134 Class<?>[] types = new Class<?>[values.length];
111135 for (int i = 0; i < types.length; i++) {
5656 public String toString() {
5757 return "permute " + source + " with " + Arrays.toString(reorder);
5858 }
59
60 public String toJava(MethodType incoming) {
61 StringBuilder builder = new StringBuilder("handle = MethodHandles.permuteArguments(handle, ");
62
63 String reorder = Arrays.toString(this.reorder);
64 reorder = reorder.substring(1, reorder.length() - 1);
65
66 builder.append(generateMethodType(source) + ", new int[] {" + reorder + "});");
67
68 return builder.toString();
69 }
70
5971 }
5151 public String toString() {
5252 return "spread " + source + " to " + down(source);
5353 }
54
55 public String toJava(MethodType incoming) {
56 StringBuilder builder = new StringBuilder("handle = handle.asSpreader(");
57
58 buildClassArgument(builder, source.parameterType(source.parameterCount() - 1));
59 builder
60 .append(", ")
61 .append(spreadTypes.length);
62
63 builder.append(");");
64
65 return builder.toString();
66 }
5467 }
4545 * @return a string representation of this transform
4646 */
4747 public abstract String toString();
48
49 /**
50 * Return a Java code representation of this transform.
51 *
52 * @return a Java code representation of this transform.
53 */
54 public abstract String toJava(MethodType incoming);
55
56 /**
57 * Build a list of argument type classes suitable for inserting into Java code.
58 *
59 * This will be an argument list of the form "pkg.Cls1.class, pkg.Cls2[].class, primtype.class, ..."
60 *
61 * @param builder the builder in which to build the argument list
62 * @param types the classes from which to create the argument list
63 */
64 protected static void buildClassArguments(StringBuilder builder, Class<?>[] types) {
65 boolean second = false;
66 for (Class cls : types) {
67 if (second) builder.append(", ");
68 second = true;
69 buildClassArgument(builder, cls);
70 }
71 }
72
73 /**
74 * Build Java code to represent a single .class reference.
75 *
76 * This will be an argument of the form "pkg.Cls1.class" or "pkg.Cls2[].class" or "primtype.class"
77 *
78 * @param builder the builder in which to build the argument
79 * @param cls the type for the argument
80 */
81 protected static void buildClassArgument(StringBuilder builder, Class cls) {
82 buildClass(builder, cls);
83 builder.append(".class");
84 }
85
86 /**
87 * Build Java code to represent a cast to the given type.
88 *
89 * This will be an argument of the form "(pkg.Cls1)" or "(pkg.Cls2[])" or "(primtype)"
90 *
91 * @param builder the builder in which to build the argument
92 * @param cls the type for the argument
93 */
94 protected static void buildClassCast(StringBuilder builder, Class cls) {
95 builder.append('(');
96 buildClass(builder, cls);
97 builder.append(')');
98 }
99
100 /**
101 * Build Java code to represent a literal primitive.
102 *
103 * This will append L or F as appropriate for long and float primitives.
104 *
105 * @param builder the builder in which to generate the code
106 * @param value the primitive value to generate from
107 */
108 protected static void buildPrimitiveJava(StringBuilder builder, Object value) {
109 builder.append(value.toString());
110 if (value.getClass() == Float.class) builder.append('F');
111 if (value.getClass() == Long.class) builder.append('L');
112 }
113
114 /**
115 * Build Java code to represent a type reference to the given class.
116 *
117 * This will be of the form "pkg.Cls1" or "pkc.Cls2[]" or "primtype".
118 *
119 * @param builder the builder in which to build the type reference
120 * @param cls the type for the reference
121 */
122 private static void buildClass(StringBuilder builder, Class cls) {
123 int arrayDims = 0;
124 Class tmp = cls;
125 while (tmp.isArray()) {
126 arrayDims++;
127 tmp = tmp.getComponentType();
128 }
129 builder.append(tmp.getName());
130 if (arrayDims > 0) {
131 for (; arrayDims > 0 ; arrayDims--) {
132 builder.append("[]");
133 }
134 }
135 }
136
137 /**
138 * Build Java code appropriate for standing up the given MethodType.
139 *
140 * @param source the MethodType for which to build Java code
141 * @return Java code suitable for building the given MethodType
142 */
143 public static String generateMethodType(MethodType source) {
144 StringBuilder builder = new StringBuilder("MethodType.methodType(");
145 buildClassArgument(builder, source.returnType());
146 if (source.parameterCount() > 0) {
147 builder.append(", ");
148 buildClassArguments(builder, source.parameterArray());
149 }
150 builder.append(")");
151 return builder.toString();
152 }
48153 }
1515 package com.headius.invokebinder.transform;
1616
1717 import com.headius.invokebinder.Binder;
18 import com.headius.invokebinder.Util;
1819
1920 import java.lang.invoke.MethodHandle;
2021 import java.lang.invoke.MethodHandles;
2122 import java.lang.invoke.MethodType;
23 import java.lang.reflect.InvocationTargetException;
2224
2325 /**
2426 * An try-finally transform.
3335
3436 private final MethodHandle post;
3537
38 private static final MethodHandle tryFinallyJava9;
39
3640 public TryFinally(MethodHandle post) {
3741 this.post = post;
3842 }
3943
4044 public MethodHandle up(MethodHandle target) {
45 if (Util.isJava9()) return nativeTryFinally(target, post);
46
4147 MethodHandle exceptionHandler = Binder
4248 .from(target.type().insertParameterTypes(0, Throwable.class).changeReturnType(void.class))
4349 .drop(0)
7177 return MethodHandles.foldArguments(realPost, target);
7278 }
7379
80 private MethodHandle nativeTryFinally(MethodHandle target, MethodHandle post) {
81 MethodType targetType = target.type();
82 boolean voidReturn = targetType.returnType() == Void.TYPE;
83 MethodType finallyType = targetType.insertParameterTypes(0, Throwable.class);
84 int dropCount = 1;
85
86 if (!voidReturn) {
87 finallyType = finallyType.insertParameterTypes(1, targetType.returnType());
88 dropCount = 2;
89 }
90
91 MethodHandle wrapPost = Binder
92 .from(finallyType)
93 .drop(0, dropCount)
94 .invoke(post);
95
96 if (!voidReturn) {
97 wrapPost = Binder.from(finallyType)
98 .foldVoid(wrapPost)
99 .permute(1)
100 .identity();
101 }
102
103 try {
104 return (MethodHandle) tryFinallyJava9.invokeExact(target, wrapPost);
105 } catch (Throwable t) {
106 throw new RuntimeException("Java 9 detected but MethodHandles.tryFinally missing", t);
107 }
108 }
109
74110 public MethodType down(MethodType type) {
75111 return type;
76112 }
78114 public String toString() {
79115 return "try/finally with " + post;
80116 }
117
118 public String toJava(MethodType incoming) {
119 throw new RuntimeException("TryFinally does not yet support toJava");
120 }
121
122 static {
123 if (Util.isJava9()) {
124 tryFinallyJava9 = Binder.from(MethodHandle.class, MethodHandle.class, MethodHandle.class).invokeStaticQuiet(MethodHandles.lookup(), MethodHandles.class, "tryFinally");
125 } else {
126 tryFinallyJava9 = null;
127 }
128 }
81129 }
5858 public String toString() {
5959 return "varargs at " + index + " into " + arrayType.getName();
6060 }
61
62 public String toJava(MethodType incoming) {
63 StringBuilder builder = new StringBuilder("handle = handle.asVarargsCollector(");
64
65 buildClassArgument(builder, arrayType);
66 builder.append(").asType(");
67 builder.append(generateMethodType(source));
68 builder.append(");");
69
70 return builder.toString();
71 }
6172 }
0 module com.headius.invokebinder {
1 requires java.base;
2 requires java.logging;
3
4 exports com.headius.invokebinder;
5 }
00 package com.headius.invokebinder;
11
22 import org.junit.Test;
3
4 import static java.lang.invoke.MethodType.methodType;
35 import static org.junit.Assert.*;
46
57 import java.io.ByteArrayOutputStream;
79 import java.lang.invoke.MethodHandle;
810 import java.lang.invoke.MethodHandles;
911 import java.lang.invoke.MethodHandles.Lookup;
10 import java.lang.invoke.MethodType;
12 import java.lang.invoke.VarHandle;
1113 import java.lang.reflect.Method;
1214
1315 /**
1517 */
1618 public class BinderTest {
1719 private static final Lookup LOOKUP = MethodHandles.lookup();
20
1821 @Test
1922 public void testFrom() throws Throwable {
2023 MethodHandle target = Subjects.concatHandle();
2831 .insert(1, "world")
2932 .invoke(target);
3033
31 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle.type());
34 assertEquals(methodType(String.class, String.class, Object.class), handle.type());
3235 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object()));
3336 }
3437
3740 Binder b1 = Binder
3841 .from(void.class)
3942 .insert(0, true);
40 assertEquals(MethodType.methodType(void.class, boolean.class), b1.type());
43 assertEquals(methodType(void.class, boolean.class), b1.type());
4144 Binder b2 = Binder
4245 .from(void.class)
4346 .insert(0, (byte)1);
44 assertEquals(MethodType.methodType(void.class, byte.class), b2.type());
47 assertEquals(methodType(void.class, byte.class), b2.type());
4548 Binder b3 = Binder
4649 .from(void.class)
4750 .insert(0, (short)1);
48 assertEquals(MethodType.methodType(void.class, short.class), b3.type());
51 assertEquals(methodType(void.class, short.class), b3.type());
4952 Binder b4 = Binder
5053 .from(void.class)
5154 .insert(0, (char)1);
52 assertEquals(MethodType.methodType(void.class, char.class), b4.type());
55 assertEquals(methodType(void.class, char.class), b4.type());
5356 Binder b5 = Binder
5457 .from(void.class)
5558 .insert(0, 1);
56 assertEquals(MethodType.methodType(void.class, int.class), b5.type());
59 assertEquals(methodType(void.class, int.class), b5.type());
5760 Binder b6 = Binder
5861 .from(void.class)
5962 .insert(0, 1L);
60 assertEquals(MethodType.methodType(void.class, long.class), b6.type());
63 assertEquals(methodType(void.class, long.class), b6.type());
6164 Binder b7 = Binder
6265 .from(void.class)
6366 .insert(0, 1.0F);
64 assertEquals(MethodType.methodType(void.class, float.class), b7.type());
67 assertEquals(methodType(void.class, float.class), b7.type());
6568 Binder b8 = Binder
6669 .from(void.class)
6770 .insert(0, 1.0);
68 assertEquals(MethodType.methodType(void.class, double.class), b8.type());
71 assertEquals(methodType(void.class, double.class), b8.type());
6972
7073 MethodHandle target = intLongHandle();
7174
7477 .insert(0, new Class[]{int.class, long.class}, 1, 1L)
7578 .invoke(target);
7679
77 assertEquals(MethodType.methodType(String.class), handle.type());
80 assertEquals(methodType(String.class), handle.type());
7881 assertEquals("intLong ok", (String) handle.invokeExact());
7982 }
8083
9295
9396 Binder newBinder = thisBinder.to(otherBinder);
9497
95 assertEquals(MethodType.methodType(String.class, String.class, String.class), otherBinder.type());
96 assertEquals(MethodType.methodType(String.class, String.class, int.class), thisBinder.type());
97 assertEquals(MethodType.methodType(String.class, String.class, String.class), newBinder.type());
98 assertEquals(methodType(String.class, String.class, String.class), otherBinder.type());
99 assertEquals(methodType(String.class, String.class, int.class), thisBinder.type());
100 assertEquals(methodType(String.class, String.class, String.class), newBinder.type());
98101
99102 MethodHandle target = newBinder.invoke(Subjects.concatHandle());
100103
106109 Binder binder = Binder
107110 .from(String.class, String.class, Integer.class);
108111
109 assertEquals(MethodType.methodType(String.class, String.class, Integer.class), binder.type());
112 assertEquals(methodType(String.class, String.class, Integer.class), binder.type());
110113
111114 binder = binder
112115 .drop(1);
113116
114 assertEquals(MethodType.methodType(String.class, String.class), binder.type());
117 assertEquals(methodType(String.class, String.class), binder.type());
115118 }
116119
117120 @Test
141144 .insert(1, "world")
142145 .invoke(target);
143146
144 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
147 assertEquals(methodType(String.class, String.class), handle.type());
145148 assertEquals("Hello, world", (String) handle.invokeExact("Hello, "));
146149
147150 MethodHandle target2 = Subjects.concatCharSequenceHandle();
150153 .insert(1, CharSequence.class, "world")
151154 .invoke(target2);
152155
153 assertEquals(MethodType.methodType(String.class, String.class), handle2.type());
156 assertEquals(methodType(String.class, String.class), handle2.type());
154157 assertEquals("Hello, world", (String) handle2.invokeExact("Hello, "));
155158 }
156159
163166 .drop(1)
164167 .invoke(target);
165168
166 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle.type());
169 assertEquals(methodType(String.class, String.class, Object.class), handle.type());
167170 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object()));
168171
169172 MethodHandle target2 = Subjects.concatCharSequenceHandle();
173176 .drop(1)
174177 .invoke(target2);
175178
176 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle2.type());
179 assertEquals(methodType(String.class, String.class, Object.class), handle2.type());
177180 assertEquals("Hello, world", (String) handle2.invokeExact("Hello, ", new Object()));
178181 }
179182
186189 .drop(1)
187190 .invoke(target);
188191
189 assertEquals(MethodType.methodType(String.class, Object.class, String.class), handle.type());
192 assertEquals(methodType(String.class, Object.class, String.class), handle.type());
190193 assertEquals("Hello, world", (String) handle.invokeExact(new Object(), "world"));
191194
192195 MethodHandle target2 = Subjects.concatHandle();
196199 .drop(1)
197200 .invoke(target2);
198201
199 assertEquals(MethodType.methodType(String.class, Object.class, String.class), handle2.type());
202 assertEquals(methodType(String.class, Object.class, String.class), handle2.type());
200203 assertEquals("Hello, world", (String) handle2.invokeExact(new Object(), "world"));
201204 }
202205
209212 .insert(1, "world")
210213 .invoke(target);
211214
212 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle.type());
215 assertEquals(methodType(String.class, String.class, Object.class), handle.type());
213216 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object()));
214217 }
215218
222225 .insert(1, "world")
223226 .invoke(target);
224227
225 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle.type());
228 assertEquals(methodType(String.class, String.class, Object.class), handle.type());
226229 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object()));
227230
228231 handle = Binder
231234 .insert(1, "world")
232235 .invoke(target);
233236
234 assertEquals(MethodType.methodType(String.class, String.class, Object.class, double.class), handle.type());
237 assertEquals(methodType(String.class, String.class, Object.class, double.class), handle.type());
235238 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object(), 1.0));
236239 }
237240
244247 .insert(1, "world")
245248 .invoke(target);
246249
247 assertEquals(MethodType.methodType(String.class, Object.class, String.class), handle.type());
250 assertEquals(methodType(String.class, Object.class, String.class), handle.type());
248251 assertEquals("Hello, world", (String) handle.invokeExact(new Object(), "Hello, "));
249252
250253 handle = Binder
253256 .insert(1, "world")
254257 .invoke(target);
255258
256 assertEquals(MethodType.methodType(String.class, Object.class, double.class, String.class), handle.type());
259 assertEquals(methodType(String.class, Object.class, double.class, String.class), handle.type());
257260 assertEquals("Hello, world", (String) handle.invokeExact(new Object(), 1.0, "Hello, "));
258261 }
259262
266269 .insert(0, "Hello, ", "world")
267270 .invoke(target);
268271
269 assertEquals(MethodType.methodType(String.class, String.class, Object.class), handle.type());
272 assertEquals(methodType(String.class, String.class, Object.class), handle.type());
270273 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", new Object()));
271274 }
272275
278281 .convert(target.type())
279282 .invoke(target);
280283
281 assertEquals(MethodType.methodType(String.class, Object.class, Integer.class, Float.class), handle.type());
284 assertEquals(methodType(String.class, Object.class, Integer.class, Float.class), handle.type());
282285 assertEquals(null, (String) handle.invokeExact((Object) "foo", (Integer) 5, (Float) 5.0f));
283286 }
284287
290293 .convert(target.type().returnType(), target.type().parameterArray())
291294 .invoke(target);
292295
293 assertEquals(MethodType.methodType(String.class, Object.class, Integer.class, Float.class), handle.type());
296 assertEquals(methodType(String.class, Object.class, Integer.class, Float.class), handle.type());
294297 assertEquals(null, (String)handle.invokeExact((Object)"foo", (Integer)5, (Float)5.0f));
295298 }
296299
302305 .cast(target.type())
303306 .invoke(target);
304307
305 assertEquals(MethodType.methodType(String.class, Object.class, byte.class, int.class), handle.type());
308 assertEquals(methodType(String.class, Object.class, byte.class, int.class), handle.type());
306309 assertEquals(null, (String)handle.invokeExact((Object)"foo", (byte)5, 5));
307310 }
308311
314317 .cast(target.type().returnType(), target.type().parameterArray())
315318 .invoke(target);
316319
317 assertEquals(MethodType.methodType(String.class, Object.class, byte.class, int.class), handle.type());
320 assertEquals(methodType(String.class, Object.class, byte.class, int.class), handle.type());
318321 assertEquals(null, (String)handle.invokeExact((Object)"foo", (byte)5, 5));
319322 }
320323
327330 .permute(0, 0)
328331 .invoke(target);
329332
330 assertEquals(MethodType.methodType(String.class, Integer.class, Float.class, String.class), handle.type());
333 assertEquals(methodType(String.class, Integer.class, Float.class, String.class), handle.type());
331334 assertEquals("foofoo", (String)handle.invokeExact((Integer) 0, (Float) 0.0f, "foo"));
332335 }
333336
339342 .spread(String.class, String.class)
340343 .invoke(target);
341344
342 assertEquals(MethodType.methodType(String.class, Object[].class), handle.type());
345 assertEquals(methodType(String.class, Object[].class), handle.type());
343346 assertEquals("foobar", (String)handle.invokeExact(new Object[] {"foo", "bar"}));
344347 }
345348
351354 .spread(2)
352355 .invoke(target);
353356
354 assertEquals(MethodType.methodType(String.class, String[].class), handle.type());
357 assertEquals(methodType(String.class, String[].class), handle.type());
355358 assertEquals("foobar", (String)handle.invokeExact(new String[] {"foo", "bar"}));
356359 }
357360
362365 .collect(1, String[].class)
363366 .invokeStatic(LOOKUP, BinderTest.class, "varargs");
364367
365 assertEquals(MethodType.methodType(String[].class, String.class, String.class, String.class), handle.type());
368 assertEquals(methodType(String[].class, String.class, String.class, String.class), handle.type());
366369 String[] ary = (String[])handle.invokeExact("one", "two", "three");
367370 assertEquals(2, ary.length);
368371 assertEquals("two", ary[0]);
373376 .collect(1, 3, Integer[].class)
374377 .invoke(Subjects.StringIntegersStringHandle);
375378
376 assertEquals(MethodType.methodType(String.class, String.class, Integer.class, Integer.class, Integer.class, String.class), handle2.type());
379 assertEquals(methodType(String.class, String.class, Integer.class, Integer.class, Integer.class, String.class), handle2.type());
377380 assertEquals("[foo, [1, 2, 3], bar]", (String)handle2.invokeExact("foo", new Integer(1), new Integer(2), new Integer(3), "bar"));
378381 }
379382
380 @Test
381 public void testVarargs() throws Throwable {
382 MethodHandle handle = Binder
383 public static String[] newStringArray(String s1, String s2) {
384 return new String[] {s1, s2};
385 }
386
387 public static MethodHandle newStringArrayHandle() throws Exception {
388 return LOOKUP.findStatic(BinderTest.class, "newStringArray", methodType(String[].class, String.class, String.class));
389 }
390
391 @Test
392 public void testCollectWithCollector() throws Throwable {
393 Binder binder = Binder
383394 .from(String[].class, String.class, String.class, String.class)
384 .varargs(1, String[].class)
395 .collect(1, String[].class, newStringArrayHandle());
396
397 String toJava = binder.toJava(methodType(String[].class, String.class, String.class, String.class));
398
399 assertTrue(toJava.contains("collectArguments"));
400
401 MethodHandle handle = binder
385402 .invokeStatic(LOOKUP, BinderTest.class, "varargs");
386403
387 assertEquals(MethodType.methodType(String[].class, String.class, String.class, String.class), handle.type());
404 assertEquals(methodType(String[].class, String.class, String.class, String.class), handle.type());
388405 String[] ary = (String[])handle.invokeExact("one", "two", "three");
389406 assertEquals(2, ary.length);
390407 assertEquals("two", ary[0]);
391408 assertEquals("three", ary[1]);
409 }
410
411 @Test
412 public void testVarargs() throws Throwable {
413 MethodHandle handle = Binder
414 .from(String[].class, String.class, String.class, String.class)
415 .varargs(1, String[].class)
416 .invokeStatic(LOOKUP, BinderTest.class, "varargs");
417
418 assertEquals(methodType(String[].class, String.class, String.class, String.class), handle.type());
419 String[] ary = (String[])handle.invokeExact("one", "two", "three");
420 assertEquals(2, ary.length);
421 assertEquals("two", ary[0]);
422 assertEquals("three", ary[1]);
392423
393424 // from #2
394 MethodHandle foo = Binder.from(MethodType.methodType(String.class, String.class))
425 MethodHandle foo = Binder.from(methodType(String.class, String.class))
395426 .varargs(0, Object[].class)
396427 .invokeStatic(MethodHandles.publicLookup(), getClass(), "varargs");
397428
404435 .from(String.class)
405436 .constant("hello");
406437
407 assertEquals(MethodType.methodType(String.class), handle.type());
438 assertEquals(methodType(String.class), handle.type());
408439 assertEquals("hello", (String)handle.invokeExact());
409440 }
410441
414445 .from(Object.class)
415446 .constant("hello");
416447
417 assertEquals(MethodType.methodType(Object.class), handle.type());
448 assertEquals(methodType(Object.class), handle.type());
418449 assertEquals("hello", (Object)handle.invokeExact());
419450 }
420451
424455 .from(String.class, String.class)
425456 .identity();
426457
427 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
458 assertEquals(methodType(String.class, String.class), handle.type());
428459 assertEquals("hello", (String)handle.invokeExact("hello"));
429460 }
430461
440471 .fold(fold)
441472 .invoke(target);
442473
443 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
474 assertEquals(methodType(String.class, String.class), handle.type());
444475 assertEquals("yahoofoo", (String)handle.invokeExact("foo"));
445476 }
446477
452483 .foldStatic(BinderTest.class, "alwaysYahooStatic")
453484 .invoke(target);
454485
455 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
486 assertEquals(methodType(String.class, String.class), handle.type());
456487 assertEquals("yahoofoo", (String)handle.invokeExact("foo"));
457488 }
458489
466497 .drop(1)
467498 .invoke(target);
468499
469 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
500 assertEquals(methodType(String.class, String.class), handle.type());
470501 assertEquals("yahoofoo", (String)handle.invokeExact("foo"));
471502 }
472503
473504 @Test
474505 public void testFilter() throws Throwable {
475506 MethodHandle target = Subjects.concatHandle();
476 MethodHandle filter = LOOKUP.findStatic(BinderTest.class, "addBaz", MethodType.methodType(String.class, String.class));
507 MethodHandle filter = LOOKUP.findStatic(BinderTest.class, "addBaz", methodType(String.class, String.class));
477508 MethodHandle handle = Binder
478509 .from(String.class, String.class, String.class)
479510 .filter(0, filter, filter)
480511 .invoke(target);
481512
482 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
513 assertEquals(methodType(String.class, String.class, String.class), handle.type());
483514 assertEquals("foobazbarbaz", (String)handle.invokeExact("foo", "bar"));
484515 }
485516
486517 @Test
518 public void testFilterForward() throws Throwable {
519 MethodHandle target = LOOKUP.findStatic(Subjects.class, "twoIntsToString", methodType(String.class, int.class, int.class));
520 MethodHandle[] filters = {Subjects.nextInt, Subjects.nextInt};
521 MethodHandle handle = Binder.from(String.class, int.class, int.class)
522 .filterForward(0, filters)
523 .invoke(target);
524
525 int first = Subjects.counter.get();
526
527 assertEquals("(" + first + ", " + (first + 1) + ")", (String) handle.invokeExact(0, 0));
528 }
529
530 @Test
487531 public void testInvoke() throws Throwable {
488532 MethodHandle target = Subjects.concatHandle();
489533 MethodHandle handle = Binder
490534 .from(String.class, String.class, String.class)
491535 .invoke(target);
492536
493 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
537 assertEquals(methodType(String.class, String.class, String.class), handle.type());
494538 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", "world"));
495539 }
496540
501545 .from(String.class, String.class, String.class)
502546 .invoke(LOOKUP, target);
503547
504 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
548 assertEquals(methodType(String.class, String.class, String.class), handle.type());
505549 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", "world"));
506550 }
507551
512556 .from(String.class, String.class, String.class)
513557 .invokeQuiet(LOOKUP, target);
514558
515 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
559 assertEquals(methodType(String.class, String.class, String.class), handle.type());
516560 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", "world"));
517561 }
518562
522566 .from(String.class, String.class, String.class)
523567 .invokeStatic(LOOKUP, Subjects.class, "concatStatic");
524568
525 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
569 assertEquals(methodType(String.class, String.class, String.class), handle.type());
526570 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", "world"));
527571 }
528572
532576 .from(String.class, String.class, String.class)
533577 .invokeStaticQuiet(LOOKUP, Subjects.class, "concatStatic");
534578
535 assertEquals(MethodType.methodType(String.class, String.class, String.class), handle.type());
579 assertEquals(methodType(String.class, String.class, String.class), handle.type());
536580 assertEquals("Hello, world", (String) handle.invokeExact("Hello, ", "world"));
537581 }
538582
542586 .from(String.class, BinderTest.class, String.class, String.class)
543587 .invokeVirtual(LOOKUP, "concatVirtual");
544588
545 assertEquals(MethodType.methodType(String.class, BinderTest.class, String.class, String.class), handle.type());
589 assertEquals(methodType(String.class, BinderTest.class, String.class, String.class), handle.type());
546590 assertEquals("Hello, world", (String) handle.invokeExact(this, "Hello, ", "world"));
547591 }
548592
552596 .from(String.class, BinderTest.class, String.class, String.class)
553597 .invokeVirtualQuiet(LOOKUP, "concatVirtual");
554598
555 assertEquals(MethodType.methodType(String.class, BinderTest.class, String.class, String.class), handle.type());
599 assertEquals(methodType(String.class, BinderTest.class, String.class, String.class), handle.type());
556600 assertEquals("Hello, world", (String) handle.invokeExact(this, "Hello, ", "world"));
557601 }
558602
562606 .from(Constructable.class, String.class, String.class)
563607 .invokeConstructor(LOOKUP, Constructable.class);
564608
565 assertEquals(MethodType.methodType(Constructable.class, String.class, String.class), handle.type());
609 assertEquals(methodType(Constructable.class, String.class, String.class), handle.type());
566610 assertEquals(new Constructable("foo", "bar"), (Constructable) handle.invokeExact("foo", "bar"));
567611 }
568612
572616 .from(Constructable.class, String.class, String.class)
573617 .invokeConstructorQuiet(LOOKUP, Constructable.class);
574618
575 assertEquals(MethodType.methodType(Constructable.class, String.class, String.class), handle.type());
619 assertEquals(methodType(Constructable.class, String.class, String.class), handle.type());
576620 assertEquals(new Constructable("foo", "bar"), (Constructable) handle.invokeExact("foo", "bar"));
577621 }
578622
583627 .from(String.class, Fields.class)
584628 .getField(LOOKUP, "instanceField");
585629
586 assertEquals(MethodType.methodType(String.class, Fields.class), handle.type());
630 assertEquals(methodType(String.class, Fields.class), handle.type());
587631 assertEquals("initial", (String)handle.invokeExact(fields));
588632 }
589633
594638 .from(String.class, Fields.class)
595639 .getFieldQuiet(LOOKUP, "instanceField");
596640
597 assertEquals(MethodType.methodType(String.class, Fields.class), handle.type());
641 assertEquals(methodType(String.class, Fields.class), handle.type());
598642 assertEquals("initial", (String)handle.invokeExact(fields));
599643 }
600644
604648 .from(String.class)
605649 .getStatic(LOOKUP, Fields.class, "staticField");
606650
607 assertEquals(MethodType.methodType(String.class), handle.type());
651 assertEquals(methodType(String.class), handle.type());
608652 assertEquals("initial", (String)handle.invokeExact());
609653 }
610654
614658 .from(String.class)
615659 .getStaticQuiet(LOOKUP, Fields.class, "staticField");
616660
617 assertEquals(MethodType.methodType(String.class), handle.type());
661 assertEquals(methodType(String.class), handle.type());
618662 assertEquals("initial", (String)handle.invokeExact());
619663 }
620664
625669 .from(void.class, Fields.class, String.class)
626670 .setField(LOOKUP, "instanceField");
627671
628 assertEquals(MethodType.methodType(void.class, Fields.class, String.class), handle.type());
672 assertEquals(methodType(void.class, Fields.class, String.class), handle.type());
629673 handle.invokeExact(fields, "modified");
630674 assertEquals("modified", fields.instanceField);
631675 }
637681 .from(void.class, Fields.class, String.class)
638682 .setFieldQuiet(LOOKUP, "instanceField");
639683
640 assertEquals(MethodType.methodType(void.class, Fields.class, String.class), handle.type());
684 assertEquals(methodType(void.class, Fields.class, String.class), handle.type());
641685 handle.invokeExact(fields, "modified");
642686 assertEquals("modified", fields.instanceField);
643687 }
649693 .from(void.class, String.class)
650694 .setStatic(LOOKUP, Fields.class, "staticField");
651695
652 assertEquals(MethodType.methodType(void.class, String.class), handle.type());
696 assertEquals(methodType(void.class, String.class), handle.type());
653697 handle.invokeExact("modified");
654698 assertEquals("modified", Fields.staticField);
655699 } finally {
664708 .from(void.class, String.class)
665709 .setStaticQuiet(LOOKUP, Fields.class, "staticField");
666710
667 assertEquals(MethodType.methodType(void.class, String.class), handle.type());
711 assertEquals(methodType(void.class, String.class), handle.type());
668712 handle.invokeExact("modified");
669713 assertEquals("modified", Fields.staticField);
670714 } finally {
678722 .from(void.class, int.class, String.class)
679723 .nop();
680724
681 assertEquals(MethodType.methodType(void.class, int.class, String.class), handle.type());
725 assertEquals(methodType(void.class, int.class, String.class), handle.type());
682726 try {
683727 handle.invokeExact(1, "foo");
684728 } catch (Throwable t) {
692736 .from(void.class, BlahException.class)
693737 .throwException();
694738
695 assertEquals(MethodType.methodType(void.class, BlahException.class), handle.type());
739 assertEquals(methodType(void.class, BlahException.class), handle.type());
696740 try {
697741 handle.invokeExact(new BlahException());
698742 assertTrue("should not reach here", false);
711755 .tryFinally(post)
712756 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFoo");
713757
714 assertEquals(MethodType.methodType(void.class, String[].class), handle.type());
758 assertEquals(methodType(void.class, String[].class), handle.type());
715759 String[] stringAry = new String[1];
716760 handle.invokeExact(stringAry);
717761 assertEquals("foofinally", stringAry[0]);
728772 .tryFinally(post)
729773 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFooAndRaise");
730774
731 assertEquals(MethodType.methodType(void.class, String[].class), handle.type());
775 assertEquals(methodType(void.class, String[].class), handle.type());
732776 String[] stringAry = new String[1];
733777 try {
734778 handle.invokeExact(stringAry);
754798 .catchException(BlahException.class, ignoreException)
755799 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFooAndRaise");
756800
757 assertEquals(MethodType.methodType(void.class, String[].class), handle.type());
801 assertEquals(methodType(void.class, String[].class), handle.type());
758802 String[] stringAry = new String[1];
759803 try {
760804 handle.invokeExact(stringAry);
775819 .tryFinally(post)
776820 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFooReturnInt");
777821
778 assertEquals(MethodType.methodType(int.class, String[].class), handle.type());
822 assertEquals(methodType(int.class, String[].class), handle.type());
779823 String[] stringAry = new String[1];
780824 assertEquals(1, (int)handle.invokeExact(stringAry));
781825 assertEquals("foofinally", stringAry[0]);
792836 .tryFinally(post)
793837 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFooReturnIntAndRaise");
794838
795 assertEquals(MethodType.methodType(int.class, String[].class), handle.type());
839 assertEquals(methodType(int.class, String[].class), handle.type());
796840 String[] stringAry = new String[1];
797841 try {
798842 int x = (int)handle.invokeExact(stringAry);
819863 .catchException(BlahException.class, ignoreException)
820864 .invokeStatic(LOOKUP, BinderTest.class, "setZeroToFooReturnIntAndRaise");
821865
822 assertEquals(MethodType.methodType(int.class, String[].class), handle.type());
866 assertEquals(methodType(int.class, String[].class), handle.type());
823867 String[] stringAry = new String[1];
824868 try {
825869 assertEquals(1, (int)handle.invokeExact(stringAry));
835879 .from(void.class, Object[].class, int.class, Object.class)
836880 .arraySet();
837881
838 assertEquals(MethodType.methodType(void.class, Object[].class, int.class, Object.class), handle.type());
882 assertEquals(methodType(void.class, Object[].class, int.class, Object.class), handle.type());
839883 Object[] ary = new Object[1];
840884 handle.invokeExact(ary, 0, (Object)"foo");
841885 assertEquals(ary[0], "foo");
847891 .from(Object.class, Object[].class, int.class)
848892 .arrayGet();
849893
850 assertEquals(MethodType.methodType(Object.class, Object[].class, int.class), handle.type());
894 assertEquals(methodType(Object.class, Object[].class, int.class), handle.type());
851895 Object[] ary = new Object[] {"foo"};
852896 assertEquals(handle.invokeExact(ary, 0), "foo");
897 }
898
899 public static final VarHandle.AccessMode[] GET_ACCESS_MODES = new VarHandle.AccessMode[]{
900 VarHandle.AccessMode.GET,
901 VarHandle.AccessMode.GET_VOLATILE,
902 VarHandle.AccessMode.GET_ACQUIRE,
903 VarHandle.AccessMode.GET_OPAQUE};
904
905 public static final VarHandle.AccessMode[] SET_ACCESS_MODES = new VarHandle.AccessMode[]{
906 VarHandle.AccessMode.SET,
907 VarHandle.AccessMode.SET_VOLATILE,
908 VarHandle.AccessMode.SET_RELEASE,
909 VarHandle.AccessMode.SET_OPAQUE};
910
911 @Test
912 public void testArrayAccess() throws Throwable {
913 for (VarHandle.AccessMode mode : GET_ACCESS_MODES) {
914 MethodHandle handle = Binder
915 .from(Object.class, Object[].class, int.class)
916 .arrayAccess(mode);
917
918 assertEquals(methodType(Object.class, Object[].class, int.class), handle.type());
919 Object[] ary = new Object[]{"foo"};
920 assertEquals(handle.invokeExact(ary, 0), "foo");
921 }
922
923 for (VarHandle.AccessMode mode : SET_ACCESS_MODES) {
924 MethodHandle handle = Binder
925 .from(void.class, Object[].class, int.class, Object.class)
926 .arrayAccess(mode);
927
928 assertEquals(methodType(void.class, Object[].class, int.class, Object.class), handle.type());
929 Object[] ary = new Object[1];
930 handle.invokeExact(ary, 0, (Object) "foo");
931 assertEquals(ary[0], "foo");
932 }
853933 }
854934
855935 @Test
868948 .invokeStatic(LOOKUP, BinderTest.class, "addBaz")
869949 );
870950
871 assertEquals(MethodType.methodType(String.class, String.class), handle.type());
951 assertEquals(methodType(String.class, String.class), handle.type());
872952 assertEquals("foobar", (String)handle.invokeExact("foo"));
873953 assertEquals("quuxbaz", (String)handle.invokeExact("quux"));
874954 }
876956 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
877957
878958 public static MethodHandle intLongHandle() throws Exception {
879 return LOOKUP.findStatic(BinderTest.class, "intLong", MethodType.methodType(String.class, int.class, long.class));
959 return LOOKUP.findStatic(BinderTest.class, "intLong", methodType(String.class, int.class, long.class));
880960 }
881961
882962 public String concatVirtual(String a, String b) {
9561036 }
9571037
9581038 public static MethodHandle mixedHandle() throws Exception {
959 return LOOKUP.findStatic(BinderTest.class, "mixed", MethodType.methodType(void.class, String.class, int.class, float.class));
1039 return LOOKUP.findStatic(BinderTest.class, "mixed", methodType(void.class, String.class, int.class, float.class));
9601040 }
9611041
9621042 public static void mixed(String a, int b, float c) {
33 import java.lang.invoke.MethodHandles;
44 import java.lang.invoke.MethodType;
55 import java.util.Arrays;
6 import java.util.concurrent.atomic.AtomicInteger;
67
78 /**
89 * Created by headius on 1/25/14.
7980 public static String upperCase(String x) {
8081 return x.toUpperCase();
8182 }
83
84 public static String twoIntsToString(int a, int b) {
85 return "(" + a + ", " + b + ")";
86 }
87
88 public static int nextInt(int ignored) {
89 return counter.getAndIncrement();
90 }
91
92 public static MethodHandle nextInt = Binder.from(int.class, int.class).invokeStaticQuiet(LOOKUP, Subjects.class, "nextInt");
93
94 public static final AtomicInteger counter = new AtomicInteger(0);
8295
8396 }
0 package com.headius.invokebinder;
1
2 import com.headius.invokebinder.transform.Cast;
3 import com.headius.invokebinder.transform.Catch;
4 import com.headius.invokebinder.transform.Collect;
5 import com.headius.invokebinder.transform.Convert;
6 import com.headius.invokebinder.transform.Drop;
7 import com.headius.invokebinder.transform.Filter;
8 import com.headius.invokebinder.transform.FilterReturn;
9 import com.headius.invokebinder.transform.Fold;
10 import com.headius.invokebinder.transform.Insert;
11 import com.headius.invokebinder.transform.Spread;
12 import com.headius.invokebinder.transform.Transform;
13 import com.headius.invokebinder.transform.Varargs;
14 import org.junit.Assert;
15 import org.junit.Test;
16
17 import java.lang.invoke.MethodHandle;
18 import java.lang.invoke.MethodHandles;
19 import java.lang.invoke.MethodType;
20
21 public class ToJavaTest {
22 @Test
23 public void testCast() {
24 Cast cast = new Cast(MethodType.methodType(String.class, Integer[].class, float.class));
25
26 String toJava = cast.toJava(null);
27
28 Assert.assertEquals("handle = MethodHandles.explicitCastArguments(handle, java.lang.Integer[].class, float.class);", toJava);
29 }
30
31 @Test
32 public void testCatch() {
33 Catch ctch = new Catch(RuntimeException.class, DUMMY_HANDLE);
34
35 String toJava = ctch.toJava(null);
36
37 Assert.assertEquals("handle = MethodHandles.catchException(handle, java.lang.RuntimeException.class, " + Catch.EXCEPTION_HANDLER_JAVA + ");", toJava);
38 }
39
40 @Test
41 public void testCollect() {
42 MethodType source = MethodType.methodType(void.class, int.class, int.class, int.class);
43 MethodType incoming = MethodType.methodType(void.class, int.class, int[].class);
44
45 Collect collect = new Collect(source, 1, int[].class);
46
47 String toJava = collect.toJava(incoming);
48
49 Assert.assertEquals("handle = handle.asCollector(int[].class, 2);", toJava);
50
51 collect = new Collect(source, 1, 1, int[].class);
52
53 toJava = collect.toJava(incoming);
54
55 String expected =
56 "handle = MethodHandles.permuteArguments(handle, MethodType.methodType(void.class, int.class, int.class, int[].class), new int[] {0, 1});\n" +
57 "handle = handle.asCollector(int[].class, 1);\n" +
58 "handle = MethodHandles.permuteArguments(handle, MethodType.methodType(void.class, int.class, int.class, int.class), new int[] {0, 2, 1});";
59
60 Assert.assertEquals(expected, toJava);
61 }
62
63 @Test
64 public void testConvert() {
65 MethodType source = MethodType.methodType(void.class, String.class);
66 MethodType incoming = MethodType.methodType(void.class, Object.class);
67
68 Convert convert = new Convert(source);
69
70 String toJava = convert.toJava(incoming);
71
72 String expected = "handle = MethodHandles.explicitCastArguments(handle.asType(MethodType.methodType(void.class, java.lang.String.class), MethodType.methodType(void.class, java.lang.String.class));";
73
74 Assert.assertEquals(expected, toJava);
75
76 source = MethodType.methodType(long.class, String.class);
77 incoming = MethodType.methodType(int.class, Object.class);
78
79 convert = new Convert(source);
80
81 toJava = convert.toJava(incoming);
82
83 Assert.assertEquals("handle = handle.asType(MethodType.methodType(long.class, java.lang.String.class));", toJava);
84 }
85
86 @Test
87 public void testDrop() {
88 MethodType incoming = MethodType.methodType(void.class);
89
90 Drop drop = new Drop(0, int.class, int.class, int.class);
91
92 String toJava = drop.toJava(incoming);
93
94 Assert.assertEquals("handle = MethodHandles.dropArguments(handle, 0, int.class, int.class, int.class);", toJava);
95 }
96
97 @Test
98 public void testFilter() {
99 Filter filter = new Filter(0, null);
100
101 String toJava = filter.toJava(DUMMY_HANDLE.type());
102
103 Assert.assertEquals("handle = MethodHandles.filterArguments(handle, 0, " + Filter.FILTER_FUNCTIONS_JAVA + ");", toJava);
104 }
105
106 @Test
107 public void testFilterReturn() {
108 FilterReturn filterReturn = new FilterReturn(DUMMY_HANDLE);
109
110 String toJava = filterReturn.toJava(null);
111
112 Assert.assertEquals("handle = MethodHandles.filterReturnValue(handle, " + FilterReturn.FILTER_FUNCTION_JAVA + ");", toJava);
113 }
114
115 @Test
116 public void testFold() {
117 Fold fold = new Fold(DUMMY_HANDLE);
118
119 String toJava = fold.toJava(null);
120
121 Assert.assertEquals("handle = MethodHandles.foldArguments(handle, " + Fold.FOLD_FUNCTION_JAVA + ");", toJava);
122 }
123
124 @Test
125 public void testInsert() {
126 Insert insert = new Insert(0, new Class[] {int.class, double.class, Object.class}, 1L, 1.0F, "hello");
127
128 String toJava = insert.toJava(null);
129
130 Assert.assertEquals("handle = MethodHandles.insertArguments(handle, 0, (int)1L, (double)1.0F, (java.lang.Object)value3);", toJava);
131 }
132
133 @Test
134 public void testSpread() {
135 Spread spread = new Spread(OBJECTARRAY_HANDLE.type(), Object.class, String.class, Integer.class);
136
137 String toJava = spread.toJava(null);
138
139 Assert.assertEquals("handle = handle.asSpreader(java.lang.Object[].class, 3);", toJava);
140 }
141
142 @Test
143 public void testVarargs() {
144 Varargs varargs = new Varargs(OBJECTS_HANDLE.type(), 0, Object[].class);
145
146 String toJava = varargs.toJava(null);
147
148 Assert.assertEquals("handle = handle.asVarargsCollector(java.lang.Object[].class).asType(" + Transform.generateMethodType(OBJECTS_HANDLE.type()) + ");", toJava);
149 }
150
151 public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
152
153 private static final MethodHandle DUMMY_HANDLE = Binder.from(void.class).invokeStaticQuiet(LOOKUP, ToJavaTest.class, "dummy");
154 private static void dummy() {}
155
156 private static final MethodHandle OBJECTARRAY_HANDLE = Binder.from(void.class, Object[].class).invokeStaticQuiet(LOOKUP, ToJavaTest.class, "objectArray");
157 private static void objectArray(Object[] ary) {}
158
159 private static final MethodHandle OBJECTS_HANDLE = Binder.from(void.class, Object.class, Object.class, Object.class).invokeStaticQuiet(LOOKUP, ToJavaTest.class, "objects");
160 private static void objects(Object o, Object p, Object q) {}
161 }