001/** 002 * Copyright (C) 2006-2025 Talend Inc. - www.talend.com 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.talend.sdk.component.runtime.manager.service; 017 018import static org.talend.sdk.component.runtime.base.lang.exception.InvocationExceptionWrapper.toRuntimeException; 019 020import java.lang.reflect.InvocationTargetException; 021import java.util.Map; 022 023import org.talend.sdk.component.api.service.BaseService; 024import org.talend.sdk.component.classloader.ThreadHelper; 025import org.talend.sdk.component.runtime.manager.asm.ProxyGenerator; 026import org.talend.sdk.component.runtime.manager.interceptor.InterceptorHandlerFacade; 027import org.talend.sdk.component.runtime.serialization.SerializableService; 028 029import lombok.RequiredArgsConstructor; 030 031@RequiredArgsConstructor 032public class ServiceHelper { 033 034 /** proxy generator */ 035 private final ProxyGenerator proxyGenerator; 036 037 /** all current services */ 038 private final Map<Class<?>, Object> allServices; 039 040 /** 041 * Create an instance of a Service with serialisation system and interceptors ... 042 * 043 * @param loader : class loader. 044 * @param containerId : container id. 045 * @param serviceClass : class of service. 046 * @return instance of service. 047 * @throws NoSuchMethodException if no default constructor. 048 */ 049 public Object createServiceInstance(final ClassLoader loader, final String containerId, final Class<?> serviceClass) 050 throws NoSuchMethodException { 051 try { 052 final Class<?> proxyClass = this.handleProxy(loader, containerId, serviceClass); 053 final Object instance = proxyClass.getConstructor().newInstance(); 054 055 if (proxyGenerator.hasInterceptors(serviceClass)) { 056 proxyGenerator 057 .initialize(instance, 058 new InterceptorHandlerFacade(serviceClass.getConstructor().newInstance(), allServices)); 059 } 060 if (instance instanceof BaseService) { 061 this.updateService((BaseService) instance, containerId, serviceClass.getName()); 062 } 063 return instance; 064 } catch (final InstantiationException | IllegalAccessException e) { 065 throw new IllegalArgumentException(e); 066 } catch (final InvocationTargetException e) { 067 throw toRuntimeException(e); 068 } 069 } 070 071 private Class<?> handleProxy(final ClassLoader loader, final String containerId, final Class<?> type) { 072 if (!proxyGenerator.hasInterceptors(type) && proxyGenerator.isSerializable(type)) { 073 return type; 074 } 075 076 return ThreadHelper 077 .runWithClassLoader(() -> proxyGenerator.generateProxy(loader, type, containerId, type.getName()), 078 loader); 079 080 } 081 082 private void updateService(final BaseService service, final String pluginId, final String key) { 083 if (service.getSerializationHelper() == null) { 084 service.setSerializationHelper(new SerializableService(pluginId, key)); 085 } 086 } 087}