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 java.util.Locale.ROOT; 019import static java.util.stream.Collectors.toSet; 020 021import java.io.ObjectStreamException; 022import java.io.Serializable; 023import java.util.Map; 024 025import org.apache.xbean.propertyeditor.PropertyEditorRegistry; 026import org.apache.xbean.recipe.ObjectRecipe; 027import org.apache.xbean.recipe.Option; 028import org.talend.sdk.component.api.service.factory.ObjectFactory; 029import org.talend.sdk.component.runtime.serialization.SerializableService; 030 031import lombok.AllArgsConstructor; 032 033@AllArgsConstructor 034public class ObjectFactoryImpl implements ObjectFactory, Serializable { 035 036 private final String plugin; 037 038 private final PropertyEditorRegistry registry; 039 040 @Override 041 public ObjectFactoryInstance createInstance(final String type) { 042 final ObjectRecipe recipe = new ObjectRecipe(type); 043 recipe.setRegistry(registry); 044 return new ObjectFactoryInstanceImpl(recipe); 045 } 046 047 Object writeReplace() throws ObjectStreamException { 048 return new SerializableService(plugin, ObjectFactory.class.getName()); 049 } 050 051 @AllArgsConstructor 052 private static class ObjectFactoryInstanceImpl implements ObjectFactoryInstance { 053 054 private final ObjectRecipe recipe; 055 056 @Override 057 public ObjectFactoryInstance withFieldInjection() { 058 recipe.allow(Option.FIELD_INJECTION); 059 recipe.allow(Option.PRIVATE_PROPERTIES); 060 return this; 061 } 062 063 @Override 064 public ObjectFactoryInstance withoutFieldInjection() { 065 recipe.disallow(Option.FIELD_INJECTION); 066 return this; 067 } 068 069 @Override 070 public ObjectFactoryInstance ignoreUnknownProperties() { 071 recipe.allow(Option.IGNORE_MISSING_PROPERTIES); 072 return this; 073 } 074 075 @Override 076 public ObjectFactoryInstance withProperties(final Map<String, ?> map) { 077 if (recipe.getOptions().contains(Option.FIELD_INJECTION) 078 && recipe.getOptions().contains(Option.PRIVATE_PROPERTIES)) { 079 map.forEach(recipe::setFieldProperty); 080 } else { 081 recipe.setAllProperties(map); 082 } 083 return this; 084 } 085 086 @Override 087 public <T> T create(final Class<T> aClass) { 088 if (recipe 089 .getProperties() 090 .keySet() 091 .stream() 092 .map(it -> it.toLowerCase(ROOT)) 093 .collect(toSet()) 094 .size() == recipe.getProperties().size()) { 095 recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); 096 } 097 try { 098 return aClass.cast(recipe.create(Thread.currentThread().getContextClassLoader())); 099 } catch (final RuntimeException re) { 100 throw new IllegalArgumentException(re); 101 } 102 } 103 } 104}