Java tutorial
/* * #%L * wcm.io * %% * Copyright (C) 2014 wcm.io * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package io.wcm.caravan.pipeline.extensions.hal.client.action; import static io.wcm.caravan.io.http.request.CaravanHttpRequest.CORRELATION_ID_HEADER_NAME; import java.util.Collection; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.methods.HttpGet; import org.osgi.annotation.versioning.ProviderType; import com.google.common.collect.Multimap; import io.wcm.caravan.hal.resource.Link; import io.wcm.caravan.io.http.request.CaravanHttpRequest; import io.wcm.caravan.io.http.request.CaravanHttpRequestBuilder; import io.wcm.caravan.pipeline.JsonPipeline; import io.wcm.caravan.pipeline.JsonPipelineContext; import io.wcm.caravan.pipeline.JsonPipelineExceptionHandler; import io.wcm.caravan.pipeline.JsonPipelineOutput; import io.wcm.caravan.pipeline.cache.CacheControlUtils; import io.wcm.caravan.pipeline.cache.CacheStrategy; import io.wcm.caravan.pipeline.extensions.hal.client.ServiceIdExtractor; import rx.Observable; /** * Action to load a HAL link. */ @ProviderType public final class LoadLink extends AbstractHalClientAction { private final ServiceIdExtractor serviceId; private final Link link; private final Map<String, Object> parameters; private String httpMethod = HttpGet.METHOD_NAME; /** * @param serviceId Service ID * @param link Link to load * @param parameters URI parameters */ public LoadLink(String serviceId, Link link, Map<String, Object> parameters) { this.serviceId = (path) -> serviceId; this.link = link; this.parameters = parameters; } /** * @param serviceId a function to extract the serviceid from a path * @param link Link to load * @param parameters URI parameters */ public LoadLink(ServiceIdExtractor serviceId, Link link, Map<String, Object> parameters) { this.serviceId = serviceId; this.link = link; this.parameters = parameters; } @Override public String getId() { return "LOAD-LINK(" + httpMethod + "-" + serviceId.getServiceId(link.getHref()) + '-' + StringUtils.defaultIfBlank(link.getName(), "") + '-' + parameters.hashCode() + ")"; } @Override public Observable<JsonPipelineOutput> execute(JsonPipelineOutput previousStepOutput, JsonPipelineContext pipelineContext) { CaravanHttpRequest request = createRequest(previousStepOutput); JsonPipeline pipeline = createPipeline(pipelineContext, request); return pipeline.getOutput().map(jsonPipelineOutput -> { int maxAge = CacheControlUtils.getLowestMaxAge(jsonPipelineOutput, previousStepOutput); return jsonPipelineOutput.withMaxAge(maxAge); }); } /** * @param httpMethodToUse the HTTP method to use when loading the link * @return this */ public HalClientAction withHttpMethod(String httpMethodToUse) { this.httpMethod = httpMethodToUse; return this; } private CaravanHttpRequest createRequest(JsonPipelineOutput previousStepOutput) { CaravanHttpRequestBuilder builder = getRequestBuilder(); builder = setCacheControlHeaderIfExists(builder, previousStepOutput); builder = setCorrelationIdIfExists(builder, previousStepOutput); builder = setAdditionalHttpHeadersIfExists(builder); builder = builder.method(httpMethod); return builder.build(parameters); } private JsonPipeline createPipeline(JsonPipelineContext context, CaravanHttpRequest request) { if (hasLogger()) { getLogger().debug("Execute request: " + request); } JsonPipeline pipeline = context.getFactory().create(request, context.getProperties()); pipeline = setCacheStrategyIfExists(pipeline); pipeline = addExceptionHandlers(pipeline); return pipeline; } /** * @return URL of the current link and parameters. */ public String getUrl() { return getRequestBuilder().build(parameters).getUrl(); } private CaravanHttpRequestBuilder getRequestBuilder() { return new CaravanHttpRequestBuilder(serviceId.getServiceId(link.getHref())).append(link.getHref()); } /** * Adds a cache point to the given JSON pipeline if provided and the http request method is GET. * @param pipeline JSON pipeline * @return JSON pipeline with or without cache point */ private JsonPipeline setCacheStrategyIfExists(JsonPipeline pipeline) { if (!HttpGet.METHOD_NAME.equals(httpMethod)) { return pipeline; } else { CacheStrategy cacheStrategy = getCacheStrategy(); return cacheStrategy == null ? pipeline : pipeline.addCachePoint(cacheStrategy); } } /** * Sets the HTTP Cache-Control header to the given request builder if provided by the previous JSON pipeline output. * @param builder HTTP request builder * @param previousStepOutput Previous JSON output * @return HTTP request builder with or without HTTP Cache-Control header */ private CaravanHttpRequestBuilder setCacheControlHeaderIfExists(CaravanHttpRequestBuilder builder, JsonPipelineOutput previousStepOutput) { if (previousStepOutput.getRequests().isEmpty()) { return builder; } CaravanHttpRequest previousRequest = previousStepOutput.getRequests().get(0); Collection<String> cacheControlHeader = previousRequest.getHeaders().get("Cache-Control"); if (cacheControlHeader == null || cacheControlHeader.isEmpty()) { return builder; } return builder.header("Cache-Control", cacheControlHeader); } /** * Sets the {@code correlation-id} HTTP header to the given request builder if provided by the previous JSON pipeline * output. * @param builder HTTP request builder * @param previousStepOutput Previous JSON output * @return HTTP request builder with or without {@code correlation-id} HTTP header */ private CaravanHttpRequestBuilder setCorrelationIdIfExists(CaravanHttpRequestBuilder builder, JsonPipelineOutput previousStepOutput) { return previousStepOutput.getCorrelationId() == null ? builder : builder.header(CORRELATION_ID_HEADER_NAME, previousStepOutput.getCorrelationId()); } /** * Adds exception handler(s) to the given JSON pipeline if provided. * @param pipeline JSON pipeline * @return JSON pipeline with or without exception handler(s) */ private JsonPipeline addExceptionHandlers(JsonPipeline pipeline) { JsonPipeline newPipeline = pipeline; for (JsonPipelineExceptionHandler handler : getExceptionHandlers()) { newPipeline = newPipeline.handleException(handler); } return newPipeline; } /** * Sets additional HTTP headers to the given request builder if provided. * @param builder HTTP request builder * @return HTTP request builder with or without headers */ private CaravanHttpRequestBuilder setAdditionalHttpHeadersIfExists(CaravanHttpRequestBuilder builder) { getHttpHeaders().keySet().forEach(name -> builder.header(name, getHttpHeaders().get(name))); return builder; } }