InternalFetchConnection.java

  1. /*
  2.  * Copyright (C) 2015, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.transport;

  11. import java.io.IOException;
  12. import java.io.PipedInputStream;
  13. import java.io.PipedOutputStream;

  14. import org.eclipse.jgit.errors.TransportException;
  15. import org.eclipse.jgit.internal.JGitText;
  16. import org.eclipse.jgit.lib.Repository;
  17. import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
  18. import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
  19. import org.eclipse.jgit.transport.resolver.UploadPackFactory;

  20. class InternalFetchConnection<C> extends BasePackFetchConnection {
  21.     private Thread worker;

  22.     /**
  23.      * Constructor for InternalFetchConnection.
  24.      *
  25.      * @param transport
  26.      *            a {@link org.eclipse.jgit.transport.PackTransport}
  27.      * @param uploadPackFactory
  28.      *            a
  29.      *            {@link org.eclipse.jgit.transport.resolver.UploadPackFactory}
  30.      * @param req
  31.      *            request
  32.      * @param remote
  33.      *            the remote {@link org.eclipse.jgit.lib.Repository}
  34.      * @throws org.eclipse.jgit.errors.TransportException
  35.      *             if any.
  36.      */
  37.     public InternalFetchConnection(PackTransport transport,
  38.             final UploadPackFactory<C> uploadPackFactory,
  39.             final C req, final Repository remote) throws TransportException {
  40.         super(transport);

  41.         final PipedInputStream in_r;
  42.         final PipedOutputStream in_w;

  43.         final PipedInputStream out_r;
  44.         final PipedOutputStream out_w;
  45.         try {
  46.             in_r = new PipedInputStream();
  47.             in_w = new PipedOutputStream(in_r);

  48.             out_r = new PipedInputStream() {
  49.                 // The client (BasePackFetchConnection) can write
  50.                 // a huge burst before it reads again. We need to
  51.                 // force the buffer to be big enough, otherwise it
  52.                 // will deadlock both threads.
  53.                 {
  54.                     buffer = new byte[MIN_CLIENT_BUFFER];
  55.                 }
  56.             };
  57.             out_w = new PipedOutputStream(out_r);
  58.         } catch (IOException err) {
  59.             remote.close();
  60.             throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
  61.         }

  62.         worker = new Thread("JGit-Upload-Pack") { //$NON-NLS-1$
  63.             @Override
  64.             public void run() {
  65.                 try {
  66.                     final UploadPack rp = uploadPackFactory.create(req, remote);
  67.                     rp.upload(out_r, in_w, null);
  68.                 } catch (ServiceNotEnabledException
  69.                         | ServiceNotAuthorizedException e) {
  70.                     // Ignored. Client cannot use this repository.
  71.                 } catch (IOException | RuntimeException err) {
  72.                     // Client side of the pipes should report the problem.
  73.                     err.printStackTrace();
  74.                 } finally {
  75.                     try {
  76.                         out_r.close();
  77.                     } catch (IOException e2) {
  78.                         // Ignore close failure, we probably crashed above.
  79.                     }

  80.                     try {
  81.                         in_w.close();
  82.                     } catch (IOException e2) {
  83.                         // Ignore close failure, we probably crashed above.
  84.                     }

  85.                     remote.close();
  86.                 }
  87.             }
  88.         };
  89.         worker.start();

  90.         init(in_r, out_w);
  91.         readAdvertisedRefs();
  92.     }

  93.     /** {@inheritDoc} */
  94.     @Override
  95.     public void close() {
  96.         super.close();

  97.         try {
  98.             if (worker != null) {
  99.                 worker.join();
  100.             }
  101.         } catch (InterruptedException ie) {
  102.             // Stop waiting and return anyway.
  103.         } finally {
  104.             worker = null;
  105.         }
  106.     }
  107. }