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