/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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.google.cloud.sql.postgres;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.cloud.sql.core.SslSocketFactory;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.logging.Logger;
import jnr.unixsocket.UnixSocket;
import jnr.unixsocket.UnixSocketAddress;
import jnr.unixsocket.UnixSocketChannel;

/**
 * A Postgres {@link SocketFactory} that establishes a secure connection to a Cloud SQL instance
 * using ephemeral certificates.
 *
 * <p>The heavy lifting is done by the singleton {@link SslSocketFactory} class.
 */
public class SocketFactory extends javax.net.SocketFactory {
  private static final Logger logger = Logger.getLogger(SocketFactory.class.getName());
  private static final String GaeRuntime = "GAE_RUNTIME";
  private static final String CloudSqlPrefix = "/cloudsql/";
  private static final String PostgreSqlSufix = "/.s.PGSQL.5432";

  private final String instanceName;

  public SocketFactory(String instanceName) {
    checkArgument(
        instanceName != null,
        "socketFactoryArg property not set. Please specify this property in the JDBC "
            + "URL or the connection Properties with the instance connection name in "
            + "form \"project:region:instance\"");
    this.instanceName = instanceName;
  }

  @Override
  public Socket createSocket() throws IOException {
    logger.info(String.format("Connecting to Cloud SQL instance [%s].", instanceName));
    String runtime = System.getenv(GaeRuntime);

    if (runtime == null || runtime.isEmpty()) {  // we aren't on Standard (not set local)
      return SslSocketFactory.getInstance().create(instanceName);
    }
    logger.info("GAE Unix Sockets");
    UnixSocketAddress path = new UnixSocketAddress(
        new File(CloudSqlPrefix + instanceName + PostgreSqlSufix));
    UnixSocket socket = UnixSocketChannel.open(path).socket();
    return socket;
  }

  @Override
  public Socket createSocket(String host, int port) throws IOException {
    throw new UnsupportedOperationException();
  }

  @Override
  public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
      throws IOException {
    throw new UnsupportedOperationException();
  }

  @Override
  public Socket createSocket(InetAddress host, int port) throws IOException {
    throw new UnsupportedOperationException();
  }

  @Override
  public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
      throws IOException {
    throw new UnsupportedOperationException();
  }
}

@@ -1391,66 +1391,8 @@
 ));%0A
-  private static final String GaeRuntime = %22GAE_RUNTIME%22;%0A
   pr
@@ -2067,16 +2067,99 @@
 eName));
+%0A%0A    // This env var is used to determine if we are running on GAE standard or not
 %0A    Str
@@ -2190,18 +2190,21 @@
 env(
-GaeRuntime
+%22GAE_RUNTIME%22
 );%0A%0A
@@ -2259,45 +2259,48 @@
  // 
-we aren't on Standard (not set local)
+If not on GAE standard, use standard SSL
 %0A   
@@ -2427,20 +2427,29 @@
 Address 
-path
+socketAddress
  = new U
@@ -2585,12 +2585,21 @@
 pen(
-path
+socketAddress
 ).so

Address feedback.