OW2 Consortium contrail

Rev

Rev 2538 | Rev 3044 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vep;

import java.security.cert.X509Certificate;
import java.sql.ResultSet;
import java.util.List;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.restlet.data.Status;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.restlet.data.Form;
import org.restlet.resource.Delete;
import org.apache.commons.lang3.RandomStringUtils;


/**
 *
 * @author piyush
 */
public class restServerUserResource extends ServerResource 
{
    private dbHandler db;
    private Logger logger;
    private boolean systemOut;
    private ONExmlrpcHandler oneHandle;
    private String oneIP;
    private String oneXmlPort;
    private String oneAdmin;
    private String oneAdminPass;
    private String dbType;
    private String vepProperties;
    
    public restServerUserResource()
    {
        vepProperties = VEPHelperMethods.getPropertyFile();
        logger = Logger.getLogger("VEP.restUserResource");
        systemOut = false;
//        dbType = VEPHelperMethods.getProperty("vepdb.choice", logger, "vep.properties");
        dbType = VEPHelperMethods.getProperty("vepdb.choice", logger, vepProperties);
        db = new dbHandler("restServerUserResource", dbType);
//        oneIP = VEPHelperMethods.getProperty("one.ip", logger, "vep.properties");
//        oneXmlPort = VEPHelperMethods.getProperty("one.port", logger, "vep.properties");
//        oneAdmin = VEPHelperMethods.getProperty("one.user", logger, "vep.properties");
//        oneAdminPass = VEPHelperMethods.getProperty("one.pass", logger, "vep.properties");
        oneIP = VEPHelperMethods.getProperty("one.ip", logger, vepProperties);
        oneXmlPort = VEPHelperMethods.getProperty("one.port", logger, vepProperties);
        oneAdmin = VEPHelperMethods.getProperty("one.user", logger, vepProperties);
        oneAdminPass = VEPHelperMethods.getProperty("one.pass", logger, vepProperties);
        
        if(oneIP!=null && oneXmlPort!=null && oneAdmin!=null && oneAdminPass!=null)
            oneHandle = new ONExmlrpcHandler(oneIP, oneXmlPort, oneAdmin, oneAdminPass, "restServerUserResource:constructor");
    }
    
    @Delete("json")
    public Representation deleteJson() throws ResourceException
    {
        Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
        String username = ((String) getRequest().getAttributes().get("name"));
        
        ///////////////////////////
        String requester = requestHeaders.getFirstValue("X-Username"); //this is there only for debug purposes
        ///////////////////////////
        
        List<X509Certificate> certs = (List)getRequest().getAttributes().get("org.restlet.https.clientCertificates");
        for(int i=0; certs != null && i < certs.size(); i++)
        {
            X509Certificate Cert = certs.get(i);
            String certName = Cert.getSubjectX500Principal().getName();
            logger.info("Received certificate with name: " + certName);
            String[] certParts = certName.split(",");
            for(int j=0; j<certParts.length; j++)
            {
                if(certParts[j].startsWith("CN="))
                {
                    requester = certParts[j].split("=")[1];
                    break;
                }
            }
            logger.info("REST request came from: " + requester);
        }
        if(certs == null)
        {
            logger.warn("Client certificates list is empty. Unauthenticated client.");
        }
        else if(certs.isEmpty())
        {
            logger.warn("Client certificates list is empty. Unauthenticated client. Size = 0.");
        }
        System.out.println("ClientCertificates List: " + getRequest().getAttributes().get("org.restlet.https.clientCertificates"));
        
        JSONObject response = new JSONObject();
        ResultSet rs;
        boolean isAdmin = false;
        
        if(requester == null)
        {
            this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            response.put("error", "CLIENT_ERROR_BAD_REQUEST");
        }
        else
        {
            //get the requester details and determine the admin status
            try
            {
                rs = db.query("select", "*", "user", "where username='" + requester + "'");
                if(rs.next())
                {
                    int requester_uid = rs.getInt("uid");
                    rs.close();
                    rs = db.query("select", "*", "ugroup", "where uid=" + requester_uid + "");
                    String groupList = "";
                    while(rs.next())
                    {
                        groupList += rs.getString("gname") + ",";
                    }
                    String[] groups = groupList.split(","); //the last index will be empty because of the trailing ,
                    logger.trace("GroupsList for requester: " + requester + " is: " + groupList);
                    for(int i=0; i<groups.length; i++)
                    {
                        if(groups[i].equalsIgnoreCase("admin") || groups[i].equalsIgnoreCase("cloudadministrator"))
                        {
                            isAdmin = true;
                            logger.trace("Setting isAdmin to true.");
                            break;
                        }
                    }
                    rs.close();
                }
                else
                {
                    this.setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
                    response.put("error", "CLIENT_ERROR_PRECONDITION_FAILED");
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace(System.err);
                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                response.put("error", "Exception caught: " + ex.getMessage());
                logger.debug("Exception caught while trying to determine admin rights of the requester");
            }
        }
        //now proceed only if requester is admin
        if(!isAdmin)
        {
            this.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
            response.put("error", "CLIENT_ERROR_FORBIDDEN");
        }
        else
        {
            if(username == null)
            {
                this.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
                response.put("error", "CLIENT_ERROR_FORBIDDEN");
            }
            else
            {
                try
                {
                    rs = db.query("SELECT", "*", "user", "where username='" + username + "'");
                    if(rs.next())
                    {
//                        int uid = rs.getInt("uid");
//                        int oneid = rs.getInt("oneid");
//                        //first delete the opennebula corresponding user
//                        boolean status = oneHandle.removeUser(oneid);
//                        if(status)
//                            logger.debug("Successfully removed corresponding user from OpenNebula cloud.");
//                        else
//                            logger.warn("Error while deleting corresponding opennebula user with uid: " + oneid);
//                        String name = rs.getString("username");
//                        db.delete("user", "where username='" + name + "'");
//                        //now delete all group data
//                        db.delete("ugroup", "where uid=" + uid);
//                        //now remove all the VMs, OVFs, VM templates, Disks etc ...
//                        
//                        
//                        //now refresh the UI
//                        logger.debug("User " + name + " was deleted successfully.");
//                        if(status)
//                        {
//                            this.setStatus(Status.SUCCESS_OK);
//                            response.put("message", "SUCCESS_OK");
//                        }
//                        else
//                        {
//                            this.setStatus(Status.SUCCESS_PARTIAL_CONTENT);
//                            response.put("message", "SUCCESS_PARTIAL_CONTENT");
//                        }
                        int uid = rs.getInt("uid");
                        int oneid = rs.getInt("oneid");
                        String name = rs.getString("username");
                        //first check if running VMs are present
                        rs = db.query("select", "*", "vmachine", "where uid=" + uid + "and state<>'FN'");
                        if(rs.next())
                        {
                            //One or more VMs are still not finished
                            this.setStatus(Status.CLIENT_ERROR_EXPECTATION_FAILED);
                            response.put("error", "CLIENT_ERROR_EXPECTATION_FAILED");
                            response.put("trace", "One or more VM from this user are still not in the Finished state, please shutdown them before deleting.");
                        } 
                        else 
                        {
                            //first get all vm ids from this user                         
                            //then delete all diskimages for these machines
                            rs=db.query("select", "vmid", "vmachine", "where uid="+uid+" group by vmid");
                            while(rs.next())
                            {
                                db.delete("diskimage","where vmid="+rs.getInt("vmid"));
                            }
                            //then delete all vms;
                            db.delete("vmachine", "where uid="+uid);
                            //then delete all vm templates
                            db.delete("vmachinetemplate", "where uid="+uid);
                            //then delete all OVFs
                            db.delete("ovf", "where uid="+uid);
                            //first delete the opennebula corresponding user
                            boolean status = oneHandle.removeUser(oneid);
                            if(status)
                                logger.debug("Successfully removed corresponding user from OpenNebula cloud.");
                            else
                                logger.warn("Error while deleting corresponding opennebula user with uid: " + oneid);
                            db.delete("user", "where username='" + name + "'");
                            //now delete all group data
                            db.delete("ugroup", "where uid=" + uid);
                            //now refresh the UI
                            logger.debug("User " + name + " was deleted successfully.");
                            if(status)
                            {
                                this.setStatus(Status.SUCCESS_OK);
                                response.put("message", "SUCCESS_OK");
                            }
                            else
                            {
                                this.setStatus(Status.SUCCESS_PARTIAL_CONTENT);
                                response.put("message", "SUCCESS_PARTIAL_CONTENT");
                            }
                        }

                    }
                    else
                    {
                        //no such user exist
                        this.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                        response.put("error", "CLIENT_ERROR_NOT_FOUND");
                    }
                }
                catch(Exception ex)
                {
                    logger.warn("Exception was caught while trying to delete user.");
                    ex.printStackTrace(System.out);
                    this.setStatus(Status.SERVER_ERROR_INTERNAL);
                    response.put("error", "SERVER_ERROR_INTERNAL");
                }
            }
        }
        StringRepresentation out = new StringRepresentation(response.toJSONString(), MediaType.APPLICATION_JSON);
        return out;
    }
    
    @Get("json")
    public Representation getValue() throws ResourceException
    {
        Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
        String contentType = requestHeaders.getFirstValue("Content-Type");
        String acceptType = requestHeaders.getFirstValue("Accept");
        Representation response = null;
        
        String username = ((String) getRequest().getAttributes().get("name"));
        
        ///////////////////////////
        String requester = requestHeaders.getFirstValue("X-Username"); //this is there only for debug purposes
        ///////////////////////////
        
        List<X509Certificate> certs = (List)getRequest().getAttributes().get("org.restlet.https.clientCertificates");
        for(int i=0; certs != null && i < certs.size(); i++)
        {
            X509Certificate Cert = certs.get(i);
            String certName = Cert.getSubjectX500Principal().getName();
            logger.info("Received certificate with name: " + certName);
            String[] certParts = certName.split(",");
            for(int j=0; j<certParts.length; j++)
            {
                if(certParts[j].startsWith("CN="))
                {
                    requester = certParts[j].split("=")[1];
                    break;
                }
            }
            logger.info("REST request came from: " + requester);
        }
        if(certs == null)
        {
            logger.warn("Client certificates list is empty. Unauthenticated client.");
        }
        else if(certs.isEmpty())
        {
            logger.warn("Client certificates list is empty. Unauthenticated client. Size = 0.");
        }
        
        if(acceptType != null)
        {
            if(acceptType.contains("html"))
                response = toHtml(username, requester);
            else if(acceptType.contains("json"))
                response = toJson(username, requester);
        }
        else
        {
            //default rendering ...
            response = toHtml(username, requester);
        }
        //System.out.println(contentType);
        return response;
    }
    
    //@Get("json")
    public Representation toJson(String username, String requester) throws ResourceException
    {
        //requester can be used to do access control. to be implemented
        JSONObject response = new JSONObject();
        ResultSet rs;
        boolean isAdmin = false;
        
        if(requester == null)
        {
            this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            response.put("error", "CLIENT_ERROR_BAD_REQUEST");
        }
        else
        {
            //get the requester details and determine the admin status
            try
            {
                rs = db.query("select", "*", "user", "where username='" + requester + "'");
                if(rs.next())
                {
                    int requester_uid = rs.getInt("uid");
                    rs.close();
                    rs = db.query("select", "*", "ugroup", "where uid=" + requester_uid + "");
                    String groupList = "";
                    while(rs.next())
                    {
                        groupList += rs.getString("gname") + ",";
                    }
                    String[] groups = groupList.split(","); //the last index will be empty because of the trailing ,
                    logger.trace("GroupsList for requester: " + requester + " is: " + groupList);
                    for(int i=0; i<groups.length; i++)
                    {
                        if(groups[i].equalsIgnoreCase("admin") || groups[i].equalsIgnoreCase("cloudadministrator"))
                        {
                            isAdmin = true;
                            logger.trace("Setting isAdmin to true.");
                            break;
                        }
                    }
                    rs.close();
                    if(username == null && !isAdmin)
                    {
                        //check if requester is in the user list
                        rs = db.query("select", "*", "user", "where username='" + requester + "'");
                        if(rs.next())
                        {
                            rs.close();
                            int count = 1;
                            JSONArray unames = new JSONArray();
                            JSONArray ulinks = new JSONArray();
                            unames.add(requester);
                            ulinks.add("/user/" + requester);
                            response.put("title", "List of Users");
                            response.put("count", count);
                            response.put("usernames", unames);
                            response.put("links", ulinks);
                        }
                        else
                        {
                            this.setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
                            response.put("error", "CLIENT_ERROR_UNAUTHORIZED");
                        }
                    }
                    else if(!isAdmin && (username != null && !username.equalsIgnoreCase(requester))) //a user can retrieve his own account info but can not do a put
                    {
                        this.setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
                        response.put("error", "CLIENT_ERROR_UNAUTHORIZED");
                    }
                    else //the requester is an admin or requester is same as the user
                    {
                        if(username == null)
                        {
                            try
                            {
                                rs = db.query("select", "username", "user", "");
                                int count = 0;
                                JSONArray unames = new JSONArray();
                                JSONArray ulinks = new JSONArray();
                                while(rs.next())
                                {
                                    // read the result set
                                    unames.add(rs.getString("username"));
                                    ulinks.add("/user/" + rs.getString("username"));
                                    count++;
                                }
                                response.put("title", "List of Users");
                                response.put("count", count);
                                response.put("usernames", unames);
                                response.put("links", ulinks);
                            }
                            catch(Exception ex)
                            {
                                response.put("error", ex.getMessage());
                                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                                logger.debug("Exception caught: " + ex.getMessage());
                            }
                        }
                        else //display details on a particular user
                        {
                            try
                            {
                                rs = db.query("select", "*", "user", "where username='" + username + "'");
                                if(rs.next())
                                {
                                    // read the result set
                                    response.put("title", "details of user " + username);
                                    response.put("username", rs.getString("username"));
                                    response.put("uid",rs.getString("uid"));
                                    response.put("vid", rs.getString("vid"));
                                    response.put("role", rs.getString("role"));
                                    //now print associated details
                                    int uid = rs.getInt("uid");
                                    JSONArray groups1 = new JSONArray();
                                    rs = db.query("select", "*", "ugroup", "where uid=" + uid + "");
                                    while(rs.next())
                                    {
                                        groups1.add(rs.getString("gname"));
                                    }
                                    rs.close();
                                    response.put("groups", groups1);
                                    //print list of VMs submitted on behalf of this user

                                    JSONArray vmids = new JSONArray();
                                    JSONArray vmcids = new JSONArray();
                                    JSONArray vmovfids = new JSONArray();
                                    JSONArray vmappnames = new JSONArray();
                                    JSONArray vmstates = new JSONArray();
                                    JSONArray vmovfsnos = new JSONArray();
                                    JSONArray vmcontrollers = new JSONArray();
                                    JSONArray vmips = new JSONArray();
                                    JSONArray vmvncips = new JSONArray();
                                    JSONArray vmvncports = new JSONArray();


                                    rs = db.query("select", "vmid, appname, ovfsno, ovfid", "vmachinetemplate", "where uid=" + uid + "");
                                    int counter=0;
                                    int count = 0;
                                    while(rs.next())
                                    {
                                        counter++;
                                        int vmid = rs.getInt("vmid");
                                        String appname = rs.getString("appname");
                                        int ovfsno = rs.getInt("ovfsno");
                                        String ovfid = rs.getString("ovfid");
                                        ResultSet rs1 = db.query("select", "id, controller, state, cid, vncip, vncport, ipaddress", "vmachine", "where vmid=" + vmid + "");
                                        while(rs1.next())
                                        {
                                            count++;
                                            vmids.add(rs1.getInt("id"));
                                            vmcids.add(rs1.getInt("cid"));
                                            vmovfids.add(ovfid);
                                            vmappnames.add(appname);
                                            vmstates.add(rs1.getString("state"));
                                            vmovfsnos.add(ovfsno);
                                            vmcontrollers.add(rs1.getString("controller"));
                                            vmips.add(rs1.getString("ipaddress"));
                                            vmvncips.add(rs1.getString("vncip"));
                                            vmvncports.add(rs1.getString("vncport"));
                                        }
                                        rs1.close();
                                        rs = db.query("select", "vmid, appname, ovfsno, ovfid", "vmachinetemplate", "where uid=" + uid + "");
                                        for(int i=0;i<counter; i++) rs.next(); //hack to overcome rs being closed after updates.
                                    }
                                    rs.close();
                                    response.put("vmcount", count);
                                    response.put("vm_ids", vmids);
                                    response.put("vm_host_ids", vmcids);
                                    response.put("vm_ovfids", vmovfids);
                                    response.put("vm_app_name", vmappnames);
                                    response.put("vm_states", vmstates);
                                    response.put("vm_ovf_sno", vmovfsnos);
                                    response.put("vm_controllers", vmcontrollers);
                                    response.put("vm_ip_addresses", vmips);
                                    response.put("vm_vnc_ips", vmvncips);
                                    response.put("vm_vnc_ports", vmvncports);
                                }
                                else
                                {
                                    response.put("error", "CLIENT_ERROR_NOT_FOUND");
                                    this.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                                }
                            }
                            catch(Exception ex)
                            {
                                response.put("error", ex.getMessage());
                                logger.debug("Exception caught: " + ex.getMessage());
                                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                            }
                        }
                    }
                }
                else
                {
                    this.setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
                    response.put("error", "CLIENT_ERROR_PRECONDITION_FAILED");
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace(System.err);
                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                response.put("error", "Exception caught: " + ex.getMessage());
                logger.debug("Exception caught while trying to determine admin rights of the requester");
            }
        }
        //now proceed only if requester is admin
        
        StringRepresentation value = new StringRepresentation(response.toJSONString(), MediaType.APPLICATION_JSON);
        return value;
    }
    
    //@Get("html")
    public Representation toHtml(String username, String requester) throws ResourceException 
    {   
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(VEPHelperMethods.getRESTwebHeader(false));
        
        ResultSet rs;
        boolean isAdmin = false;
        
        if(requester == null)
        {
            this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            stringBuilder.append("Error Occurred: Could not determine the requesting party identity<br><b>CLIENT_ERROR_BAD_REQUEST</b><br><br>");
        }
        else
        {
            //get the requester details and determine the admin status
            try
            {
                rs = db.query("select", "*", "user", "where username='" + requester + "'");
                if(rs.next())
                {
                    int requester_uid = rs.getInt("uid");
                    rs.close();
                    rs = db.query("select", "*", "ugroup", "where uid=" + requester_uid + "");
                    String groupList = "";
                    while(rs.next())
                    {
                        groupList += rs.getString("gname") + ",";
                    }
                    String[] groups = groupList.split(","); //the last index will be empty because of the trailing ,
                    logger.trace("GroupsList for requester: " + requester + " is: " + groupList);
                    for(int i=0; i<groups.length; i++)
                    {
                        if(groups[i].equalsIgnoreCase("admin") || groups[i].equalsIgnoreCase("cloudadministrator"))
                        {
                            isAdmin = true;
                            logger.trace("Setting isAdmin to true.");
                            break;
                        }
                    }
                    rs.close();
                }
                else
                {
                    this.setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
                    stringBuilder.append("Error Occurred: The requesting party identity does not exist at this provider.<br><b>CLIENT_ERROR_PRECONDITION_FAILED</b><br><br>");
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace(System.err);
                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                stringBuilder.append("Exception Occurred while determining the requesting party identity.<br><b>SERVER_ERROR_INTERNAL</b><br><br>");
                logger.debug("Exception caught while trying to determine admin rights of the requester");
            }
        }
        //now proceed only if requester is admin or if the requester is same as the account requested
        if(username == null && !isAdmin)
        {
            //check if requester is in the user list
            stringBuilder.append("List of registered VEP users<br>");
            stringBuilder.append("<ul style='font-family:Times;font-size:11pt;color:black;'>");
            try
            {
                rs = db.query("select", "*", "user", "where username='" + requester + "'");
                if(rs.next())
                {
                    int count = 1;
                    stringBuilder.append("<li>").append(requester).append(" <a href='").
                                append(requester).append("'>/user/").append(requester).append("</a>");
                    stringBuilder.append("</ul>");
                    stringBuilder.append("<b>Total count: ").append(count).append("</b><br><br>");
                }
                else
                {
                    stringBuilder.append("</ul>");
                    this.setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
                    stringBuilder.append("Error Occurred: The requesting party has inadequate privilage for this operation.<br><b>CLIENT_ERROR_UNAUTHORIZED</b><br><br>");
                }
            }
            catch(Exception ex)
            {
                stringBuilder.append("</ul>");
                stringBuilder.append("<B>SQL Query Error!! Details of exception follows ...</B>");
                stringBuilder.append("<div style='border:1px;background:red;color:black;font-family:Times;font-size:9pt;'>");
                stringBuilder.append(ex.getMessage());
                logger.debug("Exception caught: " + ex.getMessage());
                stringBuilder.append("</div>");
            }
        }
        else if(!isAdmin && (username != null && !username.equalsIgnoreCase(requester))) //a user can retrieve his own account info but can not do a put
        {
            this.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
            stringBuilder.append("Error Occurred: The requesting party has inadequate privilage for this operation.<br><b>CLIENT_ERROR_FORBIDDEN</b><br><br>");
        }
        else
        {
            if(username == null)
            {
                stringBuilder.append("List of registered VEP users<br>");
                stringBuilder.append("<ul style='font-family:Times;font-size:11pt;color:black;'>");
                //stringBuilder.append("<li>user-name-1 <a href='uid' title='to be implemented soon'>/user/uid</a>");
                try
                {
                    rs = db.query("select", "username", "user", "");
                    int count = 0;
                    while(rs.next())
                    {
                        // read the result set
                        stringBuilder.append("<li>").append(rs.getString("username")).append(" <a href='").
                                append(rs.getString("username")).append("'>/user/").append(rs.getString("username")).append("</a>");
                        count++;
                    }
                    stringBuilder.append("</ul>");
                    stringBuilder.append("<b>Total count: ").append(count).append("</b><br><br>");
                }
                catch(Exception ex)
                {
                    stringBuilder.append("</ul>");
                    stringBuilder.append("<B>SQL Query Error!! Details of exception follows ...</B>");
                    stringBuilder.append("<div style='border:1px;background:red;color:black;font-family:Times;font-size:9pt;'>");
                    stringBuilder.append(ex.getMessage());
                    logger.debug("Exception caught: " + ex.getMessage());
                    stringBuilder.append("</div>");
                }
            }
            else //return details on specified user
            {
                stringBuilder.append("Details on user <i>").append(username).append("</i> is shown below:<br><br>");
                stringBuilder.append("<table style='width:1014px;hspace:5px;background:silver;border:0px;cellspacing:2px;padding:2px;font-family:Courier;font-size:10pt;color:black;'>");
                stringBuilder.append("<tr>");
                stringBuilder.append("<td valign='top' style='width:128px;background:white;'><img style='width:128px;' src='https://www.cise.ufl.edu/~pharsh/public/user.png'>");
                stringBuilder.append("<td valign='top' align='left' bgcolor='white' width='*'>");
                try
                {
                    rs = db.query("select", "*", "user", "where username='" + username + "'");
                    if(rs.next())
                    {
                        // read the result set
                        stringBuilder.append("<div style='background:#CED1D6;font-weight:bold;'>");
                        stringBuilder.append("Username: ").append(rs.getString("username")).append("<br>");
                        stringBuilder.append("UID: ").append(rs.getString("uid")).append("<br>");
                        stringBuilder.append("VID: ").append(rs.getString("vid")).append("<br>");
                        stringBuilder.append("Role: ").append(rs.getString("role")).append("<br>");
                        stringBuilder.append("</div>");
                        //now print associated details
                        int uid = rs.getInt("uid");
                        rs = db.query("select", "*", "ugroup", "where uid=" + uid + "");
                        stringBuilder.append("<br><b>Group membership details:</b><br>");
                        stringBuilder.append("<div style='background:#CED1D6;font-weight:bold;'>");
                        while(rs.next())
                        {
                            stringBuilder.append(rs.getString("gname")).append(", ");
                        }
                        stringBuilder.append("</div>");
                        //print list of VMs submitted on behalf of this user
                        stringBuilder.append("<br><b>List of virtual machines:</b><br>");
                        stringBuilder.append("<div style='background:white;'>");
                        stringBuilder.append("<table border=1 cellpadding=2 cellspacing=2 style=\"border:1px;border-color:#000000;font-family:Courier;font-size:9pt;text-align:right;color:white;\">");
                        stringBuilder.append("<tr><th align=right style=\"background:#333333;\">vmid</th>").append("<th align=right style=\"background:#333333;\">host id</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">ovfid</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">application name</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">state</th>").append("<th align=right style=\"background:#333333;\">ovf serial</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">controller</th>").append("<th align=right style=\"background:#333333;\">ip address</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">vnc ip</th>");
                        stringBuilder.append("<th align=right style=\"background:#333333;\">vnc port</th></tr>");
                        
                        int counter=0;
                        int count = 0;
                        rs = db.query("select", "*", "vmachine", "where uid=" + uid + " ORDER BY id DESC");
                        String appname = "";
                        String ovfid = "";
                        int ovfsno = -1;
                        while(rs.next())
                        {
                            int vmid = rs.getInt("vmid");
                            ResultSet rs1 = db.query("select", "appname, ovfsno, ovfid", "vmachinetemplate", "where vmid=" + vmid + "");
                            if(rs1.next())
                            {
                                appname = rs1.getString("appname");
                                ovfsno = rs1.getInt("ovfsno");
                                ovfid = rs1.getString("ovfid");
                                rs1.close();
                            }
                            else
                            {
                                appname = "";
                                ovfsno = -1;
                                ovfid = "";
                            }
                            count++;
                            String color = "#FFFFFF";
                            if(count%2 == 1)
                                color = "#CCCCCC";
                            else
                                color = "#FFFFFF";
                            rs = db.query("select", "*", "vmachine", "where uid=" + uid + " ORDER BY id DESC");
                            counter = 0;
                            while(rs.next())
                            {
                                counter++;
                                if(counter < count)
                                {
                                    continue;
                                }
                            
                                String td = "<td style=\"background:" + color + ";color:black;font-weight:bold;\">";
                                stringBuilder.append("<tr>").append(td).append(rs.getInt("id")).append("</td>").append(td).append(rs.getInt("cid")).append("</td>").append(td).append(ovfid);
                                stringBuilder.append("</td>").append(td).append(appname).append("</td>").append(td).append(rs.getString("state")).append("</td>").append(td).append(ovfsno);
                                stringBuilder.append("</td>").append(td).append(rs.getString("controller")).append("</td>").append(td).append(rs.getString("ipaddress")).append("</td>");
                                stringBuilder.append(td).append(rs.getString("vncip")).append("</td>").append(td).append(rs.getString("vncport")).append("</td></tr>");
                                break;
                            }
                        }
                        
//                        rs = db.query("select", "vmid, appname, ovfsno, ovfid", "vmachinetemplate", "where uid=" + uid + " ORDER BY vmid DESC");
//                        while(rs.next())
//                        {
//                            counter++;
//                            int vmid = rs.getInt("vmid");
//                            String appname = rs.getString("appname");
//                            int ovfsno = rs.getInt("ovfsno");
//                            String ovfid = rs.getString("ovfid");
//                            ResultSet rs1 = db.query("select", "id, controller, state, cid, vncip, vncport, ipaddress", "vmachine", "where vmid=" + vmid + "");
//                            while(rs1.next())
//                            {
//                                count++;
//                                String color = "#FFFFFF";
//                                if(count%2 == 1)
//                                    color = "#CCCCCC";
//                                else
//                                    color = "#FFFFFF";
//                                String td = "<td style=\"background:" + color + ";color:black;font-weight:bold;\">";
//                                stringBuilder.append("<tr>").append(td).append(rs1.getInt("id")).append("</td>").append(td).append(rs1.getInt("cid")).append("</td>").append(td).append(ovfid);
//                                stringBuilder.append("</td>").append(td).append(appname).append("</td>").append(td).append(rs1.getString("state")).append("</td>").append(td).append(ovfsno);
//                                stringBuilder.append("</td>").append(td).append(rs1.getString("controller")).append("</td>").append(td).append(rs1.getString("ipaddress")).append("</td>");
//                                stringBuilder.append(td).append(rs1.getString("vncip")).append("</td>").append(td).append(rs1.getString("vncport")).append("</td></tr>");
//                            }
//                            rs1.close();
//                            rs = db.query("select", "vmid, appname, ovfsno, ovfid", "vmachinetemplate", "where uid=" + uid + "");
//                            for(int i=0;i<counter; i++) rs.next(); //hack to overcome rs being closed after updates.
//                        }
                        rs.close();
                        stringBuilder.append("</table>");
                        stringBuilder.append("<hr><b>Total VMs found: ").append(count);
                        stringBuilder.append("</b></div>");
                    }
                    else
                    {
                        stringBuilder.append("No data found ...");
                    }
                }
                catch(Exception ex)
                {
                    stringBuilder.append("</table><B>SQL Query Error!! Details of exception follows ...</B>");
                    stringBuilder.append("<div style='border:1px;background:red;color:black;font-family:Times;font-size:9pt;'>");
                    stringBuilder.append(ex.getMessage());
                    logger.debug("Exception caught: " + ex.getMessage());
                    //ex.printStackTrace(System.err);
                    stringBuilder.append("</div>");
                }
                stringBuilder.append("</table><br>");
            }
        }
        stringBuilder.append("Click on the banner image to go up one level<br>");
        stringBuilder.append(VEPHelperMethods.getRESTwebFooter());
        StringRepresentation value = new StringRepresentation(stringBuilder.toString(), MediaType.TEXT_HTML);
        if(username  == null)
        {
            logger.trace("Sent list of users.");
        }
        else
            logger.trace("Sent user details for user " + username);
        return value;
    }
    
    @Put("json")
    public Representation storeJson(String value)
    {
        JSONObject response = new JSONObject();
        ResultSet rs;
        boolean isAdmin = false;
        
        ///////////////////////////
        Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
        String requester = requestHeaders.getFirstValue("X-Username"); //this is there only for debug purposes
        ///////////////////////////
        
        List<X509Certificate> certs = (List)getRequest().getAttributes().get("org.restlet.https.clientCertificates");
        for(int i=0; certs != null && i < certs.size(); i++)
        {
            X509Certificate Cert = certs.get(i);
            String certName = Cert.getSubjectX500Principal().getName();
            logger.info("Received certificate with name: " + certName);
            String[] certParts = certName.split(",");
            for(int j=0; j<certParts.length; j++)
            {
                if(certParts[j].startsWith("CN="))
                {
                    requester = certParts[j].split("=")[1];
                    break;
                }
            }
            logger.info("REST request came from: " + requester);
        }
        if(certs == null)
        {
            logger.warn("Client certificates list is empty. Unauthenticated client.");
        }
        else if(certs.isEmpty())
        {
            logger.warn("Client certificates list is empty. Unauthenticated client. Size = 0.");
        }
        if(requester == null)
        {
            this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            response.put("error", "CLIENT_ERROR_BAD_REQUEST");
        }
        else
        {
            //get the requester details and determine the admin status
            try
            {
                rs = db.query("select", "*", "user", "where username='" + requester + "'");
                if(rs.next())
                {
                    int requester_uid = rs.getInt("uid");
                    rs.close();
                    rs = db.query("select", "*", "ugroup", "where uid=" + requester_uid + "");
                    String groupList = "";
                    while(rs.next())
                    {
                        groupList += rs.getString("gname") + ",";
                    }
                    String[] groups = groupList.split(","); //the last index will be empty because of the trailing ,
                    logger.trace("GroupsList for requester: " + requester + " is: " + groupList);
                    for(int i=0; i<groups.length; i++)
                    {
                        if(groups[i].equalsIgnoreCase("admin") || groups[i].equalsIgnoreCase("cloudadministrator"))
                        {
                            isAdmin = true;
                            logger.trace("Setting isAdmin to true.");
                            break;
                        }
                    }
                    rs.close();
                }
                else
                {
                    this.setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
                    response.put("error", "CLIENT_ERROR_PRECONDITION_FAILED");
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace(System.err);
                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                response.put("error", "Exception caught: " + ex.getMessage());
                logger.debug("Exception caught while trying to determine admin rights of the requester");
            }
        }
        //now proceed only if requester is admin
        if(!isAdmin)
        {
            this.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
            response.put("error", "CLIENT_ERROR_FORBIDDEN");
        }
        else
        {
            String username = ((String) getRequest().getAttributes().get("name"));
            if(username == null)
            {
                this.setStatus(Status.CLIENT_ERROR_FORBIDDEN);
                response.put("error", "CLIENT_ERROR_FORBIDDEN");
                //return "CLIENT_ERROR_FORBIDDEN";
            }
            else
            {
                try
                {
                    JSONObject jObj = (JSONObject)JSONValue.parse(value);
                    //format of incoming json object
                    //role
                    //vid (if known)
                    //array - groups
                    if(systemOut)
                    {
                        System.out.println("Role: " + jObj.get("role"));
                        System.out.println("Group: " + jObj.get("groups"));
                        System.out.println("Input: " + value + " Name: " + username);
                    }
                    logger.debug("Received: username: " + username + ", role: " + jObj.get("role") + ", group(s): " + jObj.get("groups") + ".");
                    String role = (String)jObj.get("role");
                    String vid = (String)jObj.get("vid");
                    JSONArray groups = (JSONArray)jObj.get("groups");
                    //first check if the same username already exists
                    rs = db.query("select", "count(*)", "user", "where username='" + username + "'");
                    int count = 0;
                    if(rs.next())
                    {
                        count = rs.getInt(1);
                        rs.close();
                    }

                    int max_uid = 0;
                    boolean proceed = true;
                    //check whether the input is SQL safe or not
                    if(role != null && !dbHandler.validateSingleWord(role)) proceed = false;
                    if(vid != null && !dbHandler.validateSingleWord(vid)) proceed = false;
                    for(int i=0; groups!= null && i<groups.size(); i++)
                    {
                        if(!dbHandler.validateSingleWord((String)groups.get(i))) proceed = false;
                    }
                    if(!proceed)
                    {
                        this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                        response.put("error", "CLIENT_ERROR_BAD_REQUEST");
                        logger.debug("Incorrect JSON object received.");
                    }
                    else
                    {
                        if(count > 0) //the user exists, just update the user.
                        {
                            rs = db.query("select", "*", "user", "where username='" + username + "'");
                            
                            if(rs.next())
                            {
                                int uid = rs.getInt("uid");
                                //uid and username can not be changed
                                boolean status = true;
                                if(jObj.get("role") !=null)
                                    status = db.update("user", "role='" + jObj.get("role") + "'", "where username='" + username + "'");
                                if(status && jObj.get("vid") != null)
                                    status = db.update("user", "vid='" + jObj.get("vid") + "'", "where username='" + username + "'");
                                if(status && groups != null)
                                {
                                    //update the group membership
                                    //group = username will always be present
                                    status = db.delete("ugroup", "where uid=" + uid);
                                    status = db.insert("ugroup", "('" + username + "'," + uid + ")");
                                    //self group has been inserted
                                    for(int i=0; i<groups.size(); i++)
                                    {
                                        if(groups.get(i).toString().trim().length() > 0)
                                        {
                                            rs = db.query("SELECT", "*", "ugroup", "where gname='" + groups.get(i).toString().trim() + "' AND uid=" + uid);
                                            if(!rs.next())
                                            {
                                                //insert the group
                                                status = db.insert("ugroup", "('" + groups.get(i).toString().trim() + "'," + uid + ")");
                                            }
                                        }
                                    }
                                }
                                if(!status)
                                {
                                    this.setStatus(Status.CLIENT_ERROR_CONFLICT);
                                    //return "CLIENT_ERROR_CONFLICT";
                                    response.put("error", "CLIENT_ERROR_CONFLICT");
                                }
                                else
                                {
                                    this.setStatus(Status.SUCCESS_ACCEPTED);
                                    //return "SUCCESS_ACCEPTED";
                                    response.put("message", "SUCCESS_ACCEPTED");
                                }
                            }
                            else
                            {
                                this.setStatus(Status.CLIENT_ERROR_CONFLICT);
                                //return "CLIENT_ERROR_CONFLICT";
                                response.put("error", "CLIENT_ERROR_CONFLICT");
                            }
                        }
                        else //new user has to be created
                        {
                            rs = db.query("select", "max(uid)", "user", "");
                            if(rs.next())
                            {
                                max_uid = rs.getInt(1);
                                if(systemOut)
                                System.out.println("maximum UID: " + max_uid);
                                logger.debug("user ID to be assigned: " + max_uid + 1);
                            }
                            rs.close();
                            vid = (jObj.get("vid") == null) ? "-1" : jObj.get("vid").toString();
                            role = (jObj.get("role") == null) ? "user" : jObj.get("role").toString();
                            //first creating openNebula user
                            //int uname_size = 5 + rand.nextInt(10);
                            int uname_size = 8;
                            //String oneUser = username + "_vep_";
                            String oneUser = RandomStringUtils.randomAlphanumeric(uname_size);
                            //now test to see if this is already in use
                            boolean genNext = true;
                            while(genNext)
                            {
                                logger.debug("Testing if opennebula mapping by id " + oneUser + " already exists.");
                                rs = db.query("select", "*", "user", "where oneuser='" + oneUser + "'");
                                if(rs.next())
                                {
                                    genNext = true;
                                    logger.debug("Opennebula mapping by id " + oneUser + " already exists. Will try to create a new id.");
                                }
                                else
                                {
                                    genNext = false;
                                    logger.debug("Opennebula mapping by id " + oneUser + " does not exists. Will try to register with ONE daemon.");
                                }
                                rs.close();
                                if(genNext)
                                    oneUser = RandomStringUtils.randomAlphanumeric(uname_size);
                            }
                            String onePass = RandomStringUtils.randomAlphanumeric(32);
                            int oneId = oneHandle.addUser(oneUser, VEPHelperMethods.makeSHA1Hash(onePass));
                            if(oneId != -1)
                            {
                                boolean status = db.insert("user", "('" + username + "'," + (max_uid + 1) + ",'" + vid + "', '" + oneUser + "', '" + onePass + "', " + oneId + ",  '" + jObj.get("role") + "')");
                                if(status)
                                {
                                    db.delete("ugroup", "where uid=" + (max_uid + 1));
                                    status = db.insert("ugroup", "('" + username + "'," + (max_uid + 1) + ")");
                                    for(int i=0; status && groups!= null && i<groups.size(); i++)
                                    {
                                        if(groups.get(i).toString().trim().length() > 0)
                                        {
                                            rs = db.query("SELECT", "*", "ugroup", "where gname='" + groups.get(i).toString().trim() + "' AND uid=" + (max_uid + 1));
                                            if(!rs.next())
                                            {
                                                //insert the group
                                                status = db.insert("ugroup", "('" + groups.get(i).toString().trim() + "'," + (max_uid + 1) + ")");
                                            }
                                        }
                                    }
                                    if(status)
                                    {
                                        this.setStatus(Status.SUCCESS_CREATED);
                                        //return "SUCCESS_CREATED";
                                        response.put("message", "SUCCESS_CREATED");
                                    }
                                    else
                                    {
                                        this.setStatus(Status.SUCCESS_PARTIAL_CONTENT);
                                        //return "SUCCESS_PARTIAL_CONTENT";
                                        response.put("error", "SUCCESS_PARTIAL_CONTENT");
                                    }
                                }
                                else
                                {
                                    this.setStatus(Status.SERVER_ERROR_INTERNAL);
                                    //return "SERVER_ERROR_INTERNAL";
                                    response.put("error", "SERVER_ERROR_INTERNAL");
                                }
                            }
                            else
                            {
                                this.setStatus(Status.SERVER_ERROR_INTERNAL);
                                //return "SERVER_ERROR_INTERNAL";
                                response.put("error", "SERVER_ERROR_INTERNAL");
                            }
                        }
                    }
                }
                catch(Exception ex)
                {
                    this.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    ex.printStackTrace(System.out);
                    //return "CLIENT_ERROR_BAD_REQUEST";
                    response.put("error", "CLIENT_ERROR_BAD_REQUEST");
                }
            }
        }
        StringRepresentation out = new StringRepresentation(response.toJSONString(), MediaType.APPLICATION_JSON);
        return out;
    }
}