LinkerServicesImpl.java revision 1645:15d52fdd9168
117721Speter/*
217721Speter * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
317721Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
454431Speter *
517721Speter * This code is free software; you can redistribute it and/or modify it
632788Speter * under the terms of the GNU General Public License version 2 only, as
754431Speter * published by the Free Software Foundation.  Oracle designates this
817721Speter * particular file as subject to the "Classpath" exception as provided
917721Speter * by Oracle in the LICENSE file that accompanied this code.
1017721Speter *
1154431Speter * This code is distributed in the hope that it will be useful, but WITHOUT
1217721Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1317721Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1454431Speter * version 2 for more details (a copy is included in the LICENSE file that
1517721Speter * accompanied this code).
1617721Speter *
1754431Speter * You should have received a copy of the GNU General Public License version
1817721Speter * 2 along with this work; if not, write to the Free Software Foundation,
1917721Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2054431Speter *
2117721Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2217721Speter * or visit www.oracle.com if you need additional information or have any
2317721Speter * questions.
2417721Speter */
2517721Speter
2654431Speter/*
2717721Speter * This file is available under and governed by the GNU General Public
2817721Speter * License version 2 only, as published by the Free Software Foundation.
2954431Speter * However, the following notice accompanied the original version of this
3017721Speter * file, and Oracle licenses the original version of this file under the BSD
3117721Speter * license:
3217721Speter */
3317721Speter/*
3454431Speter   Copyright 2009-2013 Attila Szegedi
3554431Speter
3617721Speter   Licensed under both the Apache License, Version 2.0 (the "Apache License")
3717721Speter   and the BSD License (the "BSD License"), with licensee being free to
3817721Speter   choose either of the two at their discretion.
3925839Speter
4017721Speter   You may not use this file except in compliance with either the Apache
41102843Speter   License or the BSD License.
4217721Speter
4317721Speter   If you choose to use this file in compliance with the Apache License, the
4417721Speter   following notice applies to you:
4517721Speter
4625839Speter       You may obtain a copy of the Apache License at
4734467Speter
4834467Speter           http://www.apache.org/licenses/LICENSE-2.0
4917721Speter
5025839Speter       Unless required by applicable law or agreed to in writing, software
5134467Speter       distributed under the License is distributed on an "AS IS" BASIS,
5217721Speter       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
5334467Speter       implied. See the License for the specific language governing
5434467Speter       permissions and limitations under the License.
5534467Speter
5625839Speter   If you choose to use this file in compliance with the BSD License, the
5725839Speter   following notice applies to you:
5825839Speter
5925839Speter       Redistribution and use in source and binary forms, with or without
6025839Speter       modification, are permitted provided that the following conditions are
6117721Speter       met:
6225839Speter       * Redistributions of source code must retain the above copyright
6381407Speter         notice, this list of conditions and the following disclaimer.
6425839Speter       * Redistributions in binary form must reproduce the above copyright
6525839Speter         notice, this list of conditions and the following disclaimer in the
6625839Speter         documentation and/or other materials provided with the distribution.
6725839Speter       * Neither the name of the copyright holder nor the names of
6825839Speter         contributors may be used to endorse or promote products derived from
6925839Speter         this software without specific prior written permission.
7025839Speter
7125839Speter       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
7225839Speter       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
7325839Speter       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
7434467Speter       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
7534467Speter       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7634467Speter       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7732788Speter       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
7825839Speter       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
7917721Speter       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
8017721Speter       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
8117721Speter       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8217721Speter*/
8325839Speter
8425839Speterpackage jdk.dynalink;
8525839Speter
8625839Speterimport java.lang.invoke.MethodHandle;
8725839Speterimport java.lang.invoke.MethodHandles;
8825839Speterimport java.lang.invoke.MethodHandles.Lookup;
8925839Speterimport java.lang.invoke.MethodType;
9025839Speterimport java.util.Objects;
9125839Speterimport java.util.function.Supplier;
9234467Speterimport jdk.dynalink.linker.ConversionComparator.Comparison;
9334467Speterimport jdk.dynalink.linker.GuardedInvocation;
9434467Speterimport jdk.dynalink.linker.GuardingDynamicLinker;
9534467Speterimport jdk.dynalink.linker.LinkRequest;
9617721Speterimport jdk.dynalink.linker.LinkerServices;
9717721Speterimport jdk.dynalink.linker.MethodHandleTransformer;
9817721Speter
9966528Speter/**
10017721Speter * Default implementation of the {@link LinkerServices} interface.
10183496Sdillon */
10217721Speterfinal class LinkerServicesImpl implements LinkerServices {
10317721Speter    private static final ThreadLocal<SecureLookupSupplier> threadLookupSupplier = new ThreadLocal<>();
10417721Speter
10517721Speter    private final TypeConverterFactory typeConverterFactory;
10617721Speter    private final GuardingDynamicLinker topLevelLinker;
10725839Speter    private final MethodHandleTransformer internalObjectsFilter;
10817721Speter
10917721Speter    /**
11017721Speter     * Creates a new linker services object.
11117721Speter     *
11217721Speter     * @param typeConverterFactory the type converter factory exposed by the services.
11381407Speter     * @param topLevelLinker the top level linker used by the services.
11417721Speter     * @param internalObjectsFilter a method handle transformer that is supposed to act as the implementation of this
11517721Speter     * services' {@link #filterInternalObjects(java.lang.invoke.MethodHandle)} method.
11617721Speter     */
11766528Speter    LinkerServicesImpl(final TypeConverterFactory typeConverterFactory,
11817721Speter            final GuardingDynamicLinker topLevelLinker, final MethodHandleTransformer internalObjectsFilter) {
11917721Speter        this.typeConverterFactory = typeConverterFactory;
12017721Speter        this.topLevelLinker = topLevelLinker;
12117721Speter        this.internalObjectsFilter = internalObjectsFilter;
12225839Speter    }
12381407Speter
12425839Speter    @Override
12525839Speter    public boolean canConvert(final Class<?> from, final Class<?> to) {
12617721Speter        return typeConverterFactory.canConvert(from, to);
12717721Speter    }
12817721Speter
12983496Sdillon    @Override
13032788Speter    public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
13117721Speter        return typeConverterFactory.asType(handle, fromType);
13217721Speter    }
13317721Speter
13417721Speter    @Override
13517721Speter    public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
13617721Speter        return typeConverterFactory.getTypeConverter(sourceType, targetType);
13717721Speter    }
13817721Speter
13917721Speter    @Override
14017721Speter    public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
14117721Speter        return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2);
14217721Speter    }
14317721Speter
14417721Speter    /**
14583496Sdillon     * Used to marshal a checked exception out of Supplier.get() in getGuardedInvocation.
14617721Speter     */
14717721Speter    private static class LinkerException extends RuntimeException {
14817721Speter        private static final long serialVersionUID = 1L;
14917721Speter
15017721Speter        public LinkerException(final Exception cause) {
15117721Speter            super(null, cause, true, false);
15217721Speter        }
15317721Speter    }
15426065Speter
15583496Sdillon    @Override
15617721Speter    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception {
15717721Speter        try {
15817721Speter            return getWithLookupInternal(() -> {
15917721Speter                try {
16017721Speter                    return topLevelLinker.getGuardedInvocation(linkRequest, this);
16117721Speter                } catch (final RuntimeException e) {
16266528Speter                    throw e;
16366528Speter                } catch (final Exception e) {
16466528Speter                    throw new LinkerException(e);
16517721Speter                }
16617721Speter            }, linkRequest.getCallSiteDescriptor());
16717721Speter        } catch (final LinkerException e) {
16817721Speter            throw (Exception)e.getCause();
16917721Speter        }
17017721Speter    }
17117721Speter
17217721Speter    @Override
17317721Speter    public MethodHandle filterInternalObjects(final MethodHandle target) {
17417721Speter        return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target;
17517721Speter    }
17617721Speter
17717721Speter    @Override
17817721Speter    public <T> T getWithLookup(final Supplier<T> operation, final SecureLookupSupplier lookupSupplier) {
17917721Speter        return getWithLookupInternal(
18017721Speter                Objects.requireNonNull(operation, "action"),
18117721Speter                Objects.requireNonNull(lookupSupplier, "lookupSupplier"));
18217721Speter    }
18317721Speter
18417721Speter    private static <T> T getWithLookupInternal(final Supplier<T> operation, final SecureLookupSupplier lookupSupplier) {
18517721Speter        final SecureLookupSupplier prevLookupSupplier = threadLookupSupplier.get();
18617721Speter        final boolean differ = prevLookupSupplier != lookupSupplier;
18717721Speter        if (differ) {
18817721Speter            threadLookupSupplier.set(lookupSupplier);
18917721Speter        }
19017721Speter        try {
19117721Speter            return operation.get();
19217721Speter        } finally {
19383496Sdillon            if (differ) {
19483496Sdillon                threadLookupSupplier.set(prevLookupSupplier);
19583496Sdillon            }
19617721Speter        }
19717721Speter    }
19817721Speter
19917721Speter    static Lookup getCurrentLookup() {
20017721Speter        final SecureLookupSupplier lookupSupplier = threadLookupSupplier.get();
20117721Speter        if (lookupSupplier != null) {
20217721Speter            return lookupSupplier.getLookup();
20317721Speter        }
20417721Speter        return MethodHandles.publicLookup();
20517721Speter    }
20617721Speter}
20717721Speter