Package org.apache.sling.replication.transport.impl

Source Code of org.apache.sling.replication.transport.impl.SimpleHttpReplicationTransportHandler

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/
package org.apache.sling.replication.transport.impl;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Response;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.ContentType;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.replication.communication.ReplicationEndpoint;
import org.apache.sling.replication.communication.ReplicationRequest;
import org.apache.sling.replication.packaging.ReplicationPackage;
import org.apache.sling.replication.serialization.ReplicationPackageBuilder;
import org.apache.sling.replication.transport.ReplicationTransportException;
import org.apache.sling.replication.transport.ReplicationTransportHandler;
import org.apache.sling.replication.transport.authentication.TransportAuthenticationContext;
import org.apache.sling.replication.transport.authentication.TransportAuthenticationProvider;
import org.apache.sling.replication.util.RequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleHttpReplicationTransportHandler implements ReplicationTransportHandler {

    private static final Logger log = LoggerFactory.getLogger(SimpleHttpReplicationTransportHandler.class);
    private final TransportAuthenticationProvider<Executor, Executor> transportAuthenticationProvider;
    private final ReplicationEndpoint replicationEndpoint;
    private final ReplicationPackageBuilder packageBuilder;
    private final int maxNumberOfPackages;

    public SimpleHttpReplicationTransportHandler(TransportAuthenticationProvider<Executor, Executor> transportAuthenticationProvider,
                                                 ReplicationEndpoint replicationEndpoint,
                                                 ReplicationPackageBuilder packageBuilder,
                                                 int maxNumberOfPackages) {

        if (transportAuthenticationProvider == null) {
            throw new IllegalArgumentException("The authentication provider is required");
        }

        if (!transportAuthenticationProvider.canAuthenticate(Executor.class)) {
            throw new IllegalArgumentException("Authentication provider cannot authenticate Executor");
        }

        this.transportAuthenticationProvider = transportAuthenticationProvider;
        this.replicationEndpoint = replicationEndpoint;
        this.packageBuilder = packageBuilder;
        this.maxNumberOfPackages = maxNumberOfPackages;
    }

    public void deliverPackage(@Nonnull ResourceResolver resourceResolver, @Nonnull ReplicationPackage replicationPackage) throws ReplicationTransportException {
        String hostAndPort = getHostAndPort(replicationEndpoint.getUri());

        if (hostAndPort.equals(replicationPackage.getInfo().getOrigin())) {
            log.info("skipping replication of package {} to same origin {}", replicationPackage.getId(), hostAndPort);
            return;
        }


        log.info("delivering package {} to {} using auth {}", new Object[]{
                        replicationPackage.getId(),
                        replicationEndpoint.getUri(),
                        transportAuthenticationProvider
        });

        try {
            Executor executor = Executor.newInstance();

            TransportAuthenticationContext context = new TransportAuthenticationContext();
            context.addAttribute("endpoint", replicationEndpoint);
            executor = transportAuthenticationProvider.authenticate(executor, context);

            Request req = Request.Post(replicationEndpoint.getUri()).useExpectContinue();

            InputStream inputStream = null;
            Response response = null;
            try {

                inputStream = replicationPackage.createInputStream();

                req = req.bodyStream(inputStream, ContentType.APPLICATION_OCTET_STREAM);
                response = executor.execute(req);
            } finally {
                IOUtils.closeQuietly(inputStream);
            }

            if (response != null) {
                Content content = response.returnContent();
                log.info("Replication content of type {} for {} delivered: {}", new Object[]{
                        replicationPackage.getType(),
                        Arrays.toString(replicationPackage.getPaths()),
                        content
                });
            } else {
                throw new IOException("response is empty");
            }
        } catch (Exception ex) {
            throw new ReplicationTransportException(ex);
        }

    }

    @Nonnull
    public List<ReplicationPackage> retrievePackages(@Nonnull final ResourceResolver resourceResolver, @Nonnull final ReplicationRequest replicationRequest) throws ReplicationTransportException {
        log.debug("polling from {}", replicationEndpoint.getUri());

        try {
            URI replicationURI = RequestUtils.appendReplicationRequest(replicationEndpoint.getUri(), replicationRequest);
            List<ReplicationPackage> result = new ArrayList<ReplicationPackage>();

            // TODO : executor should be cached and reused

            Executor executor = Executor.newInstance();
            TransportAuthenticationContext context = new TransportAuthenticationContext();
            context.addAttribute("endpoint", replicationEndpoint);
            executor = transportAuthenticationProvider.authenticate(executor, context);

            Request req = Request.Post(replicationURI).useExpectContinue();

            // TODO : add queue parameter

            // continuously requests package streams as long as type header is received with the response (meaning there's a package of a certain type)
            HttpResponse httpResponse;
            try {

                int polls = 0;
                while ((httpResponse = executor.execute(req).returnResponse())
                        .getStatusLine().getStatusCode() == 200
                        && polls < maxNumberOfPackages) {
                    HttpEntity entity = httpResponse.getEntity();
                    if (entity != null) {
                        final ReplicationPackage responsePackage = packageBuilder.readPackage(resourceResolver, entity.getContent());
                        if (responsePackage != null) {
                            String origin = getHostAndPort(replicationURI);
                            responsePackage.getInfo().setOrigin(origin);
                            result.add(responsePackage);
                        }
                        else {
                            log.warn("responsePackage is null");
                        }

                        polls++;
                    } else {
                        log.info("");
                        break;
                    }
                }

                log.info("polled {} packages from {}", polls, replicationEndpoint.getUri());

            } catch (HttpHostConnectException e) {
                log.info("could not connect to {} - skipping", replicationEndpoint.getUri());
            }

            return result;

        } catch (Exception ex) {
            throw new ReplicationTransportException(ex);
        }

    }

    private String getHostAndPort(URI uri) {
        return uri.getHost() + ":" + uri.getPort();
    }

}
TOP

Related Classes of org.apache.sling.replication.transport.impl.SimpleHttpReplicationTransportHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.