View Javadoc

1   /**
2    *
3    * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4    *
5    * ====================================================================
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * 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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   * ====================================================================
18   */
19  package org.jclouds.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.Set;
26  
27  import javax.annotation.Resource;
28  import javax.inject.Inject;
29  
30  import org.jclouds.aws.util.AWSUtils;
31  import org.jclouds.date.DateService;
32  import org.jclouds.ec2.domain.Attachment;
33  import org.jclouds.ec2.domain.BlockDevice;
34  import org.jclouds.ec2.domain.InstanceState;
35  import org.jclouds.ec2.domain.Reservation;
36  import org.jclouds.ec2.domain.RootDeviceType;
37  import org.jclouds.ec2.domain.RunningInstance;
38  import org.jclouds.ec2.domain.RunningInstance.Builder;
39  import org.jclouds.http.functions.ParseSax.HandlerForGeneratedRequestWithResult;
40  import org.jclouds.location.Region;
41  import org.jclouds.logging.Logger;
42  import org.xml.sax.Attributes;
43  
44  import com.google.common.collect.Sets;
45  import com.google.inject.Provider;
46  
47  /**
48   * 
49   * @author Adrian Cole
50   */
51  public abstract class BaseReservationHandler<T> extends HandlerForGeneratedRequestWithResult<T> {
52  
53     @Resource
54     protected Logger logger = Logger.NULL;
55  
56     protected final DateService dateService;
57     protected final String defaultRegion;
58     protected final Provider<Builder> builderProvider;
59  
60     @Inject
61     public BaseReservationHandler(DateService dateService, @Region String defaultRegion,
62           Provider<RunningInstance.Builder> builderProvider) {
63        this.dateService = dateService;
64        this.defaultRegion = defaultRegion;
65        this.builderProvider = builderProvider;
66        this.builder = builderProvider.get();
67     }
68  
69     protected StringBuilder currentText = new StringBuilder();
70  
71     protected Builder builder;
72  
73     protected int itemDepth;
74     boolean inInstancesSet;
75     // attachments
76     private String volumeId;
77     private Attachment.Status attachmentStatus;
78     private Date attachTime;
79     private boolean deleteOnTermination;
80     private String deviceName;
81  
82     // reservation stuff
83     private Set<String> groupIds = Sets.newLinkedHashSet();
84     private String ownerId;
85     private String requesterId;
86     private String reservationId;
87  
88     private Set<RunningInstance> instances = Sets.newLinkedHashSet();
89  
90     public void startElement(String uri, String name, String qName, Attributes attrs) {
91        if (equalsOrSuffix(qName, "item")) {
92           itemDepth++;
93        } else if (equalsOrSuffix(qName, "instancesSet")) {
94           inInstancesSet = true;
95        }
96     }
97  
98     public void endElement(String uri, String name, String qName) {
99        if (equalsOrSuffix(qName, "item")) {
100          inItem();
101          itemDepth--;
102       } else if (equalsOrSuffix(qName, "instancesSet")) {
103          inInstancesSet = false;
104       } else if (equalsOrSuffix(qName, "groupId")) {
105          groupIds.add(currentOrNull(currentText));
106       } else if (equalsOrSuffix(qName, "ownerId")) {
107          ownerId = currentOrNull(currentText);
108       } else if (equalsOrSuffix(qName, "requesterId")) {
109          requesterId = currentOrNull(currentText);
110       } else if (equalsOrSuffix(qName, "reservationId")) {
111          reservationId = currentOrNull(currentText);
112       } else if (equalsOrSuffix(qName, "amiLaunchIndex")) {
113          builder.amiLaunchIndex(currentOrNull(currentText));
114       } else if (equalsOrSuffix(qName, "dnsName")) {
115          String dnsName = currentOrNull(currentText);
116          // Eucalyptus
117          if (!"0.0.0.0".equals(dnsName))
118             builder.dnsName(dnsName);
119       } else if (equalsOrSuffix(qName, "imageId")) {
120          builder.imageId(currentOrNull(currentText));
121       } else if (equalsOrSuffix(qName, "instanceId")) {
122          builder.instanceId(currentOrNull(currentText));
123       } else if (equalsOrSuffix(qName, "name")) {
124          builder.instanceState(InstanceState.fromValue(currentOrNull(currentText)));
125       } else if (equalsOrSuffix(qName, "instanceType")) {
126          builder.instanceType(currentOrNull(currentText));
127       } else if (equalsOrSuffix(qName, "ipAddress")) {
128          builder.ipAddress(currentOrNull(currentText));
129       } else if (equalsOrSuffix(qName, "kernelId")) {
130          builder.kernelId(currentOrNull(currentText));
131       } else if (equalsOrSuffix(qName, "keyName")) {
132          builder.keyName(currentOrNull(currentText));
133       } else if (equalsOrSuffix(qName, "launchTime")) {
134          builder.launchTime(parseDate());
135       } else if (equalsOrSuffix(qName, "availabilityZone")) {
136          builder.availabilityZone(currentOrNull(currentText));
137       } else if (equalsOrSuffix(qName, "virtualizationType")) {
138          builder.virtualizationType(currentOrNull(currentText));
139       } else if (equalsOrSuffix(qName, "platform")) {
140          builder.platform(currentOrNull(currentText));
141       } else if (equalsOrSuffix(qName, "privateDnsName")) {
142          String privateDnsName = currentOrNull(currentText);
143          // Eucalyptus
144          if (!"0.0.0.0".equals(privateDnsName))
145             builder.privateDnsName(privateDnsName);
146       } else if (equalsOrSuffix(qName, "privateIpAddress")) {
147          builder.privateIpAddress(currentOrNull(currentText));
148       } else if (equalsOrSuffix(qName, "ramdiskId")) {
149          builder.ramdiskId(currentOrNull(currentText));
150       } else if (equalsOrSuffix(qName, "reason")) {
151          builder.reason(currentOrNull(currentText));
152       } else if (equalsOrSuffix(qName, "rootDeviceType")) {
153          builder.rootDeviceType(RootDeviceType.fromValue(currentOrNull(currentText)));
154       } else if (equalsOrSuffix(qName, "rootDeviceName")) {
155          builder.rootDeviceName(currentOrNull(currentText));
156       } else if (equalsOrSuffix(qName, "deviceName")) {
157          deviceName = currentOrNull(currentText);
158       } else if (equalsOrSuffix(qName, "volumeId")) {
159          volumeId = currentOrNull(currentText);
160       } else if (equalsOrSuffix(qName, "status")) {
161          attachmentStatus = Attachment.Status.fromValue(currentText.toString().trim());
162       } else if (equalsOrSuffix(qName, "attachTime")) {
163          attachTime = dateService.iso8601DateParse(currentText.toString().trim());
164       } else if (equalsOrSuffix(qName, "deleteOnTermination")) {
165          deleteOnTermination = Boolean.parseBoolean(currentText.toString().trim());
166       } else if (equalsOrSuffix(qName, "ebs")) {
167          builder.device(deviceName, new BlockDevice(volumeId, attachmentStatus, attachTime, deleteOnTermination));
168          this.deviceName = null;
169          this.volumeId = null;
170          this.attachmentStatus = null;
171          this.attachTime = null;
172          this.deleteOnTermination = true;
173       }
174       currentText = new StringBuilder();
175    }
176 
177    protected Date parseDate() {
178       try {
179          return dateService.iso8601DateParse(currentOrNull(currentText));
180       } catch (RuntimeException e) {
181          // Eucalyptus
182          return dateService.iso8601SecondsDateParse(currentOrNull(currentText));
183       }
184    }
185 
186    protected void inItem() {
187       if (endOfInstanceItem()) {
188          refineBuilderBeforeAddingInstance();
189          instances.add(builder.build());
190          builder = builderProvider.get();
191       }
192    }
193 
194    protected void refineBuilderBeforeAddingInstance() {
195       String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
196 
197       // Eucalyptus
198       if (builder.getIpAddress() == null && builder.getDnsName() != null && builder.getDnsName().matches(".*[0-9]$")) {
199          builder.ipAddress(builder.getDnsName());
200          builder.dnsName(null);
201       }
202       if (builder.getPrivateIpAddress() == null && builder.getPrivateDnsName() != null
203             && builder.getPrivateDnsName().matches(".*[0-9]$")) {
204          builder.privateIpAddress(builder.getPrivateDnsName());
205          builder.privateDnsName(null);
206       }
207 
208       builder.region((region == null) ? defaultRegion : region);
209       builder.groupIds(groupIds);
210    }
211 
212    protected Builder builder() {
213       return builder;
214    }
215 
216    protected boolean endOfInstanceItem() {
217       return itemDepth <= 2 && inInstancesSet;
218    }
219 
220    public void characters(char ch[], int start, int length) {
221       currentText.append(ch, start, length);
222    }
223 
224    protected Reservation<? extends RunningInstance> newReservation() {
225       String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
226       if (region == null)
227          region = defaultRegion;
228       Reservation<? extends RunningInstance> info = new Reservation<RunningInstance>(region, groupIds, instances,
229             ownerId, requesterId, reservationId);
230       this.groupIds = Sets.newLinkedHashSet();
231       this.instances = Sets.newLinkedHashSet();
232       this.ownerId = null;
233       this.requesterId = null;
234       this.reservationId = null;
235       return info;
236    }
237 
238 }