Reduce multi-level buffered streams in transport code
[jgit/MarioXXX.git] / org.eclipse.jgit / src / org / eclipse / jgit / transport / TransportGitAnon.java
blob8a0b4357cd56e76e17808949bac7605454108915
1 /*
2 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
3 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
5 * and other copyright owners as documented in the project's IP log.
7 * This program and the accompanying materials are made available
8 * under the terms of the Eclipse Distribution License v1.0 which
9 * accompanies this distribution, is reproduced below, and is
10 * available at http://www.eclipse.org/org/documents/edl-v10.php
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or
15 * without modification, are permitted provided that the following
16 * conditions are met:
18 * - Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
26 * - Neither the name of the Eclipse Foundation, Inc. nor the
27 * names of its contributors may be used to endorse or promote
28 * products derived from this software without specific prior
29 * written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
32 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
36 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
43 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 package org.eclipse.jgit.transport;
48 import java.io.BufferedInputStream;
49 import java.io.BufferedOutputStream;
50 import java.io.IOException;
51 import java.io.InputStream;
52 import java.io.OutputStream;
53 import java.net.ConnectException;
54 import java.net.InetAddress;
55 import java.net.InetSocketAddress;
56 import java.net.Socket;
57 import java.net.UnknownHostException;
59 import org.eclipse.jgit.errors.TransportException;
60 import org.eclipse.jgit.lib.Repository;
62 /**
63 * Transport through a git-daemon waiting for anonymous TCP connections.
64 * <p>
65 * This transport supports the <code>git://</code> protocol, usually run on
66 * the IANA registered port 9418. It is a popular means for distributing open
67 * source projects, as there are no authentication or authorization overheads.
69 class TransportGitAnon extends TcpTransport implements PackTransport {
70 static final int GIT_PORT = Daemon.DEFAULT_PORT;
72 static boolean canHandle(final URIish uri) {
73 return "git".equals(uri.getScheme());
76 TransportGitAnon(final Repository local, final URIish uri) {
77 super(local, uri);
80 @Override
81 public FetchConnection openFetch() throws TransportException {
82 return new TcpFetchConnection();
85 @Override
86 public PushConnection openPush() throws TransportException {
87 return new TcpPushConnection();
90 @Override
91 public void close() {
92 // Resources must be established per-connection.
95 Socket openConnection() throws TransportException {
96 final int tms = getTimeout() > 0 ? getTimeout() * 1000 : 0;
97 final int port = uri.getPort() > 0 ? uri.getPort() : GIT_PORT;
98 final Socket s = new Socket();
99 try {
100 final InetAddress host = InetAddress.getByName(uri.getHost());
101 s.bind(null);
102 s.connect(new InetSocketAddress(host, port), tms);
103 } catch (IOException c) {
104 try {
105 s.close();
106 } catch (IOException closeErr) {
107 // ignore a failure during close, we're already failing
109 if (c instanceof UnknownHostException)
110 throw new TransportException(uri, "unknown host");
111 if (c instanceof ConnectException)
112 throw new TransportException(uri, c.getMessage());
113 throw new TransportException(uri, c.getMessage(), c);
115 return s;
118 void service(final String name, final PacketLineOut pckOut)
119 throws IOException {
120 final StringBuilder cmd = new StringBuilder();
121 cmd.append(name);
122 cmd.append(' ');
123 cmd.append(uri.getPath());
124 cmd.append('\0');
125 cmd.append("host=");
126 cmd.append(uri.getHost());
127 if (uri.getPort() > 0 && uri.getPort() != GIT_PORT) {
128 cmd.append(":");
129 cmd.append(uri.getPort());
131 cmd.append('\0');
132 pckOut.writeString(cmd.toString());
133 pckOut.flush();
136 class TcpFetchConnection extends BasePackFetchConnection {
137 private Socket sock;
139 TcpFetchConnection() throws TransportException {
140 super(TransportGitAnon.this);
141 sock = openConnection();
142 try {
143 InputStream sIn = sock.getInputStream();
144 OutputStream sOut = sock.getOutputStream();
146 sIn = new BufferedInputStream(sIn);
147 sOut = new BufferedOutputStream(sOut);
149 init(sIn, sOut);
150 service("git-upload-pack", pckOut);
151 } catch (IOException err) {
152 close();
153 throw new TransportException(uri,
154 "remote hung up unexpectedly", err);
156 readAdvertisedRefs();
159 @Override
160 public void close() {
161 super.close();
163 if (sock != null) {
164 try {
165 sock.close();
166 } catch (IOException err) {
167 // Ignore errors during close.
168 } finally {
169 sock = null;
175 class TcpPushConnection extends BasePackPushConnection {
176 private Socket sock;
178 TcpPushConnection() throws TransportException {
179 super(TransportGitAnon.this);
180 sock = openConnection();
181 try {
182 InputStream sIn = sock.getInputStream();
183 OutputStream sOut = sock.getOutputStream();
185 sIn = new BufferedInputStream(sIn);
186 sOut = new BufferedOutputStream(sOut);
188 init(sIn, sOut);
189 service("git-receive-pack", pckOut);
190 } catch (IOException err) {
191 close();
192 throw new TransportException(uri,
193 "remote hung up unexpectedly", err);
195 readAdvertisedRefs();
198 @Override
199 public void close() {
200 super.close();
202 if (sock != null) {
203 try {
204 sock.close();
205 } catch (IOException err) {
206 // Ignore errors during close.
207 } finally {
208 sock = null;