// 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.

/**
 * AmazonEC2Skeleton.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version: 1.5.1  Built on : Oct 19, 2009 (10:59:00 EDT)
 */
    package com.amazon.ec2;
    /**
     *  AmazonEC2Skeleton java skeleton for the axisService
     */
    public class AmazonEC2Skeleton implements AmazonEC2SkeletonInterface{
        
         
        /**
         * Auto generated method signature
         * 
                                     * @param registerImage0
         */
        
                 public com.amazon.ec2.RegisterImageResponse registerImage
                  (
                  com.amazon.ec2.RegisterImage registerImage0
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#registerImage");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteTags2
         */
        
                 public com.amazon.ec2.DeleteTagsResponse deleteTags
                  (
                  com.amazon.ec2.DeleteTags deleteTags2
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteTags");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createKeyPair4
         */
        
                 public com.amazon.ec2.CreateKeyPairResponse createKeyPair
                  (
                  com.amazon.ec2.CreateKeyPair createKeyPair4
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createKeyPair");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param terminateInstances6
         */
        
                 public com.amazon.ec2.TerminateInstancesResponse terminateInstances
                  (
                  com.amazon.ec2.TerminateInstances terminateInstances6
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#terminateInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeImageAttribute8
         */
        
                 public com.amazon.ec2.DescribeImageAttributeResponse describeImageAttribute
                  (
                  com.amazon.ec2.DescribeImageAttribute describeImageAttribute8
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeImageAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSecurityGroups10
         */
        
                 public com.amazon.ec2.DescribeSecurityGroupsResponse describeSecurityGroups
                  (
                  com.amazon.ec2.DescribeSecurityGroups describeSecurityGroups10
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSecurityGroups");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describePlacementGroups12
         */
        
                 public com.amazon.ec2.DescribePlacementGroupsResponse describePlacementGroups
                  (
                  com.amazon.ec2.DescribePlacementGroups describePlacementGroups12
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describePlacementGroups");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createVpnConnection14
         */
        
                 public com.amazon.ec2.CreateVpnConnectionResponse createVpnConnection
                  (
                  com.amazon.ec2.CreateVpnConnection createVpnConnection14
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createVpnConnection");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param attachVpnGateway16
         */
        
                 public com.amazon.ec2.AttachVpnGatewayResponse attachVpnGateway
                  (
                  com.amazon.ec2.AttachVpnGateway attachVpnGateway16
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#attachVpnGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createVolume18
         */
        
                 public com.amazon.ec2.CreateVolumeResponse createVolume
                  (
                  com.amazon.ec2.CreateVolume createVolume18
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createVolume");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param releaseAddress20
         */
        
                 public com.amazon.ec2.ReleaseAddressResponse releaseAddress
                  (
                  com.amazon.ec2.ReleaseAddress releaseAddress20
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#releaseAddress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeRegions22
         */
        
                 public com.amazon.ec2.DescribeRegionsResponse describeRegions
                  (
                  com.amazon.ec2.DescribeRegions describeRegions22
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeRegions");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteSubnet24
         */
        
                 public com.amazon.ec2.DeleteSubnetResponse deleteSubnet
                  (
                  com.amazon.ec2.DeleteSubnet deleteSubnet24
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteSubnet");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeVpcs26
         */
        
                 public com.amazon.ec2.DescribeVpcsResponse describeVpcs
                  (
                  com.amazon.ec2.DescribeVpcs describeVpcs26
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeVpcs");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSpotPriceHistory28
         */
        
                 public com.amazon.ec2.DescribeSpotPriceHistoryResponse describeSpotPriceHistory
                  (
                  com.amazon.ec2.DescribeSpotPriceHistory describeSpotPriceHistory28
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSpotPriceHistory");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeReservedInstances30
         */
        
                 public com.amazon.ec2.DescribeReservedInstancesResponse describeReservedInstances
                  (
                  com.amazon.ec2.DescribeReservedInstances describeReservedInstances30
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeReservedInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeTags32
         */
        
                 public com.amazon.ec2.DescribeTagsResponse describeTags
                  (
                  com.amazon.ec2.DescribeTags describeTags32
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeTags");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param importVolume34
         */
        
                 public com.amazon.ec2.ImportVolumeResponse importVolume
                  (
                  com.amazon.ec2.ImportVolume importVolume34
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#importVolume");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSpotDatafeedSubscription36
         */
        
                 public com.amazon.ec2.DescribeSpotDatafeedSubscriptionResponse describeSpotDatafeedSubscription
                  (
                  com.amazon.ec2.DescribeSpotDatafeedSubscription describeSpotDatafeedSubscription36
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSpotDatafeedSubscription");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deactivateLicense38
         */
        
                 public com.amazon.ec2.DeactivateLicenseResponse deactivateLicense
                  (
                  com.amazon.ec2.DeactivateLicense deactivateLicense38
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deactivateLicense");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param detachVolume40
         */
        
                 public com.amazon.ec2.DetachVolumeResponse detachVolume
                  (
                  com.amazon.ec2.DetachVolume detachVolume40
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#detachVolume");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeReservedInstancesOfferings42
         */
        
                 public com.amazon.ec2.DescribeReservedInstancesOfferingsResponse describeReservedInstancesOfferings
                  (
                  com.amazon.ec2.DescribeReservedInstancesOfferings describeReservedInstancesOfferings42
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeReservedInstancesOfferings");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeConversionTasks44
         */
        
                 public com.amazon.ec2.DescribeConversionTasksResponse describeConversionTasks
                  (
                  com.amazon.ec2.DescribeConversionTasks describeConversionTasks44
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeConversionTasks");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteCustomerGateway46
         */
        
                 public com.amazon.ec2.DeleteCustomerGatewayResponse deleteCustomerGateway
                  (
                  com.amazon.ec2.DeleteCustomerGateway deleteCustomerGateway46
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteCustomerGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deletePlacementGroup48
         */
        
                 public com.amazon.ec2.DeletePlacementGroupResponse deletePlacementGroup
                  (
                  com.amazon.ec2.DeletePlacementGroup deletePlacementGroup48
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deletePlacementGroup");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param requestSpotInstances50
         */
        
                 public com.amazon.ec2.RequestSpotInstancesResponse requestSpotInstances
                  (
                  com.amazon.ec2.RequestSpotInstances requestSpotInstances50
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#requestSpotInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param confirmProductInstance52
         */
        
                 public com.amazon.ec2.ConfirmProductInstanceResponse confirmProductInstance
                  (
                  com.amazon.ec2.ConfirmProductInstance confirmProductInstance52
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#confirmProductInstance");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param modifySnapshotAttribute54
         */
        
                 public com.amazon.ec2.ModifySnapshotAttributeResponse modifySnapshotAttribute
                  (
                  com.amazon.ec2.ModifySnapshotAttribute modifySnapshotAttribute54
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#modifySnapshotAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param purchaseReservedInstancesOffering56
         */
        
                 public com.amazon.ec2.PurchaseReservedInstancesOfferingResponse purchaseReservedInstancesOffering
                  (
                  com.amazon.ec2.PurchaseReservedInstancesOffering purchaseReservedInstancesOffering56
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#purchaseReservedInstancesOffering");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param cancelConversionTask58
         */
        
                 public com.amazon.ec2.CancelConversionTaskResponse cancelConversionTask
                  (
                  com.amazon.ec2.CancelConversionTask cancelConversionTask58
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#cancelConversionTask");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteVpnConnection60
         */
        
                 public com.amazon.ec2.DeleteVpnConnectionResponse deleteVpnConnection
                  (
                  com.amazon.ec2.DeleteVpnConnection deleteVpnConnection60
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteVpnConnection");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param detachVpnGateway62
         */
        
                 public com.amazon.ec2.DetachVpnGatewayResponse detachVpnGateway
                  (
                  com.amazon.ec2.DetachVpnGateway detachVpnGateway62
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#detachVpnGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeCustomerGateways64
         */
        
                 public com.amazon.ec2.DescribeCustomerGatewaysResponse describeCustomerGateways
                  (
                  com.amazon.ec2.DescribeCustomerGateways describeCustomerGateways64
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeCustomerGateways");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeLicenses66
         */
        
                 public com.amazon.ec2.DescribeLicensesResponse describeLicenses
                  (
                  com.amazon.ec2.DescribeLicenses describeLicenses66
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeLicenses");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param revokeSecurityGroupIngress68
         */
        
                 public com.amazon.ec2.RevokeSecurityGroupIngressResponse revokeSecurityGroupIngress
                  (
                  com.amazon.ec2.RevokeSecurityGroupIngress revokeSecurityGroupIngress68
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#revokeSecurityGroupIngress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSubnets70
         */
        
                 public com.amazon.ec2.DescribeSubnetsResponse describeSubnets
                  (
                  com.amazon.ec2.DescribeSubnets describeSubnets70
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSubnets");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param resetSnapshotAttribute72
         */
        
                 public com.amazon.ec2.ResetSnapshotAttributeResponse resetSnapshotAttribute
                  (
                  com.amazon.ec2.ResetSnapshotAttribute resetSnapshotAttribute72
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#resetSnapshotAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeAddresses74
         */
        
                 public com.amazon.ec2.DescribeAddressesResponse describeAddresses
                  (
                  com.amazon.ec2.DescribeAddresses describeAddresses74
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeAddresses");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createSecurityGroup76
         */
        
                 public com.amazon.ec2.CreateSecurityGroupResponse createSecurityGroup
                  (
                  com.amazon.ec2.CreateSecurityGroup createSecurityGroup76
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createSecurityGroup");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param allocateAddress78
         */
        
                 public com.amazon.ec2.AllocateAddressResponse allocateAddress
                  (
                  com.amazon.ec2.AllocateAddress allocateAddress78
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#allocateAddress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param importKeyPair80
         */
        
                 public com.amazon.ec2.ImportKeyPairResponse importKeyPair
                  (
                  com.amazon.ec2.ImportKeyPair importKeyPair80
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#importKeyPair");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createTags82
         */
        
                 public com.amazon.ec2.CreateTagsResponse createTags
                  (
                  com.amazon.ec2.CreateTags createTags82
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createTags");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param startInstances84
         */
        
                 public com.amazon.ec2.StartInstancesResponse startInstances
                  (
                  com.amazon.ec2.StartInstances startInstances84
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#startInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeVpnConnections86
         */
        
                 public com.amazon.ec2.DescribeVpnConnectionsResponse describeVpnConnections
                  (
                  com.amazon.ec2.DescribeVpnConnections describeVpnConnections86
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeVpnConnections");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param rebootInstances88
         */
        
                 public com.amazon.ec2.RebootInstancesResponse rebootInstances
                  (
                  com.amazon.ec2.RebootInstances rebootInstances88
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#rebootInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeAvailabilityZones90
         */
        
                 public com.amazon.ec2.DescribeAvailabilityZonesResponse describeAvailabilityZones
                  (
                  com.amazon.ec2.DescribeAvailabilityZones describeAvailabilityZones90
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeAvailabilityZones");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param bundleInstance92
         */
        
                 public com.amazon.ec2.BundleInstanceResponse bundleInstance
                  (
                  com.amazon.ec2.BundleInstance bundleInstance92
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#bundleInstance");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param activateLicense94
         */
        
                 public com.amazon.ec2.ActivateLicenseResponse activateLicense
                  (
                  com.amazon.ec2.ActivateLicense activateLicense94
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#activateLicense");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSnapshots96
         */
        
                 public com.amazon.ec2.DescribeSnapshotsResponse describeSnapshots
                  (
                  com.amazon.ec2.DescribeSnapshots describeSnapshots96
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSnapshots");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createPlacementGroup98
         */
        
                 public com.amazon.ec2.CreatePlacementGroupResponse createPlacementGroup
                  (
                  com.amazon.ec2.CreatePlacementGroup createPlacementGroup98
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createPlacementGroup");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSpotInstanceRequests100
         */
        
                 public com.amazon.ec2.DescribeSpotInstanceRequestsResponse describeSpotInstanceRequests
                  (
                  com.amazon.ec2.DescribeSpotInstanceRequests describeSpotInstanceRequests100
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSpotInstanceRequests");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param associateAddress102
         */
        
                 public com.amazon.ec2.AssociateAddressResponse associateAddress
                  (
                  com.amazon.ec2.AssociateAddress associateAddress102
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#associateAddress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param runInstances104
         */
        
                 public com.amazon.ec2.RunInstancesResponse runInstances
                  (
                  com.amazon.ec2.RunInstances runInstances104
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#runInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteSecurityGroup106
         */
        
                 public com.amazon.ec2.DeleteSecurityGroupResponse deleteSecurityGroup
                  (
                  com.amazon.ec2.DeleteSecurityGroup deleteSecurityGroup106
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteSecurityGroup");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteVpc108
         */
        
                 public com.amazon.ec2.DeleteVpcResponse deleteVpc
                  (
                  com.amazon.ec2.DeleteVpc deleteVpc108
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteVpc");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteVolume110
         */
        
                 public com.amazon.ec2.DeleteVolumeResponse deleteVolume
                  (
                  com.amazon.ec2.DeleteVolume deleteVolume110
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteVolume");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createVpnGateway112
         */
        
                 public com.amazon.ec2.CreateVpnGatewayResponse createVpnGateway
                  (
                  com.amazon.ec2.CreateVpnGateway createVpnGateway112
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createVpnGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param resetInstanceAttribute114
         */
        
                 public com.amazon.ec2.ResetInstanceAttributeResponse resetInstanceAttribute
                  (
                  com.amazon.ec2.ResetInstanceAttribute resetInstanceAttribute114
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#resetInstanceAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createVpc116
         */
        
                 public com.amazon.ec2.CreateVpcResponse createVpc
                  (
                  com.amazon.ec2.CreateVpc createVpc116
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createVpc");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteKeyPair118
         */
        
                 public com.amazon.ec2.DeleteKeyPairResponse deleteKeyPair
                  (
                  com.amazon.ec2.DeleteKeyPair deleteKeyPair118
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteKeyPair");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param stopInstances120
         */
        
                 public com.amazon.ec2.StopInstancesResponse stopInstances
                  (
                  com.amazon.ec2.StopInstances stopInstances120
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#stopInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createImage122
         */
        
                 public com.amazon.ec2.CreateImageResponse createImage
                  (
                  com.amazon.ec2.CreateImage createImage122
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createImage");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeVolumes124
         */
        
                 public com.amazon.ec2.DescribeVolumesResponse describeVolumes
                  (
                  com.amazon.ec2.DescribeVolumes describeVolumes124
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeVolumes");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeKeyPairs126
         */
        
                 public com.amazon.ec2.DescribeKeyPairsResponse describeKeyPairs
                  (
                  com.amazon.ec2.DescribeKeyPairs describeKeyPairs126
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeKeyPairs");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createCustomerGateway128
         */
        
                 public com.amazon.ec2.CreateCustomerGatewayResponse createCustomerGateway
                  (
                  com.amazon.ec2.CreateCustomerGateway createCustomerGateway128
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createCustomerGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeImages130
         */
        
                 public com.amazon.ec2.DescribeImagesResponse describeImages
                  (
                  com.amazon.ec2.DescribeImages describeImages130
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeImages");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createSubnet132
         */
        
                 public com.amazon.ec2.CreateSubnetResponse createSubnet
                  (
                  com.amazon.ec2.CreateSubnet createSubnet132
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createSubnet");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param disassociateAddress134
         */
        
                 public com.amazon.ec2.DisassociateAddressResponse disassociateAddress
                  (
                  com.amazon.ec2.DisassociateAddress disassociateAddress134
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#disassociateAddress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteVpnGateway136
         */
        
                 public com.amazon.ec2.DeleteVpnGatewayResponse deleteVpnGateway
                  (
                  com.amazon.ec2.DeleteVpnGateway deleteVpnGateway136
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteVpnGateway");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param cancelSpotInstanceRequests138
         */
        
                 public com.amazon.ec2.CancelSpotInstanceRequestsResponse cancelSpotInstanceRequests
                  (
                  com.amazon.ec2.CancelSpotInstanceRequests cancelSpotInstanceRequests138
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#cancelSpotInstanceRequests");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param monitorInstances140
         */
        
                 public com.amazon.ec2.MonitorInstancesResponse monitorInstances
                  (
                  com.amazon.ec2.MonitorInstances monitorInstances140
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#monitorInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createSnapshot142
         */
        
                 public com.amazon.ec2.CreateSnapshotResponse createSnapshot
                  (
                  com.amazon.ec2.CreateSnapshot createSnapshot142
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createSnapshot");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param resetImageAttribute144
         */
        
                 public com.amazon.ec2.ResetImageAttributeResponse resetImageAttribute
                  (
                  com.amazon.ec2.ResetImageAttribute resetImageAttribute144
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#resetImageAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param attachVolume146
         */
        
                 public com.amazon.ec2.AttachVolumeResponse attachVolume
                  (
                  com.amazon.ec2.AttachVolume attachVolume146
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#attachVolume");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeInstanceAttribute148
         */
        
                 public com.amazon.ec2.DescribeInstanceAttributeResponse describeInstanceAttribute
                  (
                  com.amazon.ec2.DescribeInstanceAttribute describeInstanceAttribute148
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeInstanceAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param authorizeSecurityGroupIngress150
         */
        
                 public com.amazon.ec2.AuthorizeSecurityGroupIngressResponse authorizeSecurityGroupIngress
                  (
                  com.amazon.ec2.AuthorizeSecurityGroupIngress authorizeSecurityGroupIngress150
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#authorizeSecurityGroupIngress");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param modifyInstanceAttribute152
         */
        
                 public com.amazon.ec2.ModifyInstanceAttributeResponse modifyInstanceAttribute
                  (
                  com.amazon.ec2.ModifyInstanceAttribute modifyInstanceAttribute152
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#modifyInstanceAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeSnapshotAttribute154
         */
        
                 public com.amazon.ec2.DescribeSnapshotAttributeResponse describeSnapshotAttribute
                  (
                  com.amazon.ec2.DescribeSnapshotAttribute describeSnapshotAttribute154
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeSnapshotAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param getConsoleOutput156
         */
        
                 public com.amazon.ec2.GetConsoleOutputResponse getConsoleOutput
                  (
                  com.amazon.ec2.GetConsoleOutput getConsoleOutput156
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#getConsoleOutput");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeDhcpOptions158
         */
        
                 public com.amazon.ec2.DescribeDhcpOptionsResponse describeDhcpOptions
                  (
                  com.amazon.ec2.DescribeDhcpOptions describeDhcpOptions158
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeDhcpOptions");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param cancelBundleTask160
         */
        
                 public com.amazon.ec2.CancelBundleTaskResponse cancelBundleTask
                  (
                  com.amazon.ec2.CancelBundleTask cancelBundleTask160
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#cancelBundleTask");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteSnapshot162
         */
        
                 public com.amazon.ec2.DeleteSnapshotResponse deleteSnapshot
                  (
                  com.amazon.ec2.DeleteSnapshot deleteSnapshot162
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteSnapshot");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createSpotDatafeedSubscription164
         */
        
                 public com.amazon.ec2.CreateSpotDatafeedSubscriptionResponse createSpotDatafeedSubscription
                  (
                  com.amazon.ec2.CreateSpotDatafeedSubscription createSpotDatafeedSubscription164
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createSpotDatafeedSubscription");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteSpotDatafeedSubscription166
         */
        
                 public com.amazon.ec2.DeleteSpotDatafeedSubscriptionResponse deleteSpotDatafeedSubscription
                  (
                  com.amazon.ec2.DeleteSpotDatafeedSubscription deleteSpotDatafeedSubscription166
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteSpotDatafeedSubscription");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deregisterImage168
         */
        
                 public com.amazon.ec2.DeregisterImageResponse deregisterImage
                  (
                  com.amazon.ec2.DeregisterImage deregisterImage168
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deregisterImage");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeBundleTasks170
         */
        
                 public com.amazon.ec2.DescribeBundleTasksResponse describeBundleTasks
                  (
                  com.amazon.ec2.DescribeBundleTasks describeBundleTasks170
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeBundleTasks");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param createDhcpOptions172
         */
        
                 public com.amazon.ec2.CreateDhcpOptionsResponse createDhcpOptions
                  (
                  com.amazon.ec2.CreateDhcpOptions createDhcpOptions172
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#createDhcpOptions");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param modifyImageAttribute174
         */
        
                 public com.amazon.ec2.ModifyImageAttributeResponse modifyImageAttribute
                  (
                  com.amazon.ec2.ModifyImageAttribute modifyImageAttribute174
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#modifyImageAttribute");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeInstances176
         */
        
                 public com.amazon.ec2.DescribeInstancesResponse describeInstances
                  (
                  com.amazon.ec2.DescribeInstances describeInstances176
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param describeVpnGateways178
         */
        
                 public com.amazon.ec2.DescribeVpnGatewaysResponse describeVpnGateways
                  (
                  com.amazon.ec2.DescribeVpnGateways describeVpnGateways178
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#describeVpnGateways");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param deleteDhcpOptions180
         */
        
                 public com.amazon.ec2.DeleteDhcpOptionsResponse deleteDhcpOptions
                  (
                  com.amazon.ec2.DeleteDhcpOptions deleteDhcpOptions180
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#deleteDhcpOptions");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param importInstance182
         */
        
                 public com.amazon.ec2.ImportInstanceResponse importInstance
                  (
                  com.amazon.ec2.ImportInstance importInstance182
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#importInstance");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param associateDhcpOptions184
         */
        
                 public com.amazon.ec2.AssociateDhcpOptionsResponse associateDhcpOptions
                  (
                  com.amazon.ec2.AssociateDhcpOptions associateDhcpOptions184
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#associateDhcpOptions");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param unmonitorInstances186
         */
        
                 public com.amazon.ec2.UnmonitorInstancesResponse unmonitorInstances
                  (
                  com.amazon.ec2.UnmonitorInstances unmonitorInstances186
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#unmonitorInstances");
        }
     
         
        /**
         * Auto generated method signature
         * 
                                     * @param getPasswordData188
         */
        
                 public com.amazon.ec2.GetPasswordDataResponse getPasswordData
                  (
                  com.amazon.ec2.GetPasswordData getPasswordData188
                  )
            {
                //TODO : fill this with the necessary business logic
                throw new  java.lang.UnsupportedOperationException("Please implement " + this.getClass().getName() + "#getPasswordData");
        }
     
    }
    