UnderscoreNameLinkerExporter.java revision 1805:7caf1f762f1d
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.util.ArrayList;
33import java.util.List;
34import java.util.regex.Matcher;
35import java.util.regex.Pattern;
36import jdk.dynalink.CallSiteDescriptor;
37import jdk.dynalink.NamedOperation;
38import jdk.dynalink.NamespaceOperation;
39import jdk.dynalink.Operation;
40import jdk.dynalink.StandardNamespace;
41import jdk.dynalink.StandardOperation;
42import jdk.dynalink.linker.GuardedInvocation;
43import jdk.dynalink.linker.GuardingDynamicLinker;
44import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
45import jdk.dynalink.linker.LinkRequest;
46import jdk.dynalink.linker.LinkerServices;
47import jdk.dynalink.linker.support.SimpleLinkRequest;
48
49/**
50 * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
51 * This linker translater underscore_separated method names to CamelCase names
52 * used in Java APIs.
53 */
54public final class UnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter {
55    static {
56        System.out.println("pluggable dynalink underscore name linker loaded");
57    }
58
59    private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)");
60
61    // translate underscore_separated name as a CamelCase name
62    private static String translateToCamelCase(final String name) {
63        final Matcher m = UNDERSCORE_NAME.matcher(name);
64        final StringBuilder buf = new StringBuilder();
65        while (m.find()) {
66            m.appendReplacement(buf, m.group(1).toUpperCase());
67        }
68        m.appendTail(buf);
69        return buf.toString();
70    }
71
72    @Override
73    public List<GuardingDynamicLinker> get() {
74        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
75        linkers.add(new GuardingDynamicLinker() {
76            @Override
77            public GuardedInvocation getGuardedInvocation(final LinkRequest request,
78                final LinkerServices linkerServices) throws Exception {
79                final CallSiteDescriptor desc = request.getCallSiteDescriptor();
80                final Operation op = desc.getOperation();
81                final Object name = NamedOperation.getName(op);
82                final Operation namespaceOp = NamedOperation.getBaseOperation(op);
83                // is this a named GET_METHOD?
84                final boolean isGetMethod =
85                        NamespaceOperation.getBaseOperation(namespaceOp) == StandardOperation.GET
86                        && StandardNamespace.findFirst(namespaceOp) == StandardNamespace.METHOD;
87                if (isGetMethod && name instanceof String) {
88                    final String str = (String)name;
89                    if (str.indexOf('_') == -1) {
90                        return null;
91                    }
92
93                    final String nameStr = translateToCamelCase(str);
94                    // create a new call descriptor to use translated name
95                    final CallSiteDescriptor newDesc = desc.changeOperation(((NamedOperation)op).changeName(nameStr));
96                    // create a new Link request to link the call site with translated name
97                    final LinkRequest newRequest = request.replaceArguments(newDesc, request.getArguments());
98                    // return guarded invocation linking the translated request
99                    return linkerServices.getGuardedInvocation(newRequest);
100                }
101
102                return null;
103            }
104        });
105        return linkers;
106    }
107}
108