package io.quarkus.camel.core.runtime.graal;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;

import org.apache.camel.CamelContext;
import org.apache.camel.Producer;
import org.apache.camel.builder.xml.XPathBuilder;
import org.apache.camel.cloud.ServiceDiscovery;
import org.apache.camel.converter.jaxp.DomConverter;
import org.apache.camel.converter.jaxp.StaxConverter;
import org.apache.camel.converter.jaxp.XmlConverter;
import org.apache.camel.support.IntrospectionSupport.ClassInfo;
import org.apache.camel.support.LRUCacheFactory;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

class CamelSubstitutions {
}

@TargetClass(className = "org.apache.camel.support.IntrospectionSupport")
final class Target_org_apache_camel_support_IntrospectionSupport {

    @Alias
    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)
    private static Map<Class<?>, ClassInfo> CACHE = LRUCacheFactory.newLRUWeakCache(256);
}

@TargetClass(className = "org.apache.camel.util.HostUtils")
final class Target_org_apache_camel_util_HostUtils {

    @Substitute
    private static InetAddress chooseAddress() throws UnknownHostException {
        return InetAddress.getByName("0.0.0.0");
    }
}

@TargetClass(className = "org.apache.camel.builder.xml.XPathBuilder", onlyWith = XmlDisabled.class)
final class Target_org_apache_camel_builder_xml_XPathBuilder {

    @Substitute
    public static XPathBuilder xpath(String text) {
        throw new UnsupportedOperationException();
    }

    @Substitute
    public static XPathBuilder xpath(String text, Class<?> resultType) {
        throw new UnsupportedOperationException();
    }

}

@TargetClass(className = "org.apache.camel.component.validator.ValidatorEndpoint", onlyWith = XmlDisabled.class)
final class Target_org_apache_camel_component_validator_ValidatorEndpoint {

    @Substitute
    public Producer createProducer() throws Exception {
        throw new UnsupportedOperationException();
    }
}

@TargetClass(className = "org.apache.camel.impl.converter.CoreStaticTypeConverterLoader", onlyWith = XmlDisabled.class)
final class Target_org_apache_camel_impl_converter_CoreStaticTypeConverterLoader {

    @Substitute
    private XmlConverter getXmlConverter() {
        throw new UnsupportedOperationException();
    }

    @Substitute
    private DomConverter getDomConverter() {
        throw new UnsupportedOperationException();
    }

    @Substitute
    private StaxConverter getStaxConverter() {
        throw new UnsupportedOperationException();
    }
}

@@ -39,16 +39,81 @@
 graal;%0A%0A
+import java.lang.reflect.Method;%0Aimport java.lang.reflect.Proxy;%0A
 import j
@@ -192,51 +192,89 @@
 til.
-Map;%0A%0Aimport org.apache.camel.CamelContext;
+ArrayList;%0Aimport java.util.Arrays;%0Aimport java.util.List;%0Aimport java.util.Map;%0A
 %0Aimp
@@ -358,56 +358,8 @@
 er;%0A
-import org.apache.camel.cloud.ServiceDiscovery;%0A
 impo
@@ -824,16 +824,48 @@
 etClass;
+%0Aimport com.sun.beans.WeakCache;
 %0A%0Aclass 
@@ -884,24 +884,295 @@
 utions %7B%0A%7D%0A%0A
+@TargetClass(className = %22java.beans.Introspector%22)%0Afinal class Target_java_beans_Introspector %7B%0A%0A    @Alias%0A    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)%0A    private static WeakCache%3CClass%3C?%3E, Method%5B%5D%3E declaredMethodCache = new WeakCache%3C%3E();%0A%0A%7D%0A%0A
 @TargetClass
@@ -1470,16 +1470,957 @@
 e(256);%0A
+%0A%7D%0A%0A@TargetClass(className = %22org.apache.camel.component.bean.BeanInfo%22)%0Afinal class Target_org_apache_camel_component_bean_BeanInfo %7B%0A%0A    @Alias%0A    @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)%0A    private static List%3CMethod%3E EXCLUDED_METHODS;%0A%0A    static %7B%0A        EXCLUDED_METHODS = new ArrayList%3C%3E();%0A        // exclude all java.lang.Object methods as we dont want to invoke them%0A        EXCLUDED_METHODS.addAll(Arrays.asList(Object.class.getMethods()));%0A        // exclude all java.lang.reflect.Proxy methods as we dont want to invoke them%0A        EXCLUDED_METHODS.addAll(Arrays.asList(Proxy.class.getMethods()));%0A        try %7B%0A            // but keep toString as this method is okay%0A            EXCLUDED_METHODS.remove(Object.class.getDeclaredMethod(%22toString%22));%0A            EXCLUDED_METHODS.remove(Proxy.class.getDeclaredMethod(%22toString%22));%0A        %7D catch (Throwable e) %7B%0A            // ignore%0A        %7D%0A    %7D%0A%0A
 %7D%0A%0A@Targ

Remove retained references to private java.lang.Object.registerNatives / java.lang.reflect.Proxy.defineClass0 methods