/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.apache.ambari.view.hive2.resources.browser;
import com.google.common.base.Optional;
import org.apache.ambari.view.ViewContext;
import org.apache.ambari.view.hive2.AuthParams;
import org.apache.ambari.view.hive2.ConnectionFactory;
import org.apache.ambari.view.hive2.ConnectionSystem;
import org.apache.ambari.view.hive2.client.ConnectionConfig;
import org.apache.ambari.view.hive2.internal.ConnectionException;
import org.apache.ambari.view.hive2.internal.HiveConnectionWrapper;
import org.apache.ambari.view.hive2.utils.ServiceFormattedException;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Connection verification and management controller
*/
public class ConnectionService {
public static final String NO_PASSWORD = "";
public static final String SUFFIX = "validating the login";
@Inject
protected ViewContext context;
protected final static Logger LOG =
LoggerFactory.getLogger(ConnectionService.class);
/**
* Check if LDAP is configured on Hive
* if no password is cached , ask for one(401)
* if yes and a password is cached, try
* to connect, if connection succeeds
* return OK,
*
* if connection fails - ask for one again(401)
*/
@GET
@Path("connect")
@Produces(MediaType.APPLICATION_JSON)
public Response attemptConnection() {
boolean ldapEnabled = ConnectionFactory.isLdapEnabled(context);
if(ldapEnabled) {
ConnectionSystem instance = ConnectionSystem.getInstance();
Optional<String> password = instance.getPassword(context);
if (!password.isPresent()) {
// No password cached - request for one
return Response.status(Response.Status.UNAUTHORIZED).build();
}
// if there was a password cached, make a connection attempt
// get the password
String pass = password.get();
// password may be stale, try to connect to Hive
return attemptHiveConnection(pass,ldapEnabled);
}
return attemptHiveConnection(NO_PASSWORD,ldapEnabled);
}
private Response getOKResponse() {
JSONObject response = new JSONObject();
response.put("message", "OK");
response.put("trace", null);
response.put("status", "200");
return Response.ok().entity(response).type(MediaType.APPLICATION_JSON).build();
}
private Response attemptHiveConnection(String pass, boolean ldapEnabled) {
ConnectionConfig connectionConfig = ConnectionFactory.create(context);
HiveConnectionWrapper hiveConnectionWrapper = new HiveConnectionWrapper(connectionConfig.getJdbcUrl(), connectionConfig.getUsername(), pass,new AuthParams(context));
try {
hiveConnectionWrapper.connect();
} catch (ConnectionException e) {
// Cannot connect with the current credentials
// check the message to see if the cause was a login failure
// return a 401
// else return a 500
if(isLoginError(e) && ldapEnabled)
return Response.status(Response.Status.UNAUTHORIZED).build();
else
throw new ServiceFormattedException(e.getMessage(), e);
} finally {
try {
hiveConnectionWrapper.disconnect();
}
catch(ConnectionException e){
LOG.warn("Cannot close the connection");
}
}
return getOKResponse() ;
}
private boolean isLoginError(ConnectionException ce) {
return ce.getCause().getMessage().toLowerCase().endsWith(SUFFIX);
}
/**
* Set password
* This just updates the caches.
*/
@POST
@Path("auth")
@Consumes(MediaType.APPLICATION_JSON)
public Response setupPassword(AuthRequest request) {
try {
//Cache the password for the user
ConnectionSystem instance = ConnectionSystem.getInstance();
instance.persistCredentials(context.getUsername(),request.password);
return getOKResponse();
} catch (WebApplicationException ex) {
throw ex;
} catch (Exception ex) {
throw new ServiceFormattedException(ex.getMessage(), ex);
}
}
public static class AuthRequest {
public String password;
}
}