package org.restler; import org.restler.client.*; import org.restler.http.security.AuthenticatingEnhancer; import org.restler.http.security.SecuritySession; import org.restler.http.security.authentication.AuthenticationStrategy; import org.restler.http.security.authentication.CookieAuthenticationStrategy; import org.restler.http.security.authentication.HttpBasicAuthenticationStrategy; import org.restler.http.security.authorization.AuthorizationStrategy; import org.restler.http.security.authorization.FormAuthorizationStrategy; import org.restler.util.UriBuilder; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.function.Function; import java.util.stream.Collectors; import static org.restler.http.security.authentication.CookieAuthenticationStrategy.JSESSIONID; /** * The main entry point into the library. A {@code Restler} is actually a builder for {@code Service}s. Instances of * {@code Restler} can be reused to produce slightly different services - for example, two services that differ only * by their base URLs, or two services that differ only in authorization settings. * <p> * {@code Restler} could be extended in three main ways: * </p> * <ul> * <li>Each {@code Restler} is configured with {@code CoreModule} that defines supported service description formats * and provides CgLib {@code net.sf.cglib.proxy.InvocationHandler} that will be used to proxy remote services</li> * <li>A list of {@code CallEnhancer}s instances and/or suppliers may be provided to enable additional capabilities</li> * <li>Custom {@code AuthenticationStrategy} and {@code AuthorizationStrategy} may be provided to support custom security mechanisms</li> * </ul> */ public class Restler { public static final Executor defaultThreadPool = Executors.newCachedThreadPool(); private final List<CallEnhancer> enhancers = new ArrayList<>(); private final List<Function<RestlerConfig, List<CallEnhancer>>> enhancerFactories = new ArrayList<>(); private final UriBuilder uriBuilder; private AuthenticationStrategy authenticationStrategy; private AuthorizationStrategy authorizationStrategy; private Executor threadPool = Restler.defaultThreadPool; private boolean autoAuthorize = true; private Function<RestlerConfig, CoreModule> createCoreModule; /** * Instantiates a new {@code Restler} with a given base URL and a function that is able to produce a {@code CoreModule} from a {@code RestlerConfig}. The core module * producing function should take into account all data provided by {@code RestlerConfig}, especially the list of provided {@code CallEnhancer} instances - * all of them should be able to take part in request processing. */ public Restler(String baseUrl, Function<RestlerConfig, CoreModule> coreModule) { uriBuilder = new UriBuilder(baseUrl); this.createCoreModule = coreModule; } /** * Instantiates a new {@code Restler} with a given base URL and a function that is able to produce a {@code CoreModule} from a {@code RestlerConfig}. The core module * producing function should take into account all data provided by {@code RestlerConfig}, especially the list of provided {@code CallEnhancer} instances - * all of them should be able to take part in request processing. */ public Restler(URI baseUrl, Function<RestlerConfig, CoreModule> coreModule) { uriBuilder = new UriBuilder(baseUrl); this.createCoreModule = coreModule; } public Restler authenticationStrategy(AuthenticationStrategy authenticationStrategy) { this.authenticationStrategy = authenticationStrategy; return this; } public Restler authorizationStrategy(AuthorizationStrategy authorizationStrategy, AuthenticationStrategy authenticationStrategy) { this.authorizationStrategy = authorizationStrategy; return authenticationStrategy(authenticationStrategy); } public Restler formAuthentication(URI loginUrl, String userName, String password) { return formAuthentication(loginUrl, "username", userName, "password", password, JSESSIONID); } public Restler formAuthentication(URI loginUrl, String userNameParam, String userName, String passwordParam, String password, String sessionCookieName) { return authorizationStrategy(new FormAuthorizationStrategy(loginUrl, userNameParam, userName, passwordParam, password, sessionCookieName), new CookieAuthenticationStrategy()); } public Restler httpBasicAuthentication(String login, String password) { return authenticationStrategy(new HttpBasicAuthenticationStrategy(login, password)); } public Restler autoAuthorize(boolean autoAuthorize) { this.autoAuthorize = autoAuthorize; return this; } public Restler threadPool(Executor executor) { this.threadPool = executor; return this; } public Restler addEnhancer(CallEnhancer enhancer) { enhancers.add(enhancer); return this; } public Restler add(Function<RestlerConfig, List<CallEnhancer>> enhancerFactory) { enhancerFactories.add(enhancerFactory); return this; } public Restler scheme(String scheme) { uriBuilder.scheme(scheme); return this; } public Restler host(String host) { uriBuilder.host(host); return this; } public Restler port(int port) { uriBuilder.port(port); return this; } public Restler path(String path) { uriBuilder.path(path); return this; } public Restler replacePath(String path) { uriBuilder.replacePath(path); return this; } public Service build() throws RestlerException { SecuritySession session = new SecuritySession(authorizationStrategy, authenticationStrategy, autoAuthorize); List<CallEnhancer> enhancers = new ArrayList<>(this.enhancers); RestlerConfig config = new RestlerConfig(uriBuilder.build(), enhancers, threadPool, session); List<CallEnhancer> additionalEnhancers = enhancerFactories.stream().flatMap((enhancerFactory) -> enhancerFactory.apply(config).stream()).collect(Collectors.toList()); enhancers.addAll(additionalEnhancers); if (authenticationStrategy != null) { enhancers.add(new AuthenticatingEnhancer(session)); } return new Service(createCoreModule.apply(config), session); } }