UnderscoreNameLinkerExporter.java revision 1565:c779bd47d648
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 32import java.lang.invoke.MethodHandle; 33import java.lang.invoke.MethodHandles; 34import java.lang.invoke.MethodType; 35import java.util.ArrayList; 36import java.util.List; 37import java.util.regex.Pattern; 38import java.util.regex.Matcher; 39import jdk.dynalink.CallSiteDescriptor; 40import jdk.dynalink.CompositeOperation; 41import jdk.dynalink.NamedOperation; 42import jdk.dynalink.Operation; 43import jdk.dynalink.CompositeOperation; 44import jdk.dynalink.StandardOperation; 45import jdk.dynalink.linker.GuardingDynamicLinker; 46import jdk.dynalink.linker.GuardingDynamicLinkerExporter; 47import jdk.dynalink.linker.GuardedInvocation; 48import jdk.dynalink.linker.LinkRequest; 49import jdk.dynalink.linker.LinkerServices; 50import 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 */ 57public 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} 130