View Javadoc

1   /**
2    * Licensed to jclouds, Inc. (jclouds) under one or more
3    * contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  jclouds licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.jclouds.aws.ec2.xml;
20  
21  import static org.jclouds.util.SaxUtils.currentOrNull;
22  import static org.jclouds.util.SaxUtils.equalsOrSuffix;
23  
24  import java.util.Date;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.annotation.Resource;
29  import javax.inject.Inject;
30  
31  import org.jclouds.aws.ec2.domain.AWSRunningInstance;
32  import org.jclouds.aws.ec2.domain.MonitoringState;
33  import org.jclouds.aws.util.AWSUtils;
34  import org.jclouds.date.DateCodec;
35  import org.jclouds.date.DateCodecFactory;
36  import org.jclouds.ec2.domain.Attachment;
37  import org.jclouds.ec2.domain.BlockDevice;
38  import org.jclouds.ec2.domain.Hypervisor;
39  import org.jclouds.ec2.domain.InstanceState;
40  import org.jclouds.ec2.domain.Reservation;
41  import org.jclouds.ec2.domain.RootDeviceType;
42  import org.jclouds.ec2.domain.RunningInstance;
43  import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
44  import org.jclouds.location.Region;
45  import org.jclouds.logging.Logger;
46  import org.xml.sax.Attributes;
47  import org.xml.sax.SAXException;
48  
49  import com.google.common.base.Supplier;
50  import com.google.common.collect.Maps;
51  import com.google.common.collect.Sets;
52  import com.google.inject.Provider;
53  
54  /**
55   * 
56   * @author Adrian Cole
57   */
58  public abstract class BaseAWSReservationHandler<T> extends HandlerForGeneratedRequestWithResult<T> {
59  
60     @Resource
61     protected Logger logger = Logger.NULL;
62  
63     protected final DateCodec dateCodec;
64     protected final Supplier<String> defaultRegion;
65     protected final Provider<AWSRunningInstance.Builder> builderProvider;
66  
67     @Inject
68     public BaseAWSReservationHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
69           Provider<AWSRunningInstance.Builder> builderProvider) {
70        this.dateCodec = dateCodecFactory.iso8601();
71        this.defaultRegion = defaultRegion;
72        this.builderProvider = builderProvider;
73        this.builder = builderProvider.get();
74     }
75  
76     protected StringBuilder currentText = new StringBuilder();
77  
78     protected AWSRunningInstance.Builder builder;
79  
80     protected int itemDepth;
81     boolean inInstancesSet;
82     // attachments
83     private String volumeId;
84     private Attachment.Status attachmentStatus;
85     private Date attachTime;
86     private boolean deleteOnTermination;
87     private String deviceName;
88  
89     // reservation stuff
90     private String groupId;
91     private Map<String, String> reservationGroupIdToNames = Maps.newLinkedHashMap();
92     private String ownerId;
93     private String requesterId;
94     private String reservationId;
95  
96     private Set<RunningInstance> instances = Sets.newLinkedHashSet();
97  
98     protected int depth = 0;
99  
100    private boolean inPlacement;
101    private boolean inIamInstanceProfile;
102 
103    @Override
104    public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
105       if (equalsOrSuffix(qName, "item")) {
106          itemDepth++;
107       } else if (equalsOrSuffix(qName, "instancesSet")) {
108          inInstancesSet = true;
109       } else if (equalsOrSuffix(qName, "placement")) {
110          inPlacement = true;
111       } else if (equalsOrSuffix(qName, "iamInstanceProfile")) {
112          inIamInstanceProfile = true;
113       }
114    }
115 
116    public void endElement(String uri, String name, String qName) {
117       if (equalsOrSuffix(qName, "item")) {
118          inItem();
119          itemDepth--;
120       } else if (equalsOrSuffix(qName, "state")) {
121          builder.monitoringState(MonitoringState.fromValue(currentOrNull(currentText)));
122       } else if (equalsOrSuffix(qName, "groupId")) {
123          groupId = currentOrNull(currentText);
124       } else if (equalsOrSuffix(qName, "groupName") && inPlacement) {
125          builder.placementGroup(currentOrNull(currentText));
126       } else if (equalsOrSuffix(qName, "arn") && inIamInstanceProfile) {
127          builder.iamInstanceProfileArn(currentOrNull(currentText));
128       } else if (equalsOrSuffix(qName, "id") && inIamInstanceProfile) {
129          builder.iamInstanceProfileId(currentOrNull(currentText));
130       } else if (equalsOrSuffix(qName, "groupName")) {
131          switch (itemDepth) {
132          case 2:
133             reservationGroupIdToNames.put(groupId, currentOrNull(currentText));
134             break;
135          case 3:
136             builder.securityGroupIdToName(groupId, currentOrNull(currentText));
137             break;
138          }
139          groupId = null;
140       } else if (equalsOrSuffix(qName, "subnetId")) {
141          builder.subnetId(currentOrNull(currentText));
142       } else if (equalsOrSuffix(qName, "spotInstanceRequestId")) {
143          builder.spotInstanceRequestId(currentOrNull(currentText));
144       } else if (equalsOrSuffix(qName, "vpcId")) {
145          builder.vpcId(currentOrNull(currentText));
146       } else if (equalsOrSuffix(qName, "hypervisor")) {
147          builder.hypervisor(Hypervisor.fromValue(currentOrNull(currentText)));
148       } else if (equalsOrSuffix(qName, "productCode")) {
149          builder.productCode(currentOrNull(currentText));
150       } else if (equalsOrSuffix(qName, "instancesSet")) {
151          inInstancesSet = false;
152       } else if (equalsOrSuffix(qName, "placement")) {
153          inPlacement = false;
154       } else if (equalsOrSuffix(qName, "iamInstanceProfile")) {
155          inIamInstanceProfile = false;
156       } else if (equalsOrSuffix(qName, "ownerId")) {
157          ownerId = currentOrNull(currentText);
158       } else if (equalsOrSuffix(qName, "requesterId")) {
159          requesterId = currentOrNull(currentText);
160       } else if (equalsOrSuffix(qName, "reservationId")) {
161          reservationId = currentOrNull(currentText);
162       } else if (equalsOrSuffix(qName, "amiLaunchIndex")) {
163          builder.amiLaunchIndex(currentOrNull(currentText));
164       } else if (equalsOrSuffix(qName, "dnsName")) {
165          builder.dnsName(currentOrNull(currentText));
166       } else if (equalsOrSuffix(qName, "imageId")) {
167          builder.imageId(currentOrNull(currentText));
168       } else if (equalsOrSuffix(qName, "instanceId")) {
169          builder.instanceId(currentOrNull(currentText));
170       } else if (equalsOrSuffix(qName, "name")) {
171          String rawState = currentOrNull(currentText);
172          builder.rawState(rawState);
173          builder.instanceState(InstanceState.fromValue(rawState));
174       } else if (equalsOrSuffix(qName, "instanceType")) {
175          builder.instanceType(currentOrNull(currentText));
176       } else if (equalsOrSuffix(qName, "ipAddress")) {
177          builder.ipAddress(currentOrNull(currentText));
178       } else if (equalsOrSuffix(qName, "kernelId")) {
179          builder.kernelId(currentOrNull(currentText));
180       } else if (equalsOrSuffix(qName, "keyName")) {
181          builder.keyName(currentOrNull(currentText));
182       } else if (equalsOrSuffix(qName, "launchTime")) {
183          builder.launchTime(dateCodec.toDate(currentOrNull(currentText)));
184       } else if (equalsOrSuffix(qName, "availabilityZone")) {
185          builder.availabilityZone(currentOrNull(currentText));
186       } else if (equalsOrSuffix(qName, "virtualizationType")) {
187          builder.virtualizationType(currentOrNull(currentText));
188       } else if (equalsOrSuffix(qName, "platform")) {
189          builder.platform(currentOrNull(currentText));
190       } else if (equalsOrSuffix(qName, "privateDnsName")) {
191          builder.privateDnsName(currentOrNull(currentText));
192       } else if (equalsOrSuffix(qName, "privateIpAddress")) {
193          builder.privateIpAddress(currentOrNull(currentText));
194       } else if (equalsOrSuffix(qName, "ramdiskId")) {
195          builder.ramdiskId(currentOrNull(currentText));
196       } else if (equalsOrSuffix(qName, "reason")) {
197          builder.reason(currentOrNull(currentText));
198       } else if (equalsOrSuffix(qName, "rootDeviceType")) {
199          builder.rootDeviceType(RootDeviceType.fromValue(currentOrNull(currentText)));
200       } else if (equalsOrSuffix(qName, "rootDeviceName")) {
201          builder.rootDeviceName(currentOrNull(currentText));
202       } else if (equalsOrSuffix(qName, "deviceName")) {
203          deviceName = currentOrNull(currentText);
204       } else if (equalsOrSuffix(qName, "volumeId")) {
205          volumeId = currentOrNull(currentText);
206       } else if (equalsOrSuffix(qName, "status")) {
207          attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
208       } else if (equalsOrSuffix(qName, "attachTime")) {
209          attachTime = dateCodec.toDate(currentOrNull(currentText));
210       } else if (equalsOrSuffix(qName, "deleteOnTermination")) {
211          deleteOnTermination = Boolean.parseBoolean(currentText.toString().trim());
212       } else if (equalsOrSuffix(qName, "ebs")) {
213          builder.device(deviceName, new BlockDevice(volumeId, attachmentStatus, attachTime, deleteOnTermination));
214          this.deviceName = null;
215          this.volumeId = null;
216          this.attachmentStatus = null;
217          this.attachTime = null;
218          this.deleteOnTermination = true;
219       }
220       currentText = new StringBuilder();
221    }
222    
223    protected void inItem() {
224       if (endOfInstanceItem()) {
225          refineBuilderBeforeAddingInstance();
226          instances.add(builder.build());
227          builder = builderProvider.get();
228       }
229    }
230 
231    protected void refineBuilderBeforeAddingInstance() {
232       String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
233       builder.region((region == null) ? defaultRegion.get() : region);
234    }
235 
236    protected abstract boolean endOfInstanceItem();
237 
238    public void characters(char ch[], int start, int length) {
239       currentText.append(ch, start, length);
240    }
241 
242    protected Reservation<? extends RunningInstance> newReservation() {
243       String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
244       if (region == null)
245          region = defaultRegion.get();
246       Reservation<? extends RunningInstance> info = new Reservation<RunningInstance>(region,
247             reservationGroupIdToNames.values(), instances, ownerId, requesterId, reservationId);
248       this.reservationGroupIdToNames = Maps.newLinkedHashMap();
249       this.instances = Sets.newLinkedHashSet();
250       this.ownerId = null;
251       this.requesterId = null;
252       this.reservationId = null;
253       return info;
254    }
255 
256 }