View Javadoc
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  
11  package org.eclipse.jgit.transport;
12  
13  import java.io.IOException;
14  import java.io.PipedInputStream;
15  import java.io.PipedOutputStream;
16  
17  import org.eclipse.jgit.errors.TransportException;
18  import org.eclipse.jgit.internal.JGitText;
19  import org.eclipse.jgit.lib.Repository;
20  import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
21  import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
22  import org.eclipse.jgit.transport.resolver.UploadPackFactory;
23  
24  class InternalFetchConnection<C> extends BasePackFetchConnection {
25  	private Thread worker;
26  
27  	/**
28  	 * Constructor for InternalFetchConnection.
29  	 *
30  	 * @param transport
31  	 *            a {@link org.eclipse.jgit.transport.PackTransport}
32  	 * @param uploadPackFactory
33  	 *            a
34  	 *            {@link org.eclipse.jgit.transport.resolver.UploadPackFactory}
35  	 * @param req
36  	 *            request
37  	 * @param remote
38  	 *            the remote {@link org.eclipse.jgit.lib.Repository}
39  	 * @throws org.eclipse.jgit.errors.TransportException
40  	 *             if any.
41  	 */
42  	public InternalFetchConnection(PackTransport transport,
43  			final UploadPackFactory<C> uploadPackFactory,
44  			final C req, final Repository remote) throws TransportException {
45  		super(transport);
46  
47  		final PipedInputStream in_r;
48  		final PipedOutputStream in_w;
49  
50  		final PipedInputStream out_r;
51  		final PipedOutputStream out_w;
52  		try {
53  			in_r = new PipedInputStream();
54  			in_w = new PipedOutputStream(in_r);
55  
56  			out_r = new PipedInputStream() {
57  				// The client (BasePackFetchConnection) can write
58  				// a huge burst before it reads again. We need to
59  				// force the buffer to be big enough, otherwise it
60  				// will deadlock both threads.
61  				{
62  					buffer = new byte[MIN_CLIENT_BUFFER];
63  				}
64  			};
65  			out_w = new PipedOutputStream(out_r);
66  		} catch (IOException err) {
67  			remote.close();
68  			throw new TransportException(uri, JGitText.get().cannotConnectPipes, err);
69  		}
70  
71  		worker = new Thread("JGit-Upload-Pack") { //$NON-NLS-1$
72  			@Override
73  			public void run() {
74  				try {
75  					final UploadPack rp = uploadPackFactory.create(req, remote);
76  					rp.upload(out_r, in_w, null);
77  				} catch (ServiceNotEnabledException
78  						| ServiceNotAuthorizedException e) {
79  					// Ignored. Client cannot use this repository.
80  				} catch (IOException | RuntimeException err) {
81  					// Client side of the pipes should report the problem.
82  					err.printStackTrace();
83  				} finally {
84  					try {
85  						out_r.close();
86  					} catch (IOException e2) {
87  						// Ignore close failure, we probably crashed above.
88  					}
89  
90  					try {
91  						in_w.close();
92  					} catch (IOException e2) {
93  						// Ignore close failure, we probably crashed above.
94  					}
95  
96  					remote.close();
97  				}
98  			}
99  		};
100 		worker.start();
101 
102 		init(in_r, out_w);
103 		readAdvertisedRefs();
104 	}
105 
106 	/** {@inheritDoc} */
107 	@Override
108 	public void close() {
109 		super.close();
110 
111 		try {
112 			if (worker != null) {
113 				worker.join();
114 			}
115 		} catch (InterruptedException ie) {
116 			// Stop waiting and return anyway.
117 		} finally {
118 			worker = null;
119 		}
120 	}
121 }