Project: android-rackspacecloud
/**
 * 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 net.elasticgrid.rackspace.cloudservers; 
 
import net.elasticgrid.rackspace.cloudservers.Server.Status; 
import net.elasticgrid.rackspace.cloudservers.internal.ConfirmResize; 
import net.elasticgrid.rackspace.cloudservers.internal.Flavors; 
import net.elasticgrid.rackspace.cloudservers.internal.Images; 
import net.elasticgrid.rackspace.cloudservers.internal.Metadata; 
import net.elasticgrid.rackspace.cloudservers.internal.MetadataItem; 
import net.elasticgrid.rackspace.cloudservers.internal.Private; 
import net.elasticgrid.rackspace.cloudservers.internal.Public; 
import net.elasticgrid.rackspace.cloudservers.internal.Reboot; 
import net.elasticgrid.rackspace.cloudservers.internal.Rebuild; 
import net.elasticgrid.rackspace.cloudservers.internal.Resize; 
import net.elasticgrid.rackspace.cloudservers.internal.RevertResize; 
import net.elasticgrid.rackspace.cloudservers.internal.ServerID; 
import net.elasticgrid.rackspace.cloudservers.internal.Servers; 
import net.elasticgrid.rackspace.cloudservers.internal.SharedIpGroup; 
import net.elasticgrid.rackspace.cloudservers.internal.SharedIpGroups; 
import net.elasticgrid.rackspace.cloudservers.internal.ShareIp; 
import net.elasticgrid.rackspace.common.RackspaceConnection; 
import net.elasticgrid.rackspace.common.RackspaceException; 
import org.apache.http.HttpException; 
import org.apache.http.client.methods.HttpDelete; 
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.client.methods.HttpPut; 
import org.apache.http.client.methods.HttpRequestBase; 
import org.apache.http.entity.ContentProducer; 
import org.apache.http.entity.EntityTemplate; 
import org.jibx.runtime.BindingDirectory; 
import org.jibx.runtime.IBindingFactory; 
import org.jibx.runtime.IMarshallingContext; 
import org.jibx.runtime.JiBXException; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.net.InetAddress; 
import java.net.MalformedURLException; 
import java.net.UnknownHostException; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Collections; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
 
/**
 * Implementation based on the XML documents. 
 * 
 * @author Jerome Bernard 
 */
 
public class XMLCloudServers extends RackspaceConnection implements CloudServers { 
    private static final Logger logger = Logger.getLogger(XMLCloudServers.class.getName()); 
 
    /**
     * Initializes the Rackspace Cloud Servers connection with the Rackspace login information. 
     * 
     * @param username the Rackspace username 
     * @param apiKey   the Rackspace API key 
     * @throws RackspaceException if the credentials are invalid 
     * @throws IOException        if there is a network issue 
     * @see #authenticate() 
     */
 
    public XMLCloudServers(String username, String apiKey) throws RackspaceException, IOException { 
        super(username, apiKey); 
    } 
 
    public List<Server> getServers() throws CloudServersException { 
        logger.info("Retrieving servers information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers"); 
        return buildListOfServers(request); 
    } 
 
    public List<Server> getServersWithDetails() throws CloudServersException { 
        logger.info("Retrieving detailed servers information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/detail"); 
        return buildListOfServers(request); 
    } 
 
    private List<Server> buildListOfServers(HttpGet request) throws CloudServersException { 
        Servers response = makeRequestInt(request, Servers.class); 
        List<Server> servers = new ArrayList<Server>(response.getServers().size()); 
        for (net.elasticgrid.rackspace.cloudservers.internal.Server server : response.getServers()) 
            servers.add(buildServer(server)); 
        return servers; 
    } 
 
    public Server getServerDetails(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving detailed information for server {0}...", serverID); 
        validateServerID(serverID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/" + serverID); 
        return buildServer(makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.Server.class)); 
    } 
 
    private Server buildServer(net.elasticgrid.rackspace.cloudservers.internal.Server response) throws CloudServersException { 
        try { 
            return new Server( 
                    response.getId(), response.getName(), response.getAdminPass(), 
                    response.getImageId(), response.getFlavorId(), 
                    response.getStatus() == null ? null : Status.valueOf(response.getStatus().name()), 
                    metadataAsMap(response.getMetadata()), 
                    new Addresses(response.getAddresses()), 
                    new Personality(response.getPersonality()) 
            ); 
        } catch (UnknownHostException e) { 
            throw new CloudServersException("Can't build server", e); 
        } 
    } 
 
    private static Map<String, String> metadataAsMap(Metadata metadata) { 
        if (metadata == null
            return Collections.emptyMap(); 
        Map<String, String> meta = new HashMap<String, String>(); 
        for (MetadataItem item : metadata.getMetadatas()) { 
            meta.put(item.getKey(), item.getString()); 
        } 
        return meta; 
    } 
 
    public Addresses getServerAddresses(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving all IP addresses of server {0}...", serverID); 
        validateServerID(serverID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/" + serverID + "/ips"); 
        net.elasticgrid.rackspace.cloudservers.internal.Addresses response = makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.Addresses.class); 
        try { 
            return new Addresses(response); 
        } catch (UnknownHostException e) { 
            throw new CloudServersException("Can't validate server addresses", e); 
        } 
    } 
 
    public List<InetAddress> getServerPublicAddresses(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving all public IP addresses of server {0}...", serverID); 
        validateServerID(serverID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/" + serverID + "/ips/public"); 
        Public response = makeRequestInt(request, Public.class); 
        try { 
            List<InetAddress> addresses = new ArrayList<InetAddress>(response.getAddressLists().size()); 
            for (net.elasticgrid.rackspace.cloudservers.internal.Address address : response.getAddressLists()) { 
                addresses.add(InetAddress.getByName(address.getAddr())); 
            } 
            return addresses; 
        } catch (UnknownHostException e) { 
            throw new CloudServersException("Can't validate server addresses", e); 
        } 
    } 
 
    public List<InetAddress> getServerPrivateAddresses(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving all private IP addresses of server {0}...", serverID); 
        validateServerID(serverID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/" + serverID + "/ips/private"); 
        Private response = makeRequestInt(request, Private.class); 
        try { 
            List<InetAddress> addresses = new ArrayList<InetAddress>(response.getAddressLists().size()); 
            for (net.elasticgrid.rackspace.cloudservers.internal.Address address : response.getAddressLists()) { 
                addresses.add(InetAddress.getByName(address.getAddr())); 
            } 
            return addresses; 
        } catch (UnknownHostException e) { 
            throw new CloudServersException("Can't validate server addresses", e); 
        } 
    } 
 
    public void shareAddress(int groupID, int serverID, InetAddress address) throws CloudServersException { 
        shareAddress(groupID, serverID, address, false); 
    } 
 
    public void shareAddress(int groupID, int serverID, InetAddress address, boolean configureServer) throws CloudServersException { 
        logger.log(Level.INFO, "Sharing IP in group {0} for address {1} with server {2}..."new Object[]{groupID, address, serverID}); 
        validateServerID(serverID); 
        if (address == null
            throw new IllegalArgumentException("Invalid IP address"); 
        ShareIp shareIp = new ShareIp(); 
        shareIp.setSharedIpGroupId(groupID); 
        shareIp.setConfigureServer(configureServer); 
        HttpPut request = new HttpPut(getServerManagementURL() + "/servers/" + serverID 
                + "/ips/public/" + address.getHostAddress()); 
        makeRequestInt(request); 
    } 
 
    public void unshareAddress(int serverID, InetAddress address) throws CloudServersException { 
        logger.log(Level.INFO, "Unsharing IP address {0} with server {1}..."new Object[]{address, serverID}); 
        validateServerID(serverID); 
        if (address == null
            throw new IllegalArgumentException("Invalid IP address"); 
        HttpDelete request = new HttpDelete(getServerManagementURL() + "/servers/" + serverID 
                + "/ips/public/" + address.getHostAddress()); 
        makeRequestInt(request); 
    } 
 
    public Server createServer(String name, int imageID, int flavorID) throws CloudServersException { 
        return createServer(name, imageID, flavorID, null); 
    } 
 
    public Server createServer(String name, int imageID, int flavorID, Map<String, String> metadata) throws CloudServersException { 
        logger.log(Level.INFO, "Creating server {0} from image {1} running on flavor {2}..."
                new Object[]{name, imageID, flavorID}); 
        if (name == null
            throw new IllegalArgumentException("Server name has to be specified!"); 
        if (imageID == 0
            throw new IllegalArgumentException("Image ID has to be specified!"); 
        if (flavorID == 0
            throw new IllegalArgumentException("Flavor ID has to be specified!"); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers"); 
        net.elasticgrid.rackspace.cloudservers.internal.Server server = new net.elasticgrid.rackspace.cloudservers.internal.Server(); 
        server.setName(name); 
        server.setImageId(imageID); 
        server.setFlavorId(flavorID); 
        if (metadata != null && !metadata.isEmpty()) { 
            Metadata rawMetadata = new Metadata(); 
            List<MetadataItem> metadataItems = rawMetadata.getMetadatas(); 
            for (Map.Entry<String, String> entry : metadata.entrySet()) { 
                MetadataItem item = new MetadataItem(); 
                item.setKey(entry.getKey()); 
                item.setString(entry.getValue()); 
                metadataItems.add(item); 
            } 
            server.setMetadata(rawMetadata); 
        } 
        return buildServer(makeEntityRequestInt(request, server, net.elasticgrid.rackspace.cloudservers.internal.Server.class)); 
    } 
 
    public void rebootServer(int serverID) throws CloudServersException { 
        rebootServer(serverID, RebootType.SOFT); 
    } 
 
    public void rebootServer(int serverID, RebootType type) throws CloudServersException { 
        logger.log(Level.INFO, "Rebooting server {0} via {1} reboot..."new Object[]{serverID, type.name()}); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        Reboot reboot = new Reboot(); 
        reboot.setType(net.elasticgrid.rackspace.cloudservers.internal.RebootType.valueOf(type.name())); 
        makeEntityRequestInt(request, reboot); 
    } 
 
    public void rebuildServer(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Rebuilding server {0}...", serverID); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        makeEntityRequestInt(request, new Rebuild()); 
    } 
 
    public void rebuildServer(int serverID, int imageID) throws CloudServersException { 
        logger.log(Level.INFO, "Rebuilding server {0} from image {1}..."new Object[]{serverID, imageID}); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        Rebuild rebuild = new Rebuild(); 
        rebuild.setImageId(imageID); 
        makeEntityRequestInt(request, rebuild); 
    } 
 
    public void resizeServer(int serverID, int flavorID) throws CloudServersException { 
        logger.log(Level.INFO, "Resizing server {0} to run on flavor {1}..."new Object[]{serverID, flavorID}); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        Resize resize = new Resize(); 
        resize.setFlavorId(flavorID); 
        makeEntityRequestInt(request, resize); 
    } 
 
    public void confirmResize(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Confirming resize of server {0}...", serverID); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        makeEntityRequestInt(request, new ConfirmResize()); 
    } 
 
    public void revertResize(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Cancelling resize of server {0}...", serverID); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/action"); 
        makeEntityRequestInt(request, new RevertResize()); 
    } 
 
    public void updateServerName(int serverID, String name) throws CloudServersException { 
        updateServerNameAndPassword(serverID, name, null); 
    } 
 
    public void updateServerPassword(int serverID, String password) throws CloudServersException { 
        updateServerNameAndPassword(serverID, null, password); 
    } 
 
    public void updateServerNameAndPassword(final int serverID, final String name, final String password) throws CloudServersException { 
        validateServerID(serverID); 
        HttpPut request = new HttpPut(getServerManagementURL() + "/servers/" + serverID); 
        net.elasticgrid.rackspace.cloudservers.internal.Server server = new net.elasticgrid.rackspace.cloudservers.internal.Server(); 
        server.setId(serverID); 
        if (name != null
            server.setName(name); 
        if (password != null
            server.setAdminPass(password); 
        makeEntityRequestInt(request, server); 
    } 
 
    public void deleteServer(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Deleting server {0}...", serverID); 
        validateServerID(serverID); 
        HttpDelete request = new HttpDelete(getServerManagementURL() + "/servers/" + serverID); 
        makeRequestInt(request); 
    } 
 
    public Limits getLimits() throws CloudServersException { 
        HttpGet request = new HttpGet(getServerManagementURL() + "/limits"); 
        net.elasticgrid.rackspace.cloudservers.internal.Limits response = makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.Limits.class); 
        List<RateLimit> rateLimits = new ArrayList<RateLimit>(response.getRate().getRateLimits().size()); 
        for (net.elasticgrid.rackspace.cloudservers.internal.RateLimit limit : response.getRate().getRateLimits()) 
            rateLimits.add(new RateLimit( 
                    HTTPVerb.valueOf(limit.getVerb().name()), 
                    limit.getURI(), 
                    limit.getRegex(), 
                    limit.getValue(), 
                    limit.getRemaining(), 
                    RateLimit.Unit.valueOf(limit.getUnit().name()), 
                    limit.getResetTime() 
            )); 
        List<AbsoluteLimit> absoluteLimits = new ArrayList<AbsoluteLimit>(response.getAbsolute().getAbsoluteLimits().size()); 
        for (net.elasticgrid.rackspace.cloudservers.internal.AbsoluteLimit limit : response.getAbsolute().getAbsoluteLimits()) 
            absoluteLimits.add(new AbsoluteLimit(limit.getName(), limit.getValue())); 
        return new Limits(rateLimits, absoluteLimits); 
    } 
 
    public List<Flavor> getFlavors() throws CloudServersException { 
        logger.info("Retrieving flavors information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/flavors"); 
        return buildListOfFlavors(request); 
    } 
 
    public List<Flavor> getFlavorsWithDetails() throws CloudServersException { 
        logger.info("Retrieving detailed flavors information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/flavors/detail"); 
        return buildListOfFlavors(request); 
    } 
 
    public Flavor getFlavorDetails(int flavorID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving detailed information for flavor {0}...", flavorID); 
        validateFlavorID(flavorID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/flavors/" + flavorID); 
        return buildFlavor(makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.Flavor.class)); 
    } 
 
    private List<Flavor> buildListOfFlavors(HttpGet request) throws CloudServersException { 
        Flavors response = makeRequestInt(request, Flavors.class); 
        List<Flavor> flavors = new ArrayList<Flavor>(response.getFlavors().size()); 
        for (net.elasticgrid.rackspace.cloudservers.internal.Flavor flavor : response.getFlavors()) 
            flavors.add(buildFlavor(flavor)); 
        return flavors; 
    } 
 
    private Flavor buildFlavor(net.elasticgrid.rackspace.cloudservers.internal.Flavor response) { 
        return new Flavor(response.getId(), response.getName(), response.getRam(), response.getDisk()); 
    } 
 
    public List<Image> getImages() throws CloudServersException { 
        logger.info("Retrieving images information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/images"); 
        return buildListOfImages(makeRequestInt(request, Images.class)); 
    } 
 
    public List<Image> getImagesWithDetails() throws CloudServersException { 
        logger.info("Retrieving detailed images information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/images/detail"); 
        return buildListOfImages(makeRequestInt(request, Images.class)); 
    } 
 
    public Image getImageDetails(int imageID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving detailed information for image {0}...", imageID); 
        validateImageID(imageID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/images/" + imageID); 
        return buildImage(makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.Image.class)); 
    } 
 
    public Image createImage(String name, int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Creating image named ''{0}'' from server {1}..."new Object[]{name, serverID}); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/images"); 
        net.elasticgrid.rackspace.cloudservers.internal.Image image = new net.elasticgrid.rackspace.cloudservers.internal.Image(); 
        image.setName(name); 
        image.setServerId(serverID); 
        return buildImage(makeEntityRequestInt(request, image, net.elasticgrid.rackspace.cloudservers.internal.Image.class)); 
    } 
 
    private List<Image> buildListOfImages(Images response) { 
        List<Image> images = new ArrayList<Image>(response.getImages().size()); 
        for (net.elasticgrid.rackspace.cloudservers.internal.Image image : response.getImages()) 
            images.add(buildImage(image)); 
        return images; 
    } 
 
    private Image buildImage(net.elasticgrid.rackspace.cloudservers.internal.Image created) { 
        return new Image( 
                created.getId(), created.getName(), created.getServerId(), 
                created.getUpdated(), created.getCreated(), created.getProgress(), 
                created.getStatus() == null ? null : Image.Status.valueOf(created.getStatus().name()) 
        ); 
    } 
 
    public BackupSchedule getBackupSchedule(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving backup schedule for server {0}...", serverID); 
        validateServerID(serverID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/servers/" + serverID + "/backup_schedule"); 
        net.elasticgrid.rackspace.cloudservers.internal.BackupSchedule response = makeRequestInt(request, net.elasticgrid.rackspace.cloudservers.internal.BackupSchedule.class); 
        return new BackupSchedule( 
                response.getEnabled(), 
                BackupSchedule.WeeklyBackup.valueOf(response.getWeekly().name()), 
                BackupSchedule.DailyBackup.valueOf(response.getDaily().name()) 
        ); 
    } 
 
    public void scheduleBackup(int serverID, BackupSchedule schedule) throws CloudServersException { 
        logger.log(Level.INFO, "Updating backup schedule for server {0} to {1}..."
                new Object[]{serverID, schedule}); 
        validateServerID(serverID); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/servers/" + serverID + "/backup_schedule"); 
        net.elasticgrid.rackspace.cloudservers.internal.BackupSchedule s = new net.elasticgrid.rackspace.cloudservers.internal.BackupSchedule(); 
        s.setEnabled(schedule.isEnabled()); 
        s.setWeekly(net.elasticgrid.rackspace.cloudservers.internal.WeeklyBackup.valueOf(schedule.getWeekly().name())); 
        s.setDaily(net.elasticgrid.rackspace.cloudservers.internal.DailyBackup.valueOf(schedule.getDaily().name())); 
        makeEntityRequestInt(request, s); 
    } 
 
    public void deleteBackupSchedule(int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Deleting backup schedule for server {0}...", serverID); 
        validateServerID(serverID); 
        HttpDelete request = new HttpDelete(getServerManagementURL() + "/servers/" + serverID + "/backup_schedule"); 
        makeRequestInt(request); 
    } 
 
    public List<SharedIPGroup> getSharedIPGroups() throws CloudServersException { 
        logger.info("Retrieving shared IP groups information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/shared_ip_groups"); 
        return buildListOfSharedIPGroups(request); 
    } 
 
    public List<SharedIPGroup> getSharedIPGroupsWithDetails() throws CloudServersException { 
        logger.info("Retrieving detailed shared IP groups information..."); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/shared_ip_groups/detail"); 
        return buildListOfSharedIPGroups(request); 
    } 
 
    public SharedIPGroup getSharedIPGroup(int groupID) throws CloudServersException { 
        logger.log(Level.INFO, "Retrieving detailed shared IP group information for {0}...", groupID); 
        HttpGet request = new HttpGet(getServerManagementURL() + "/shared_ip_groups/" + groupID); 
        return buildSharedIPGroup(makeRequestInt(request, SharedIpGroup.class)); 
    } 
 
    public SharedIPGroup createSharedIPGroup(String name) throws CloudServersException { 
        return createSharedIPGroup(name, 0); 
    } 
 
    public SharedIPGroup createSharedIPGroup(String name, int serverID) throws CloudServersException { 
        logger.log(Level.INFO, "Creating shared IP group named {0} for server {1}..."new Object[]{name, serverID}); 
        HttpPost request = new HttpPost(getServerManagementURL() + "/shared_ip_groups"); 
        SharedIpGroup group = new SharedIpGroup(); 
        group.setName(name); 
        if (serverID != 0) { 
            ServerID server = new ServerID(); 
            server.setId(serverID); 
            group.setServer(server); 
        } 
        return buildSharedIPGroup(makeEntityRequestInt(request, group, SharedIpGroup.class)); 
    } 
 
    public void deleteSharedIPGroup(int groupID) throws CloudServersException { 
        logger.log(Level.INFO, "Deleting shared IP group {0}...", groupID); 
        validateSharedIPGroupID(groupID); 
        HttpDelete request = new HttpDelete(getServerManagementURL() + "/shared_ip_groups/" + groupID); 
        makeRequestInt(request); 
    } 
 
    private List<SharedIPGroup> buildListOfSharedIPGroups(HttpGet request) throws CloudServersException { 
        SharedIpGroups response = makeRequestInt(request, SharedIpGroups.class); 
        List<SharedIPGroup> groups = new ArrayList<SharedIPGroup>(response.getSharedIpGroups().size()); 
        for (SharedIpGroup group : response.getSharedIpGroups()) 
            groups.add(buildSharedIPGroup(group)); 
        return groups; 
    } 
 
    private SharedIPGroup buildSharedIPGroup(SharedIpGroup group) { 
        List<Integer> serverIDs = new ArrayList<Integer>(group.getServers().getServerIDLists().size()); 
        for (ServerID id : group.getServers().getServerIDLists()) 
            serverIDs.add(id.getId()); 
        return new SharedIPGroup(group.getId(), group.getName(), serverIDs); 
    } 
 
    protected void makeEntityRequestInt(HttpEntityEnclosingRequestBase request, final Object entity) throws CloudServersException { 
        makeEntityRequestInt(request, entity, Void.class); 
    } 
 
    protected <T> T makeEntityRequestInt(HttpEntityEnclosingRequestBase request, final Object entity, Class<T> respType) throws CloudServersException { 
        request.setEntity(new EntityTemplate(new ContentProducer() { 
            public void writeTo(OutputStream output) throws IOException { 
                try { 
                    IBindingFactory bindingFactory = BindingDirectory.getFactory(entity.getClass()); 
                    final IMarshallingContext marshallingCxt = bindingFactory.createMarshallingContext(); 
                    marshallingCxt.marshalDocument(entity, "UTF-8"true, output); 
                } catch (JiBXException e) { 
                    IOException ioe = new IOException("Can't marshal server details"); 
                    ioe.initCause(e); 
                    e.printStackTrace(); 
                    throw ioe; 
                } 
            } 
        })); 
        return makeRequestInt(request, respType); 
    } 
 
    protected void makeRequestInt(HttpRequestBase request) throws CloudServersException { 
        makeRequestInt(request, Void.class); 
    } 
 
    protected <T> T makeRequestInt(HttpRequestBase request, Class<T> respType) throws CloudServersException { 
        try { 
            return makeRequest(request, respType); 
        } catch (RackspaceException e) { 
            throw new CloudServersException(e); 
        } catch (JiBXException e) { 
            throw new CloudServersException("Problem parsing returned message.", e); 
        } catch (MalformedURLException e) { 
            throw new CloudServersException(e.getMessage(), e); 
        } catch (IOException e) { 
            throw new CloudServersException(e.getMessage(), e); 
        } catch (HttpException e) { 
            throw new CloudServersException(e.getMessage(), e); 
        } 
    } 
 
    private void validateServerID(int serverID) throws IllegalArgumentException { 
        if (serverID == 0
            throw new IllegalArgumentException("Invalid serverID " + serverID); 
    } 
 
    private void validateFlavorID(int flavorID) throws IllegalArgumentException { 
        if (flavorID == 0
            throw new IllegalArgumentException("Invalid flavorID " + flavorID); 
    } 
 
    private void validateImageID(int imageID) throws IllegalArgumentException { 
        if (imageID == 0
            throw new IllegalArgumentException("Invalid imageID " + imageID); 
    } 
 
    private void validateSharedIPGroupID(int groupID) throws IllegalArgumentException { 
        if (groupID == 0
            throw new IllegalArgumentException("Invalid shared IP group ID " + groupID); 
    } 
}