package org.jboss.resteasy.plugins.providers;

import org.jboss.resteasy.core.ThreadLocalResteasyProviderFactory;
import org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl;
import org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor;
import org.jboss.resteasy.plugins.interceptors.GZIPEncodingInterceptor;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.spi.config.ConfigurationFactory;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

import javax.ws.rs.RuntimeType;
import javax.ws.rs.ext.Providers;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;

Author:Bill Burke
Version:$Revision: 1 $
/** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */
public class RegisterBuiltin { private static final Map<ClassLoader, ResteasyProviderFactory> configuredClientFactories = new WeakHashMap<>(); private static final boolean gzipForCachedFactories = isGZipEnabled(); public static synchronized ResteasyProviderFactory getClientInitializedResteasyProviderFactory(ClassLoader cl) { ResteasyProviderFactory rpf = null; final boolean gzip = isGZipEnabled(); if (gzipForCachedFactories == gzip) { rpf = configuredClientFactories.get(cl); } if (rpf == null) { rpf = new ResteasyProviderFactoryImpl(RuntimeType.CLIENT) { @Override public RuntimeType getRuntimeType() { return RuntimeType.CLIENT; } }; if (!rpf.isBuiltinsRegistered()) { register(rpf); } if (gzipForCachedFactories == gzip) { configuredClientFactories.put(cl, rpf); } } return rpf; } public static void register(ResteasyProviderFactory factory) { final ResteasyProviderFactory monitor = (factory instanceof ThreadLocalResteasyProviderFactory) ? ((ThreadLocalResteasyProviderFactory) factory).getDelegate() : factory; synchronized (monitor) { if (factory.isBuiltinsRegistered() || !factory.isRegisterBuiltins()) return; try { registerProviders(factory); } catch (Exception e) { throw new RuntimeException(e); } factory.setBuiltinsRegistered(true); } } public static void registerProviders(ResteasyProviderFactory factory) throws Exception { Map<String, URL> origins = scanBuiltins(); for (final Entry<String, URL> entry : origins.entrySet()) { final String line = entry.getKey(); try { Class<?> clazz; if (System.getSecurityManager() == null) { clazz = Thread.currentThread().getContextClassLoader().loadClass(line); } else { clazz = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { @Override public Class<?> run() throws ClassNotFoundException { return Thread.currentThread().getContextClassLoader().loadClass(line); } }); } factory.registerProvider(clazz, true); } catch (NoClassDefFoundError e) { LogMessages.LOGGER.noClassDefFoundErrorError(line, entry.getValue(), e); } catch (ClassNotFoundException | PrivilegedActionException ex) { LogMessages.LOGGER.classNotFoundException(line, entry.getValue(), ex); } } if (isGZipEnabled()) { factory.registerProvider(GZIPDecodingInterceptor.class, true); factory.registerProvider(GZIPEncodingInterceptor.class, true); } } public static Map<String, URL> scanBuiltins() throws IOException, PrivilegedActionException { Enumeration<URL> en; if (System.getSecurityManager() == null) { en = Thread.currentThread().getContextClassLoader().getResources("META-INF/services/" + Providers.class.getName()); } else { en = AccessController.doPrivileged(new PrivilegedExceptionAction<Enumeration<URL>>() { @Override public Enumeration<URL> run() throws IOException { return Thread.currentThread().getContextClassLoader().getResources("META-INF/services/" + Providers.class.getName()); } }); } Map<String, URL> origins = new HashMap<String, URL>(); while (en.hasMoreElements()) { final URL url = en.nextElement(); InputStream is; if (System.getSecurityManager() == null) { is = url.openStream(); } else { is = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() { @Override public InputStream run() throws IOException { return url.openStream(); } }); } try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); String line; while ((line = reader.readLine()) != null) { line = line.trim(); if (line.equals("")) continue; origins.put(line, url); } } finally { is.close(); } } return origins; } public static boolean isGZipEnabled() { return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { final String value = ConfigurationFactory.getInstance().getConfiguration().getOptionalValue("resteasy.allowGzip", String.class).orElse(null); if ("".equals(value)) return Boolean.FALSE; return Boolean.parseBoolean(value); } }); } }