// Copyright (C) 2013 The Android Open Source Project
//
// 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.

package com.googlesource.gerrit.plugins.download.scheme;

import static com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme.DEFAULT_DOWNLOADS;
import static com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme.SSH;

import com.google.common.base.Strings;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.config.DownloadScheme;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.DownloadConfig;
import com.google.gerrit.server.ssh.SshAdvertisedAddresses;
import com.google.inject.Inject;
import com.google.inject.Provider;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class SshScheme extends DownloadScheme {
  private final String sshdAddress;
  private final String sshdHost;
  private final int sshdPort;
  private final Provider<CurrentUser> userProvider;
  private final boolean schemeAllowed;

  @Inject
  SshScheme(@SshAdvertisedAddresses List<String> sshAddresses,
      @CanonicalWebUrl @Nullable Provider<String> urlProvider,
      Provider<CurrentUser> userProvider, DownloadConfig downloadConfig) {
    String sshAddr = !sshAddresses.isEmpty() ? sshAddresses.get(0) : null;
    if (sshAddr != null && (sshAddr.startsWith("*:") || "".equals(sshAddr))
        && urlProvider != null) {
      try {
        sshAddr = (new URL(urlProvider.get())).getHost() + sshAddr.substring(1);
      } catch (MalformedURLException e) {
        // ignore, then this scheme will be disabled
      }
    }
    this.sshdAddress = sshAddr;

    int port = 29418;
    int p = sshdAddress.indexOf(":");
    if (p > 0) {
      this.sshdHost = sshdAddress.substring(0, p);
      try {
        port = Integer.parseInt(sshdAddress.substring(p + 1));
      } catch (NumberFormatException e) {
        // use default port
      }
    } else {
      this.sshdHost = sshdAddress;
    }
    this.sshdPort = port;

    this.userProvider = userProvider;
    this.schemeAllowed = downloadConfig.getDownloadSchemes().contains(SSH)
        || downloadConfig.getDownloadSchemes().contains(DEFAULT_DOWNLOADS);
  }

  @Override
  public String getUrl(String project) {
    if (!isEnabled() || !userProvider.get().isIdentifiedUser()) {
      return null;
    }
    String username = userProvider.get().getUserName();
    if (Strings.isNullOrEmpty(username)) {
      return null;
    }

    StringBuilder r = new StringBuilder();
    r.append("ssh://");
    r.append(username);
    r.append("@");
    r.append(ensureSlash(sshdAddress));
    r.append(project);
    return r.toString();
  }

  @Override
  public boolean isEnabled() {
    return schemeAllowed && sshdAddress != null;
  }

  @Override
  public boolean isAuthRequired() {
    return true;
  }

  @Override
  public boolean isAuthSupported() {
    return true;
  }

  private static String ensureSlash(String in) {
    if (in != null && !in.endsWith("/")) {
      return in + "/";
    }
    return in;
  }

  public String getSshdHost() {
    return sshdHost;
  }

  public int getSshdPort() {
    return sshdPort;
  }
}

@@ -2264,16 +2264,80 @@
  29418;%0A
+    String host = sshdAddress;%0A    if (sshdAddress != null) %7B%0A  
     int 
@@ -2366,24 +2366,26 @@
 f(%22:%22);%0A    
+  
 if (p %3E 0) %7B
@@ -2387,34 +2387,27 @@
  0) %7B%0A      
-this.sshdH
+  h
 ost = sshdAd
@@ -2431,24 +2431,26 @@
 , p);%0A      
+  
 try %7B%0A      
@@ -2451,16 +2451,18 @@
         
+ 
+ 
 port = I
@@ -2506,32 +2506,34 @@
 (p + 1));%0A      
+  
 %7D catch (NumberF
@@ -2560,16 +2560,18 @@
         
+ 
+ 
 // use d
@@ -2584,26 +2584,30 @@
  port%0A      
-%7D%0A
+  %7D%0A  
     %7D else %7B
@@ -2617,18 +2617,11 @@
     
-this.sshdH
+  h
 ost 
@@ -2635,25 +2635,59 @@
 ddress;%0A    
+ 
-%7D
+ %7D%0A    %7D%0A    this.sshdHost = host;
 %0A    this.ss

Fix NullPointerException when SSH address is malformed