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