|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
8 * - Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * |
|
11 * - Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * |
|
15 * - Neither the name of Oracle nor the names of its |
|
16 * contributors may be used to endorse or promote products derived |
|
17 * from this software without specific prior written permission. |
|
18 * |
|
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
|
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
|
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
30 */ |
|
31 |
|
32 import java.lang.invoke.MethodHandle; |
|
33 import java.lang.invoke.MethodHandles; |
|
34 import java.lang.invoke.MethodType; |
|
35 import java.util.ArrayList; |
|
36 import java.util.List; |
|
37 import java.util.regex.Pattern; |
|
38 import java.util.regex.Matcher; |
|
39 import jdk.dynalink.CallSiteDescriptor; |
|
40 import jdk.dynalink.CompositeOperation; |
|
41 import jdk.dynalink.NamedOperation; |
|
42 import jdk.dynalink.Operation; |
|
43 import jdk.dynalink.CompositeOperation; |
|
44 import jdk.dynalink.StandardOperation; |
|
45 import jdk.dynalink.linker.GuardingDynamicLinker; |
|
46 import jdk.dynalink.linker.GuardingDynamicLinkerExporter; |
|
47 import jdk.dynalink.linker.GuardedInvocation; |
|
48 import jdk.dynalink.linker.LinkRequest; |
|
49 import jdk.dynalink.linker.LinkerServices; |
|
50 import jdk.dynalink.linker.support.SimpleLinkRequest; |
|
51 |
|
52 /** |
|
53 * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). |
|
54 * This linker translater underscore_separated method names to CamelCase names |
|
55 * used in Java APIs. |
|
56 */ |
|
57 public final class UnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter { |
|
58 static { |
|
59 System.out.println("pluggable dynalink underscore name linker loaded"); |
|
60 } |
|
61 |
|
62 private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)"); |
|
63 |
|
64 // translate underscore_separated name as a CamelCase name |
|
65 private static String translateToCamelCase(String name) { |
|
66 Matcher m = UNDERSCORE_NAME.matcher(name); |
|
67 StringBuilder buf = new StringBuilder(); |
|
68 while (m.find()) { |
|
69 m.appendReplacement(buf, m.group(1).toUpperCase()); |
|
70 } |
|
71 m.appendTail(buf); |
|
72 return buf.toString(); |
|
73 } |
|
74 |
|
75 // locate the first standard operation from the call descriptor |
|
76 private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) { |
|
77 final Operation base = NamedOperation.getBaseOperation(desc.getOperation()); |
|
78 if (base instanceof StandardOperation) { |
|
79 return (StandardOperation)base; |
|
80 } else if (base instanceof CompositeOperation) { |
|
81 final CompositeOperation cop = (CompositeOperation)base; |
|
82 for(int i = 0; i < cop.getOperationCount(); ++i) { |
|
83 final Operation op = cop.getOperation(i); |
|
84 if (op instanceof StandardOperation) { |
|
85 return (StandardOperation)op; |
|
86 } |
|
87 } |
|
88 } |
|
89 return null; |
|
90 } |
|
91 |
|
92 @Override |
|
93 public List<GuardingDynamicLinker> get() { |
|
94 final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>(); |
|
95 linkers.add(new GuardingDynamicLinker() { |
|
96 @Override |
|
97 public GuardedInvocation getGuardedInvocation(LinkRequest request, |
|
98 LinkerServices linkerServices) throws Exception { |
|
99 final Object self = request.getReceiver(); |
|
100 CallSiteDescriptor desc = request.getCallSiteDescriptor(); |
|
101 Operation op = desc.getOperation(); |
|
102 Object name = NamedOperation.getName(op); |
|
103 // is this a named GET_METHOD? |
|
104 boolean isGetMethod = getFirstStandardOperation(desc) == StandardOperation.GET_METHOD; |
|
105 if (isGetMethod && name instanceof String) { |
|
106 String str = (String)name; |
|
107 if (str.indexOf('_') == -1) { |
|
108 return null; |
|
109 } |
|
110 |
|
111 String nameStr = translateToCamelCase(str); |
|
112 // create a new call descriptor to use translated name |
|
113 CallSiteDescriptor newDesc = new CallSiteDescriptor( |
|
114 desc.getLookup(), |
|
115 new NamedOperation(NamedOperation.getBaseOperation(op), nameStr), |
|
116 desc.getMethodType()); |
|
117 // create a new Link request to link the call site with translated name |
|
118 LinkRequest newRequest = new SimpleLinkRequest(newDesc, |
|
119 request.isCallSiteUnstable(), request.getArguments()); |
|
120 // return guarded invocation linking the translated request |
|
121 return linkerServices.getGuardedInvocation(newRequest); |
|
122 } |
|
123 |
|
124 return null; |
|
125 } |
|
126 }); |
|
127 return linkers; |
|
128 } |
|
129 } |