// 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
// 
//   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.cloud.api;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpStatus;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.impl.NoConnectionReuseStrategy;
import org.apache.http.impl.SocketHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.log4j.Logger;

import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.api.response.ExceptionResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.async.AsyncJob;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO;
import com.cloud.cluster.StackMaid;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.event.EventUtils;
import com.cloud.exception.CloudAuthenticationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.DomainManager;
import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserContext;
import com.cloud.user.UserVO;
import com.cloud.utils.IdentityProxy;
import com.cloud.utils.Pair;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CSExceptionErrorCode;
import com.cloud.uuididentity.dao.IdentityDao;

public class ApiServer implements HttpRequestHandler {
    private static final Logger s_logger = Logger.getLogger(ApiServer.class.getName());
    private static final Logger s_accessLogger = Logger.getLogger("apiserver." + ApiServer.class.getName());

    public static final short ADMIN_COMMAND = 1;
    public static final short DOMAIN_ADMIN_COMMAND = 4;
    public static final short RESOURCE_DOMAIN_ADMIN_COMMAND = 2;
    public static final short USER_COMMAND = 8;
    public static boolean encodeApiResponse = false;
    public static String jsonContentType = "text/javascript";
    private Properties _apiCommands = null;
    private ApiDispatcher _dispatcher;
    private AccountManager _accountMgr = null;
    private DomainManager _domainMgr = null;
    private AsyncJobManager _asyncMgr = null;
    private Account _systemAccount = null;
    private User _systemUser = null;

    private static int _workerCount = 0;

    private static ApiServer s_instance = null;
    private static List<String> s_userCommands = null;
    private static List<String> s_resellerCommands = null; // AKA domain-admin
    private static List<String> s_adminCommands = null;
    private static List<String> s_resourceDomainAdminCommands = null;
    private static List<String> s_allCommands = null;
    private static List<String> s_pluggableServiceCommands = null;
    private static final DateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

    private static ExecutorService _executor = new ThreadPoolExecutor(10, 150, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new NamedThreadFactory("ApiServer"));

    static {
        s_userCommands = new ArrayList<String>();
        s_resellerCommands = new ArrayList<String>();
        s_adminCommands = new ArrayList<String>();
        s_resourceDomainAdminCommands = new ArrayList<String>();
        s_allCommands = new ArrayList<String>();
        s_pluggableServiceCommands = new ArrayList<String>();
    }

    private ApiServer() {
    }

    public static void initApiServer(String[] apiConfig) {
        if (s_instance == null) {
            s_instance = new ApiServer();
            s_instance.init(apiConfig);
        }
    }

    public static ApiServer getInstance() {
        // initApiServer();
        return s_instance;
    }

    public Properties get_apiCommands() {
        return _apiCommands;
    }

    public static boolean isPluggableServiceCommand(String cmdClassName) {
        if (s_pluggableServiceCommands != null) {
            if (s_pluggableServiceCommands.contains(cmdClassName)) {
                return true;
            }
        }
        return false;
    }

    private String[] getPluggableServicesApiConfigs() {
        List<String> pluggableServicesApiConfigs = new ArrayList<String>();

        ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
        List<PluggableService> services = locator.getAllPluggableServices();
        for (PluggableService service : services) {
            pluggableServicesApiConfigs.add(service.getPropertiesFile());
        }
        return pluggableServicesApiConfigs.toArray(new String[0]);
    }

    private void processConfigFiles(String[] apiConfig, boolean pluggableServicesConfig) {
        try {
            if (_apiCommands == null) {
                _apiCommands = new Properties();
            }
            Properties preProcessedCommands = new Properties();
            if (apiConfig != null) {
                for (String configFile : apiConfig) {
                    File commandsFile = PropertiesUtil.findConfigFile(configFile);
                    if (commandsFile != null) {
                        try {
                            preProcessedCommands.load(new FileInputStream(commandsFile));
                        } catch (FileNotFoundException fnfex) {
                            // in case of a file within a jar in classpath, try to open stream using url
                            InputStream stream = PropertiesUtil.openStreamFromURL(configFile);
                            if (stream != null) {
                                preProcessedCommands.load(stream);
                            } else {
                                s_logger.error("Unable to find properites file", fnfex);
                            }
                        }
                    }
                }
                for (Object key : preProcessedCommands.keySet()) {
                    String preProcessedCommand = preProcessedCommands.getProperty((String) key);
                    String[] commandParts = preProcessedCommand.split(";");
                    _apiCommands.put(key, commandParts[0]);

                    if (pluggableServicesConfig) {
                        s_pluggableServiceCommands.add(commandParts[0]);
                    }

                    if (commandParts.length > 1) {
                        try {
                            short cmdPermissions = Short.parseShort(commandParts[1]);
                            if ((cmdPermissions & ADMIN_COMMAND) != 0) {
                                s_adminCommands.add((String) key);
                            }
                            if ((cmdPermissions & RESOURCE_DOMAIN_ADMIN_COMMAND) != 0) {
                                s_resourceDomainAdminCommands.add((String) key);
                            }
                            if ((cmdPermissions & DOMAIN_ADMIN_COMMAND) != 0) {
                                s_resellerCommands.add((String) key);
                            }
                            if ((cmdPermissions & USER_COMMAND) != 0) {
                                s_userCommands.add((String) key);
                            }
                        } catch (NumberFormatException nfe) {
                            s_logger.info("Malformed command.properties permissions value, key = " + key + ", value = " + preProcessedCommand);
                        }
                    }
                }

                s_allCommands.addAll(s_adminCommands);
                s_allCommands.addAll(s_resourceDomainAdminCommands);
                s_allCommands.addAll(s_userCommands);
                s_allCommands.addAll(s_resellerCommands);
            }
        } catch (FileNotFoundException fnfex) {
            s_logger.error("Unable to find properites file", fnfex);
        } catch (IOException ioex) {
            s_logger.error("Exception loading properties file", ioex);
        }
    }

    public void init(String[] apiConfig) {
        BaseCmd.setComponents(new ApiResponseHelper());
        BaseListCmd.configure();
        processConfigFiles(apiConfig, false);

        // get commands for all pluggable services
        String[] pluggableServicesApiConfigs = getPluggableServicesApiConfigs();
        processConfigFiles(pluggableServicesApiConfigs, true);

        ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
        _accountMgr = locator.getManager(AccountManager.class);
        _asyncMgr = locator.getManager(AsyncJobManager.class);
        _systemAccount = _accountMgr.getSystemAccount();
        _systemUser = _accountMgr.getSystemUser();
        _dispatcher = ApiDispatcher.getInstance();
        _domainMgr = locator.getManager(DomainManager.class);

        Integer apiPort = null; // api port, null by default
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        SearchCriteria<ConfigurationVO> sc = configDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, "integration.api.port");
        List<ConfigurationVO> values = configDao.search(sc, null);
        if ((values != null) && (values.size() > 0)) {
            ConfigurationVO apiPortConfig = values.get(0);
            if (apiPortConfig.getValue() != null) {
                apiPort = Integer.parseInt(apiPortConfig.getValue());
            }
        }

        encodeApiResponse = Boolean.valueOf(configDao.getValue(Config.EncodeApiResponse.key()));

        String jsonType = configDao.getValue(Config.JavaScriptDefaultContentType.key());
        if (jsonType != null) {
            jsonContentType = jsonType;
        }

        if (apiPort != null) {
            ListenerThread listenerThread = new ListenerThread(this, apiPort);
            listenerThread.start();
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
        // get some information for the access log...
        StringBuffer sb = new StringBuffer();
        HttpServerConnection connObj = (HttpServerConnection) context.getAttribute("http.connection");
        if (connObj instanceof SocketHttpServerConnection) {
            InetAddress remoteAddr = ((SocketHttpServerConnection) connObj).getRemoteAddress();
            sb.append(remoteAddr.toString() + " -- ");
        }
        sb.append(request.getRequestLine());

        try {
            String uri = request.getRequestLine().getUri();
            int requestParamsStartIndex = uri.indexOf('?');
            if (requestParamsStartIndex >= 0) {
                uri = uri.substring(requestParamsStartIndex + 1);
            }

            String[] paramArray = uri.split("&");
            if (paramArray.length < 1) {
                s_logger.info("no parameters received for request: " + uri + ", aborting...");
                return;
            }

            Map parameterMap = new HashMap<String, String[]>();

            String responseType = BaseCmd.RESPONSE_TYPE_XML;
            for (String paramEntry : paramArray) {
                String[] paramValue = paramEntry.split("=");
                if (paramValue.length != 2) {
                    s_logger.info("malformed parameter: " + paramEntry + ", skipping");
                    continue;
                }
                if ("response".equalsIgnoreCase(paramValue[0])) {
                    responseType = paramValue[1];
                } else {
                    // according to the servlet spec, the parameter map should be in the form (name=String,
                    // value=String[]), so
                    // parameter values will be stored in an array
                    parameterMap.put(/* name */paramValue[0], /* value */new String[] { paramValue[1] });
                }
            }
            try {
                // always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM
                UserContext.registerContext(_systemUser.getId(), _systemAccount, null, true);
                sb.insert(0, "(userId=" + User.UID_SYSTEM + " accountId=" + Account.ACCOUNT_ID_SYSTEM + " sessionId=" + null + ") ");
                String responseText = handleRequest(parameterMap, true, responseType, sb);
                sb.append(" 200 " + ((responseText == null) ? 0 : responseText.length()));

                writeResponse(response, responseText, HttpStatus.SC_OK, responseType, null);
            } catch (ServerApiException se) {
                String responseText = getSerializedApiError(se.getErrorCode(), se.getDescription(), parameterMap, responseType, se);                
                writeResponse(response, responseText, se.getErrorCode(), responseType, se.getDescription());
                sb.append(" " + se.getErrorCode() + " " + se.getDescription());
            } catch (RuntimeException e) {
                // log runtime exception like NullPointerException to help identify the source easier
                s_logger.error("Unhandled exception, ", e);
                throw e;
            }
        } finally {
            s_accessLogger.info(sb.toString());
            UserContext.unregisterContext();
        }
    }

    @SuppressWarnings("rawtypes")
    public String handleRequest(Map params, boolean decode, String responseType, StringBuffer auditTrailSb) throws ServerApiException {
        String response = null;
        String[] command = null;
        try {
            command = (String[]) params.get("command");
            if (command == null) {
                s_logger.error("invalid request, no command sent");
                if (s_logger.isTraceEnabled()) {
                    s_logger.trace("dumping request parameters");
                    for (Object key : params.keySet()) {
                        String keyStr = (String) key;
                        String[] value = (String[]) params.get(key);
                        s_logger.trace("   key: " + keyStr + ", value: " + ((value == null) ? "'null'" : value[0]));
                    }
                }
                throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "Invalid request, no command sent");
            } else {
                Map<String, String> paramMap = new HashMap<String, String>();
                Set keys = params.keySet();
                Iterator keysIter = keys.iterator();
                while (keysIter.hasNext()) {
                    String key = (String) keysIter.next();
                    if ("command".equalsIgnoreCase(key)) {
                        continue;
                    }
                    String[] value = (String[]) params.get(key);

                    String decodedValue = null;
                    if (decode) {
                        try {
                            decodedValue = URLDecoder.decode(value[0], "UTF-8");
                        } catch (UnsupportedEncodingException usex) {
                            s_logger.warn(key + " could not be decoded, value = " + value[0]);
                            throw new ServerApiException(BaseCmd.PARAM_ERROR, key + " could not be decoded, received value " + value[0]);
                        } catch (IllegalArgumentException iae) {
                            s_logger.warn(key + " could not be decoded, value = " + value[0]);
                            throw new ServerApiException(BaseCmd.PARAM_ERROR, key + " could not be decoded, received value " + value[0] + " which contains illegal characters eg.%");
                        }
                    } else {
                        decodedValue = value[0];
                    }
                    paramMap.put(key, decodedValue);
                }
                String cmdClassName = _apiCommands.getProperty(command[0]);
                if (cmdClassName != null) {
                    Class<?> cmdClass = Class.forName(cmdClassName);
                    BaseCmd cmdObj = (BaseCmd) cmdClass.newInstance();
                    cmdObj.setFullUrlParams(paramMap);
                    cmdObj.setResponseType(responseType);
                    // This is where the command is either serialized, or directly dispatched
                    response = queueCommand(cmdObj, paramMap);
                    buildAuditTrail(auditTrailSb, command[0], response);
                } else {
                    if (!command[0].equalsIgnoreCase("login") && !command[0].equalsIgnoreCase("logout")) {
                        String errorString = "Unknown API command: " + ((command == null) ? "null" : command[0]);
                        s_logger.warn(errorString);
                        auditTrailSb.append(" " + errorString);
                        throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, errorString);
                    }
                }
            }
        } catch (Exception ex) {
            if (ex instanceof InvalidParameterValueException) {
            	InvalidParameterValueException ref = (InvalidParameterValueException)ex;
            	ServerApiException e = new ServerApiException(BaseCmd.PARAM_ERROR, ex.getMessage());            	
                // copy over the IdentityProxy information as well and throw the serverapiexception.
                ArrayList<IdentityProxy> idList = ref.getIdProxyList();
                if (idList != null) {
                	// Iterate through entire arraylist and copy over each proxy id.
                	for (int i = 0 ; i < idList.size(); i++) {
                		IdentityProxy obj = idList.get(i);
                		e.addProxyObject(obj.getTableName(), obj.getValue(), obj.getidFieldName());
                	}
                }
                // Also copy over the cserror code and the function/layer in which it was thrown.
            	e.setCSErrorCode(ref.getCSErrorCode());
                throw e;
            } else if (ex instanceof PermissionDeniedException) {
            	PermissionDeniedException ref = (PermissionDeniedException)ex;
            	ServerApiException e = new ServerApiException(BaseCmd.ACCOUNT_ERROR, ex.getMessage());
                // copy over the IdentityProxy information as well and throw the serverapiexception.
            	ArrayList<IdentityProxy> idList = ref.getIdProxyList();
                if (idList != null) {
                	// Iterate through entire arraylist and copy over each proxy id.
                	for (int i = 0 ; i < idList.size(); i++) {
                		IdentityProxy obj = idList.get(i);
                		e.addProxyObject(obj.getTableName(), obj.getValue(), obj.getidFieldName());
                	}
                }
                e.setCSErrorCode(ref.getCSErrorCode());
                throw e;
            } else if (ex instanceof ServerApiException) {
                throw (ServerApiException) ex;
            } else {
                s_logger.error("unhandled exception executing api command: " + ((command == null) ? "null" : command[0]), ex);
                ServerApiException e = new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal server error, unable to execute request.");
                e.setCSErrorCode(CSExceptionErrorCode.getCSErrCode("ServerApiException"));
                throw e;
            }
        }
        return response;
    }

    private String queueCommand(BaseCmd cmdObj, Map<String, String> params) {
        UserContext ctx = UserContext.current();
        Long callerUserId = ctx.getCallerUserId();
        Account caller = ctx.getCaller();
        if (cmdObj instanceof BaseAsyncCmd) {
            Long objectId = null;
            String objectEntityTable = null;
            if (cmdObj instanceof BaseAsyncCreateCmd) {
                BaseAsyncCreateCmd createCmd = (BaseAsyncCreateCmd) cmdObj;
                _dispatcher.dispatchCreateCmd(createCmd, params);
                objectId = createCmd.getEntityId();
                objectEntityTable = createCmd.getEntityTable();
                params.put("id", objectId.toString());
            } else {
                ApiDispatcher.setupParameters(cmdObj, params);
                ApiDispatcher.plugService(cmdObj);
            }

            BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmdObj;

            if (callerUserId != null) {
                params.put("ctxUserId", callerUserId.toString());
            }
            if (caller != null) {
                params.put("ctxAccountId", String.valueOf(caller.getId()));
            }

            long startEventId = ctx.getStartEventId();
            asyncCmd.setStartEventId(startEventId);

            // save the scheduled event
            Long eventId = EventUtils.saveScheduledEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId, 
                    asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(), asyncCmd.getEventDescription(),
                    startEventId);
            if (startEventId == 0) {
                // There was no create event before, set current event id as start eventId
                startEventId = eventId;
            }

            params.put("ctxStartEventId", String.valueOf(startEventId));

            ctx.setAccountId(asyncCmd.getEntityOwnerId());

            AsyncJobVO job = new AsyncJobVO();
            job.setInstanceId((objectId == null) ? asyncCmd.getInstanceId() : objectId);
            job.setInstanceType(asyncCmd.getInstanceType());
            job.setUserId(callerUserId);
            job.setAccountId(caller.getId());

            job.setCmd(cmdObj.getClass().getName());
            job.setCmdInfo(ApiGsonHelper.getBuilder().create().toJson(params));

            long jobId = _asyncMgr.submitAsyncJob(job);

            if (jobId == 0L) {
                String errorMsg = "Unable to schedule async job for command " + job.getCmd();
                s_logger.warn(errorMsg);
                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, errorMsg);
            }

            if (objectId != null) {
                SerializationContext.current().setUuidTranslation(true);
                return ((BaseAsyncCreateCmd) asyncCmd).getResponse(jobId, objectId, objectEntityTable);
            }

            SerializationContext.current().setUuidTranslation(true);
            return ApiResponseSerializer.toSerializedString(asyncCmd.getResponse(jobId), asyncCmd.getResponseType());
        } else {
            _dispatcher.dispatch(cmdObj, params);

            // if the command is of the listXXXCommand, we will need to also return the
            // the job id and status if possible
            if (cmdObj instanceof BaseListCmd) {
                buildAsyncListResponse((BaseListCmd) cmdObj, caller);
            }

            SerializationContext.current().setUuidTranslation(true);
            return ApiResponseSerializer.toSerializedString((ResponseObject) cmdObj.getResponseObject(), cmdObj.getResponseType());
        }
    }

    private void buildAsyncListResponse(BaseListCmd command, Account account) {
        List<ResponseObject> responses = ((ListResponse) command.getResponseObject()).getResponses();
        if (responses != null && responses.size() > 0) {
            List<? extends AsyncJob> jobs = null;

            // list all jobs for ROOT admin
            if (account.getType() == Account.ACCOUNT_TYPE_ADMIN) {
                jobs = _asyncMgr.findInstancePendingAsyncJobs(command.getInstanceType(), null);
            } else {
                jobs = _asyncMgr.findInstancePendingAsyncJobs(command.getInstanceType(), account.getId());
            }

            if (jobs.size() == 0) {
                return;
            }

            // Using maps might possibly be more efficient if the set is large enough but for now, we'll just do a
            // comparison of two lists. Either way, there shouldn't be too many async jobs active for the account.
            for (AsyncJob job : jobs) {
                if (job.getInstanceId() == null) {
                    continue;
                }
                for (ResponseObject response : responses) {
                    if (response.getObjectId() != null && job.getInstanceId().longValue() == response.getObjectId().longValue()) {
                        response.setJobId(job.getId());
                        response.setJobStatus(job.getStatus());
                    }
                }
            }
        }
    }

    private void buildAuditTrail(StringBuffer auditTrailSb, String command, String result) {
        if (result == null) {
            return;
        }
        auditTrailSb.append(" " + HttpServletResponse.SC_OK + " ");
        auditTrailSb.append(result);
        /*
         * if (command.equals("queryAsyncJobResult")){ //For this command we need to also log job status and job
         * resultcode for
         * (Pair<String,Object> pair : resultValues){ String key = pair.first(); if (key.equals("jobstatus")){
         * auditTrailSb.append(" "); auditTrailSb.append(key); auditTrailSb.append("=");
         * auditTrailSb.append(pair.second());
         * }else if (key.equals("jobresultcode")){ auditTrailSb.append(" "); auditTrailSb.append(key);
         * auditTrailSb.append("=");
         * auditTrailSb.append(pair.second()); } } }else { for (Pair<String,Object> pair : resultValues){ if
         * (pair.first().equals("jobid")){ // Its an async job so report the jobid auditTrailSb.append(" ");
         * auditTrailSb.append(pair.first()); auditTrailSb.append("="); auditTrailSb.append(pair.second()); } } }
         */
    }

    private static boolean isCommandAvailable(String commandName) {
        boolean isCommandAvailable = false;
        isCommandAvailable = s_allCommands.contains(commandName);
        return isCommandAvailable;
    }

    public boolean verifyRequest(Map<String, Object[]> requestParameters, Long userId) throws ServerApiException {
        try {
            String apiKey = null;
            String secretKey = null;
            String signature = null;
            String unsignedRequest = null;

            String[] command = (String[]) requestParameters.get("command");
            if (command == null) {
                s_logger.info("missing command, ignoring request...");
                return false;
            }

            String commandName = command[0];

            // if userId not null, that mean that user is logged in
            if (userId != null) {
                Long accountId = ApiDBUtils.findUserById(userId).getAccountId();
                Account userAccount = _accountMgr.getAccount(accountId);
                short accountType = userAccount.getType();

                if (!isCommandAvailable(accountType, commandName)) {
                    s_logger.warn("The given command:" + commandName + " does not exist");
                    throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist");
                }
                return true;
            } else {
                // check against every available command to see if the command exists or not
                if (!isCommandAvailable(commandName) && !commandName.equals("login") && !commandName.equals("logout")) {
                    s_logger.warn("The given command:" + commandName + " does not exist");
                    throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command does not exist");
                }
            }

            // - build a request string with sorted params, make sure it's all lowercase
            // - sign the request, verify the signature is the same
            List<String> parameterNames = new ArrayList<String>();

            for (Object paramNameObj : requestParameters.keySet()) {
                parameterNames.add((String) paramNameObj); // put the name in a list that we'll sort later
            }

            Collections.sort(parameterNames);

            String signatureVersion = null;
            String expires = null;

            for (String paramName : parameterNames) {
                // parameters come as name/value pairs in the form String/String[]
                String paramValue = ((String[]) requestParameters.get(paramName))[0];

                if ("signature".equalsIgnoreCase(paramName)) {
                    signature = paramValue;
                } else {
                    if ("apikey".equalsIgnoreCase(paramName)) {
                        apiKey = paramValue;
                    }
                    else if ("signatureversion".equalsIgnoreCase(paramName)) {
                        signatureVersion = paramValue;
                    } else if ("expires".equalsIgnoreCase(paramName)) {
                        expires = paramValue;
                    }

                    if (unsignedRequest == null) {
                        unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                    } else {
                        unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
                    }
                }
            }

            // if api/secret key are passed to the parameters
            if ((signature == null) || (apiKey == null)) {
                if (s_logger.isDebugEnabled()) {
                    s_logger.info("expired session, missing signature, or missing apiKey -- ignoring request...sig: " + signature + ", apiKey: " + apiKey);
                }
                return false; // no signature, bad request
            }

            Date expiresTS = null;
            if ("3".equals(signatureVersion)) {
                // New signature authentication. Check for expire parameter and its validity
                if (expires == null) {
                    s_logger.info("missing Expires parameter -- ignoring request...sig: " + signature + ", apiKey: " + apiKey);
                    return false;
                }
                synchronized (_dateFormat) {
                    try {
                        expiresTS = _dateFormat.parse(expires);
                    } catch (ParseException pe) {
                        s_logger.info("Incorrect date format for Expires parameter", pe);
                        return false;
                    }
                }
                Date now = new Date(System.currentTimeMillis());
                if (expiresTS.before(now)) {
                    s_logger.info("Request expired -- ignoring ...sig: " + signature + ", apiKey: " + apiKey);
                    return false;
                }
            }

            Transaction txn = Transaction.open(Transaction.CLOUD_DB);
            txn.close();
            User user = null;
            // verify there is a user with this api key
            Pair<User, Account> userAcctPair = _accountMgr.findUserByApiKey(apiKey);
            if (userAcctPair == null) {
                s_logger.info("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey);
                return false;
            }

            user = userAcctPair.first();
            Account account = userAcctPair.second();

            if (user.getState() != Account.State.enabled || !account.getState().equals(Account.State.enabled)) {
                s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() + "; accountState: "
                        + account.getState());
                return false;
            }

            UserContext.updateContext(user.getId(), account, null);

            if (!isCommandAvailable(account.getType(), commandName)) {
                s_logger.warn("The given command:" + commandName + " does not exist");
                throw new ServerApiException(BaseCmd.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist");
            }

            // verify secret key exists
            secretKey = user.getSecretKey();
            if (secretKey == null) {
                s_logger.info("User does not have a secret key associated with the account -- ignoring request, username: " + user.getUsername());
                return false;
            }

            unsignedRequest = unsignedRequest.toLowerCase();

            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
            mac.init(keySpec);
            mac.update(unsignedRequest.getBytes());
            byte[] encryptedBytes = mac.doFinal();
            String computedSignature = Base64.encodeBase64String(encryptedBytes);
            boolean equalSig = signature.equals(computedSignature);
            if (!equalSig) {
                s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
            }
            return equalSig;
        } catch (Exception ex) {
            if (ex instanceof ServerApiException && ((ServerApiException) ex).getErrorCode() == BaseCmd.UNSUPPORTED_ACTION_ERROR) {
                throw (ServerApiException) ex;
            }
            s_logger.error("unable to verifty request signature", ex);
        }
        return false;
    }
    
    public Long fetchDomainId(String domainUUID){
        ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
        IdentityDao identityDao = locator.getDao(IdentityDao.class);
        try{
            Long domainId = identityDao.getIdentityId("domain", domainUUID);
            return domainId;
        }catch(InvalidParameterValueException ex){
            return null;
        }
    }

    public void loginUser(HttpSession session, String username, String password, Long domainId, String domainPath, String loginIpAddress ,Map<String, Object[]> requestParameters) throws CloudAuthenticationException {
        // We will always use domainId first. If that does not exist, we will use domain name. If THAT doesn't exist
        // we will default to ROOT
        if (domainId == null) {
            if (domainPath == null || domainPath.trim().length() == 0) {
                domainId = DomainVO.ROOT_DOMAIN;
            } else {
                Domain domainObj = _domainMgr.findDomainByPath(domainPath);
                if (domainObj != null) {
                    domainId = domainObj.getId();
                } else { // if an unknown path is passed in, fail the login call
                    throw new CloudAuthenticationException("Unable to find the domain from the path " + domainPath);
                }
            }
        }

        UserAccount userAcct = _accountMgr.authenticateUser(username, password, domainId, loginIpAddress, requestParameters);
        if (userAcct != null) {
            String timezone = userAcct.getTimezone();
            float offsetInHrs = 0f;
            if (timezone != null) {
                TimeZone t = TimeZone.getTimeZone(timezone);
                s_logger.info("Current user logged in under " + timezone + " timezone");

                java.util.Date date = new java.util.Date();
                long longDate = date.getTime();
                float offsetInMs = (t.getOffset(longDate));
                offsetInHrs = offsetInMs / (1000 * 60 * 60);
                s_logger.info("Timezone offset from UTC is: " + offsetInHrs);
            }

            Account account = _accountMgr.getAccount(userAcct.getAccountId());

            // set the userId and account object for everyone
            session.setAttribute("userid", userAcct.getId());
            UserVO user = (UserVO) _accountMgr.getActiveUser(userAcct.getId());
            if(user.getUuid() != null){
                session.setAttribute("user_UUID", user.getUuid());
            }
            
            session.setAttribute("username", userAcct.getUsername());
            session.setAttribute("firstname", userAcct.getFirstname());
            session.setAttribute("lastname", userAcct.getLastname());
            session.setAttribute("accountobj", account);
            session.setAttribute("account", account.getAccountName());
            
            session.setAttribute("domainid", account.getDomainId());
            DomainVO domain = (DomainVO) _domainMgr.getDomain(account.getDomainId());
            if(domain.getUuid() != null){
                session.setAttribute("domain_UUID", domain.getUuid());
            }
            
            session.setAttribute("type", Short.valueOf(account.getType()).toString());
            session.setAttribute("registrationtoken", userAcct.getRegistrationToken());
            session.setAttribute("registered", new Boolean(userAcct.isRegistered()).toString());

            if (timezone != null) {
                session.setAttribute("timezone", timezone);
                session.setAttribute("timezoneoffset", Float.valueOf(offsetInHrs).toString());
            }

            // (bug 5483) generate a session key that the user must submit on every request to prevent CSRF, add that
            // to the login response so that session-based authenticators know to send the key back
            SecureRandom sesssionKeyRandom = new SecureRandom();
            byte sessionKeyBytes[] = new byte[20];
            sesssionKeyRandom.nextBytes(sessionKeyBytes);
            String sessionKey = Base64.encodeBase64String(sessionKeyBytes);
            session.setAttribute("sessionkey", sessionKey);

            return;
        }
        throw new CloudAuthenticationException("Failed to authenticate user " + username + " in domain " + domainId + "; please provide valid credentials");
    }

    public void logoutUser(long userId) {
        _accountMgr.logoutUser(Long.valueOf(userId));
        return;
    }

    public boolean verifyUser(Long userId) {
        User user = _accountMgr.getUserIncludingRemoved(userId);
        Account account = null;
        if (user != null) {
            account = _accountMgr.getAccount(user.getAccountId());
        }

        if ((user == null) || (user.getRemoved() != null) || !user.getState().equals(Account.State.enabled) || (account == null) || !account.getState().equals(Account.State.enabled)) {
            s_logger.warn("Deleted/Disabled/Locked user with id=" + userId + " attempting to access public API");
            return false;
        }
        return true;
    }

    public static boolean isCommandAvailable(short accountType, String commandName) {
        boolean isCommandAvailable = false;
        switch (accountType) {
        case Account.ACCOUNT_TYPE_ADMIN:
            isCommandAvailable = s_adminCommands.contains(commandName);
            break;
        case Account.ACCOUNT_TYPE_DOMAIN_ADMIN:
            isCommandAvailable = s_resellerCommands.contains(commandName);
            break;
        case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN:
            isCommandAvailable = s_resourceDomainAdminCommands.contains(commandName);
            break;
        case Account.ACCOUNT_TYPE_NORMAL:
            isCommandAvailable = s_userCommands.contains(commandName);
            break;
        }
        return isCommandAvailable;
    }

    // FIXME: rather than isError, we might was to pass in the status code to give more flexibility
    private void writeResponse(HttpResponse resp, final String responseText, final int statusCode, String responseType, String reasonPhrase) {
        try {
            resp.setStatusCode(statusCode);
            resp.setReasonPhrase(reasonPhrase);

            BasicHttpEntity body = new BasicHttpEntity();
            if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
                // JSON response
                body.setContentType(jsonContentType);
                if (responseText == null) {
                    body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes("UTF-8")));
                }
            } else {
                body.setContentType("text/xml");
                if (responseText == null) {
                    body.setContent(new ByteArrayInputStream("<error>Internal Server Error</error>".getBytes("UTF-8")));
                }
            }

            if (responseText != null) {
                body.setContent(new ByteArrayInputStream(responseText.getBytes("UTF-8")));
            }
            resp.setEntity(body);
        } catch (Exception ex) {
            s_logger.error("error!", ex);
        }
    }

    // FIXME: the following two threads are copied from
    // http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/httpcore/src/examples/org/apache/http/examples/ElementalHttpServer.java
    // we have to cite a license if we are using this code directly, so we need to add the appropriate citation or
    // modify the
    // code to be very specific to our needs
    static class ListenerThread extends Thread {
        private HttpService _httpService = null;
        private ServerSocket _serverSocket = null;
        private HttpParams _params = null;

        public ListenerThread(ApiServer requestHandler, int port) {
            try {
                _serverSocket = new ServerSocket(port);
            } catch (IOException ioex) {
                s_logger.error("error initializing api server", ioex);
                return;
            }

            _params = new BasicHttpParams();
            _params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 30000).setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
                    .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false).setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
                    .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");

            // Set up the HTTP protocol processor
            BasicHttpProcessor httpproc = new BasicHttpProcessor();
            httpproc.addInterceptor(new ResponseDate());
            httpproc.addInterceptor(new ResponseServer());
            httpproc.addInterceptor(new ResponseContent());
            httpproc.addInterceptor(new ResponseConnControl());

            // Set up request handlers
            HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
            reqistry.register("*", requestHandler);

            // Set up the HTTP service
            _httpService = new HttpService(httpproc, new NoConnectionReuseStrategy(), new DefaultHttpResponseFactory());
            _httpService.setParams(_params);
            _httpService.setHandlerResolver(reqistry);
        }

        @Override
        public void run() {
            s_logger.info("ApiServer listening on port " + _serverSocket.getLocalPort());
            while (!Thread.interrupted()) {
                try {
                    // Set up HTTP connection
                    Socket socket = _serverSocket.accept();
                    DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
                    conn.bind(socket, _params);

                    // Execute a new worker task to handle the request
                    _executor.execute(new WorkerTask(_httpService, conn, _workerCount++));
                } catch (InterruptedIOException ex) {
                    break;
                } catch (IOException e) {
                    s_logger.error("I/O error initializing connection thread", e);
                    break;
                }
            }
        }
    }

    static class WorkerTask implements Runnable {
        private final HttpService _httpService;
        private final HttpServerConnection _conn;

        public WorkerTask(final HttpService httpService, final HttpServerConnection conn, final int count) {
            _httpService = httpService;
            _conn = conn;
        }

        @Override
        public void run() {
            HttpContext context = new BasicHttpContext(null);
            try {
                while (!Thread.interrupted() && _conn.isOpen()) {
                    try {
                        _httpService.handleRequest(_conn, context);
                        _conn.close();
                    } finally {
                        StackMaid.current().exitCleanup();
                    }
                }
            } catch (ConnectionClosedException ex) {
                if (s_logger.isTraceEnabled()) {
                    s_logger.trace("ApiServer:  Client closed connection");
                }
            } catch (IOException ex) {
                if (s_logger.isTraceEnabled()) {
                    s_logger.trace("ApiServer:  IOException - " + ex);
                }
            } catch (HttpException ex) {
                s_logger.warn("ApiServer:  Unrecoverable HTTP protocol violation" + ex);
            } finally {
                try {
                    _conn.shutdown();
                } catch (IOException ignore) {
                }
            }
        }
    }

    public String getSerializedApiError(int errorCode, String errorText, Map<String, Object[]> apiCommandParams, String responseType, Exception ex) {
        String responseName = null;
        String cmdClassName = null;

        String responseText = null;

        try {
            if (errorCode == BaseCmd.UNSUPPORTED_ACTION_ERROR || apiCommandParams == null || apiCommandParams.isEmpty()) {
                responseName = "errorresponse";
            } else {
                Object cmdObj = apiCommandParams.get("command");
                // cmd name can be null when "command" parameter is missing in the request
                if (cmdObj != null) {
                    String cmdName = ((String[]) cmdObj)[0];
                    cmdClassName = _apiCommands.getProperty(cmdName);
                    if (cmdClassName != null) {
                        Class<?> claz = Class.forName(cmdClassName);
                        responseName = ((BaseCmd) claz.newInstance()).getCommandName();
                    } else {
                        responseName = "errorresponse";
                    }
                }
            }
            ExceptionResponse apiResponse = new ExceptionResponse();
            apiResponse.setErrorCode(errorCode);
            apiResponse.setErrorText(errorText);
            apiResponse.setResponseName(responseName);
            // Also copy over the IdentityProxy object List into this new apiResponse, from
            // the exception caught. When invoked from handle(), the exception here can
            // be either ServerApiException, PermissionDeniedException or InvalidParameterValue
            // Exception. When invoked from ApiServlet's processRequest(), this can be
            // a standard exception like NumberFormatException. We'll leave the standard ones alone.
            if (ex != null) {
            	if (ex instanceof ServerApiException || ex instanceof PermissionDeniedException
            			|| ex instanceof InvalidParameterValueException) {
            		// Cast the exception appropriately and retrieve the IdentityProxy
            		if (ex instanceof ServerApiException) {
            			ServerApiException ref = (ServerApiException) ex;
            			ArrayList<IdentityProxy> idList = ref.getIdProxyList();
            			if (idList != null) {
            				for (int i=0; i < idList.size(); i++) {
            					IdentityProxy id = idList.get(i);
            					apiResponse.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName());
            				}            				
            			}
            			// Also copy over the cserror code and the function/layer in which it was thrown.
            			apiResponse.setCSErrorCode(ref.getCSErrorCode());
            		} else if (ex instanceof PermissionDeniedException) {
            			PermissionDeniedException ref = (PermissionDeniedException) ex;
            			ArrayList<IdentityProxy> idList = ref.getIdProxyList();
            			if (idList != null) {
            				for (int i=0; i < idList.size(); i++) {
            					IdentityProxy id = idList.get(i);
            					apiResponse.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName());
            				}            				
            			}
            			// Also copy over the cserror code and the function/layer in which it was thrown.
            			apiResponse.setCSErrorCode(ref.getCSErrorCode());
            		} else if (ex instanceof InvalidParameterValueException) {
            			InvalidParameterValueException ref = (InvalidParameterValueException) ex;
            			ArrayList<IdentityProxy> idList = ref.getIdProxyList();
            			if (idList != null) {
            				for (int i=0; i < idList.size(); i++) {
            					IdentityProxy id = idList.get(i);
            					apiResponse.addProxyObject(id.getTableName(), id.getValue(), id.getidFieldName());
            				}            				
            			}
            			// Also copy over the cserror code and the function/layer in which it was thrown.
            			apiResponse.setCSErrorCode(ref.getCSErrorCode());
            		}
            	}
            }
            SerializationContext.current().setUuidTranslation(true);
            responseText = ApiResponseSerializer.toSerializedString(apiResponse, responseType);

        } catch (Exception e) {
            s_logger.error("Exception responding to http request", e);            
        }
        return responseText;
    }
}
