Merge pull request #671 from aledsage/Fix-TemplateBuilder-javadoc

Fixes TemplateBuilder.from(...) javadoc
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/ComputePoolReference.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/ComputePoolReference.java
new file mode 100644
index 0000000..72211f6
--- /dev/null
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/ComputePoolReference.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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 org.jclouds.trmk.vcloud_0_8.domain;
+
+import static com.google.common.base.Objects.equal;
+
+import java.net.URI;
+
+import com.google.common.base.Objects;
+
+/**
+ * @author Adrian Cole
+ */
+public class ComputePoolReference implements Comparable<ComputePoolReference> {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromComputePoolReference(this);
+   }
+
+   public static class Builder {
+      private URI href;
+      private String name;
+
+      public Builder href(URI href) {
+         this.href = href;
+         return this;
+      }
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public ComputePoolReference build() {
+         return new ComputePoolReference(href, name);
+      }
+
+      public Builder fromComputePoolReference(ComputePoolReference in) {
+         return href(in.getHref()).name(in.getName());
+      }
+
+   }
+
+   private final URI href;
+   private final String name;
+
+   public ComputePoolReference(URI href, String name) {
+      this.href = href;
+      this.name = name;
+   }
+
+   public int compareTo(ComputePoolReference that) {
+      return (this == that) ? 0 : getHref().compareTo(that.getHref());
+   }
+
+   public URI getHref() {
+      return href;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+      ComputePoolReference that = ComputePoolReference.class.cast(o);
+      return equal(this.href, that.href) && equal(this.name, that.name);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(href, name);
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper("").add("href", href).add("name", name).toString();
+   }
+}
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/NetworkAdapter.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/NetworkAdapter.java
index c65718a..1508fb9 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/NetworkAdapter.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/NetworkAdapter.java
@@ -18,10 +18,52 @@
  */
 package org.jclouds.trmk.vcloud_0_8.domain;
 
+import static com.google.common.base.Objects.equal;
+
+import com.google.common.base.Objects;
+
 /**
  * @author Seshu Pasam
  */
 public class NetworkAdapter implements Comparable<NetworkAdapter> {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromNetworkAdapter(this);
+   }
+
+   public static class Builder {
+      private String macAddress;
+      private String name;
+      private Subnet subnet;
+
+      public Builder macAddress(String macAddress) {
+         this.macAddress = macAddress;
+         return this;
+      }
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public Builder subnet(Subnet subnet) {
+         this.subnet = subnet;
+         return this;
+      }
+
+      public NetworkAdapter build() {
+         return new NetworkAdapter(macAddress, name, subnet);
+      }
+
+      public Builder fromNetworkAdapter(NetworkAdapter in) {
+         return macAddress(in.getMacAddress()).name(in.getName()).subnet(in.getSubnet());
+      }
+
+   }
+
    private final String macAddress;
    private final String name;
    private final Subnet subnet;
@@ -49,44 +91,23 @@
    }
 
    @Override
-   public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((macAddress== null) ? 0 : macAddress.hashCode());
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      result = prime * result + ((subnet == null) ? 0 : subnet.hashCode());
-      return result;
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+      NetworkAdapter that = NetworkAdapter.class.cast(o);
+      return equal(this.macAddress, that.macAddress) && equal(this.name, that.name) && equal(this.subnet, that.subnet);
    }
 
    @Override
-   public boolean equals(Object obj) {
-      if (this == obj)
-         return true;
-      if (obj == null)
-         return false;
-      if (getClass() != obj.getClass())
-         return false;
-      NetworkAdapter other = (NetworkAdapter) obj;
-      if (macAddress == null) {
-         if (other.macAddress != null)
-            return false;
-      } else if (!macAddress.equals(other.macAddress))
-         return false;
-      if (name == null) {
-         if (other.name != null)
-            return false;
-      } else if (!name.equals(other.name))
-         return false;
-      if (subnet == null) {
-         if (other.subnet != null)
-            return false;
-      } else if (!subnet.equals(other.subnet))
-         return false;
-      return true;
+   public int hashCode() {
+      return Objects.hashCode(macAddress, name, subnet);
    }
 
    @Override
    public String toString() {
-      return "[MAC address=" + macAddress + ", name=" + name + ", subnet=" + subnet + "]";
+      return Objects.toStringHelper("").add("macAddress", macAddress).add("name", name).add("subnet", subnet)
+               .toString();
    }
 }
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/Subnet.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/Subnet.java
index fd34859..8bb466c 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/Subnet.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/Subnet.java
@@ -18,12 +18,48 @@
  */
 package org.jclouds.trmk.vcloud_0_8.domain;
 
+import static com.google.common.base.Objects.equal;
+
 import java.net.URI;
 
+import com.google.common.base.Objects;
+
 /**
  * @author Seshu Pasam
  */
 public class Subnet implements Comparable<Subnet> {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromSubnet(this);
+   }
+
+   public static class Builder {
+      private URI href;
+      private String name;
+
+      public Builder href(URI href) {
+         this.href = href;
+         return this;
+      }
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public Subnet build() {
+         return new Subnet(href, name);
+      }
+
+      public Builder fromSubnet(Subnet in) {
+         return href(in.getHref()).name(in.getName());
+      }
+
+   }
+
    private final URI href;
    private final String name;
 
@@ -45,38 +81,22 @@
    }
 
    @Override
-   public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((href == null) ? 0 : href.hashCode());
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      return result;
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+      Subnet that = Subnet.class.cast(o);
+      return equal(this.href, that.href) && equal(this.name, that.name);
    }
 
    @Override
-   public boolean equals(Object obj) {
-      if (this == obj)
-         return true;
-      if (obj == null)
-         return false;
-      if (getClass() != obj.getClass())
-         return false;
-      Subnet other = (Subnet) obj;
-      if (href == null) {
-         if (other.href != null)
-            return false;
-      } else if (!href.equals(other.href))
-         return false;
-      if (name == null) {
-         if (other.name != null)
-            return false;
-      } else if (!name.equals(other.name))
-         return false;
-      return true;
+   public int hashCode() {
+      return Objects.hashCode(href, name);
    }
 
    @Override
    public String toString() {
-      return "[href=" + href + ", name=" + name + "]";
+      return Objects.toStringHelper("").add("href", href).add("name", name).toString();
    }
 }
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/VAppExtendedInfo.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/VAppExtendedInfo.java
index 945433e..8e03862 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/VAppExtendedInfo.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/domain/VAppExtendedInfo.java
@@ -2,7 +2,7 @@
  * Licensed to jclouds, Inc. (jclouds) under one or more
  * contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
+ * regarding copyright ownershhref.  jclouds 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
@@ -18,28 +18,103 @@
  */
 package org.jclouds.trmk.vcloud_0_8.domain;
 
+import static com.google.common.base.Objects.equal;
+
 import java.net.URI;
 import java.util.List;
 
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
 /**
- * @author Seshu Pasam
+ * @author Seshu Pasam, Adrian Cole
  */
 public class VAppExtendedInfo implements Comparable<VAppExtendedInfo> {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromVAppExtendedInfo(this);
+   }
+
+   public static class Builder {
+      private String id;
+      private URI href;
+      private String name;
+      private String longName;
+      private List<String> tags = Lists.newArrayList();
+      private List<NetworkAdapter> networkAdapters = Lists.newArrayList();
+      private ComputePoolReference computePoolReference;
+
+      public Builder id(String id) {
+         this.id = id;
+         return this;
+      }
+
+      public Builder href(URI href) {
+         this.href = href;
+         return this;
+      }
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public Builder longName(String longName) {
+         this.longName = longName;
+         return this;
+      }
+
+      public Builder tags(List<String> tags) {
+         this.tags = tags;
+         return this;
+      }
+
+      public Builder networkAdapters(List<NetworkAdapter> networkAdapters) {
+         this.networkAdapters = networkAdapters;
+         return this;
+      }
+
+      public Builder networkAdapter(NetworkAdapter networkAdapter) {
+         this.networkAdapters.add(networkAdapter);
+         return this;
+      }
+
+      public Builder computePoolReference(ComputePoolReference computePoolReference) {
+         this.computePoolReference = computePoolReference;
+         return this;
+      }
+
+      public VAppExtendedInfo build() {
+         return new VAppExtendedInfo(id, href, name, tags, longName, networkAdapters, computePoolReference);
+      }
+
+      public Builder fromVAppExtendedInfo(VAppExtendedInfo in) {
+         return id(in.getId()).href(in.getHref()).name(in.getName()).longName(in.getLongName()).tags(in.getTags())
+                  .networkAdapters(in.getNetworkAdapters()).computePoolReference(in.getComputePoolReference());
+      }
+
+   }
+
    private final String id;
    private final URI href;
    private final String name;
-   private final List<String> tags;
    private final String longName;
+   private final List<String> tags;
    private final List<NetworkAdapter> networkAdapters;
+   private final ComputePoolReference computePoolReference;
 
    public VAppExtendedInfo(String id, URI href, String name, List<String> tags, String longName,
-           List<NetworkAdapter> networkAdapters) {
+            List<NetworkAdapter> networkAdapters, ComputePoolReference computePoolReference) {
       this.id = id;
       this.href = href;
       this.name = name;
       this.tags = tags;
       this.longName = longName;
       this.networkAdapters = networkAdapters;
+      this.computePoolReference = computePoolReference;
    }
 
    public int compareTo(VAppExtendedInfo that) {
@@ -58,71 +133,44 @@
       return name;
    }
 
-   public List<String> getTags() {
-      return tags;
-   }
-
    public String getLongName() {
       return longName;
    }
 
+   public List<String> getTags() {
+      return tags;
+   }
+
    public List<NetworkAdapter> getNetworkAdapters() {
       return networkAdapters;
    }
 
-   @Override
-   public int hashCode() {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((href == null) ? 0 : href.hashCode());
-      result = prime * result + ((id == null) ? 0 : id.hashCode());
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      result = prime * result + ((longName == null) ? 0 : longName.hashCode());
-      result = prime * result + ((tags == null) ? 0 : tags.hashCode());
-      result = prime * result + ((networkAdapters == null) ? 0 : networkAdapters.hashCode());
-      return result;
+   public ComputePoolReference getComputePoolReference() {
+      return computePoolReference;
    }
 
    @Override
-   public boolean equals(Object obj) {
-      if (this == obj)
+   public boolean equals(Object o) {
+      if (this == o)
          return true;
-      if (obj == null)
+      if (o == null || getClass() != o.getClass())
          return false;
-      if (getClass() != obj.getClass())
-         return false;
-      VAppExtendedInfo other = (VAppExtendedInfo) obj;
-      if (href == null) {
-         if (other.href != null)
-            return false;
-      } else if (!href.equals(other.href))
-         return false;
-      if (id == null) {
-         if (other.id != null)
-            return false;
-      } else if (!id.equals(other.id))
-         return false;
-      if (name == null) {
-         if (other.name != null)
-            return false;
-      } else if (!name.equals(other.name))
-         return false;
-      if (tags == null) {
-         if (other.tags != null)
-            return false;
-      } else if (!tags.equals(other.tags))
-         return false;
-      if (networkAdapters == null) {
-         if (other.networkAdapters != null)
-            return false;
-      } else if (!networkAdapters.equals(other.networkAdapters))
-         return false;
-      return true;
+      VAppExtendedInfo that = VAppExtendedInfo.class.cast(o);
+      return equal(this.id, that.id) && equal(this.href, that.href) && equal(this.name, that.name)
+               && equal(this.longName, that.longName) && equal(this.tags, that.tags)
+               && equal(this.networkAdapters, that.networkAdapters)
+               && equal(this.computePoolReference, that.computePoolReference);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id, href, name, longName, tags, networkAdapters, computePoolReference);
    }
 
    @Override
    public String toString() {
-      return "[href=" + href + ", id=" + id + ", name=" + name + ", long name=" + longName
-          + ", tags=" + tags.toString() + ", network adapters=" + networkAdapters.toString() + "]";
+      return Objects.toStringHelper("").add("id", id).add("href", href).add("name", name).add("longName", longName)
+               .add("tags", tags).add("networkAdapters", networkAdapters).add("computePoolReference",
+                        computePoolReference).toString();
    }
 }
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandler.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandler.java
index 60ed24e..fad34bb 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandler.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandler.java
@@ -18,53 +18,39 @@
  */
 package org.jclouds.trmk.vcloud_0_8.xml;
 
-import java.net.URI;
-import java.util.Arrays;
-import java.util.List;
+import static org.jclouds.util.SaxUtils.currentOrNull;
 
-import javax.annotation.Resource;
+import java.net.URI;
 
 import org.jclouds.http.functions.ParseSax.HandlerWithResult;
-import org.jclouds.logging.Logger;
+import org.jclouds.trmk.vcloud_0_8.domain.ComputePoolReference;
 import org.jclouds.trmk.vcloud_0_8.domain.NetworkAdapter;
 import org.jclouds.trmk.vcloud_0_8.domain.Subnet;
 import org.jclouds.trmk.vcloud_0_8.domain.VAppExtendedInfo;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
-import com.google.common.collect.Lists;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
 
 /**
- * @author Seshu Pasam
+ * @author Seshu Pasam, Adrian Cole
  */
 public class VAppExtendedInfoHandler extends HandlerWithResult<VAppExtendedInfo> {
 
-   @Resource
-   protected Logger logger = Logger.NULL;
    private StringBuilder currentText = new StringBuilder();
 
-   private String id;
-   private URI href;
-   private String name;
-   private String longName;
-   private List<String> tags;
-   private List<NetworkAdapter> networkAdapters = Lists.newArrayList();
+   private VAppExtendedInfo.Builder builder = VAppExtendedInfo.builder();
+   private NetworkAdapter.Builder adapterBuilder = NetworkAdapter.builder();
+   private Subnet.Builder subnetBuilder = Subnet.builder();
+   private ComputePoolReference.Builder poolBuilder = ComputePoolReference.builder();
    private boolean inAdapters;
-   private String macAddress;
-   private String adapterName;
    private boolean inSubnet;
-   private Subnet subnet;
-   private URI subnetLocation;
-   private String subnetName;
-
-   protected String currentOrNull() {
-      String returnVal = currentText.toString().trim();
-      return returnVal.equals("") ? null : returnVal;
-   }
+   private boolean inComputePool;
 
    @Override
    public VAppExtendedInfo getResult() {
-      return new VAppExtendedInfo(id, href, name, tags, longName, networkAdapters);
+      return builder.build();
    }
 
    @Override
@@ -73,47 +59,55 @@
          inAdapters = true;
       } else if (qName.equals("Subnet")) {
          inSubnet = true;
+      } else if (qName.equals("ComputePoolReference")) {
+         inComputePool = true;
       }
    }
 
    public void endElement(String uri, String name, String qName) {
-      String current = currentOrNull();
+      String current = currentOrNull(currentText);
       if (current != null) {
          if (qName.equals("Id")) {
-            this.id = current;
+            builder.id(current);
          } else if (qName.equals("Tags")) {
-            this.tags = Arrays.asList(current.split(","));
+            builder.tags(ImmutableList.copyOf(Splitter.on(',').split(current)));
          } else if (qName.equals("LongName")) {
-            this.longName = current;
+            builder.longName(current);
          } else if (qName.equals("Href")) {
+            URI href = URI.create(current);
             if (inSubnet) {
-               this.subnetLocation = URI.create(current);
+               subnetBuilder.href(href);
+            } else if (inComputePool) {
+               poolBuilder.href(href);
             } else {
-               this.href = URI.create(current);
+               builder.href(href);
             }
          } else if (qName.equals("Name")) {
             if (inSubnet) {
-               this.subnetName = current;
+               subnetBuilder.name(current);
             } else if (inAdapters) {
-               this.adapterName = current;
+               adapterBuilder.name(current);
+            } else if (inComputePool) {
+               poolBuilder.name(current);
             } else {
-               this.name = current;
+               builder.name(current);
             }
-         } else if (qName.equals("NetworkAdapters")) {
-             inAdapters = false;
-         } else if (qName.equals("NetworkAdapter")) {
-             networkAdapters.add(new NetworkAdapter(macAddress, adapterName, subnet));
-             macAddress = null;
-             adapterName = null;
-             subnet = null;
          } else if (qName.equals("MacAddress")) {
-             macAddress = current;
-         } else if (qName.equals("Subnet")) {
-             subnet = new Subnet(subnetLocation, subnetName);
-             subnetLocation = null;
-             subnetName = null;
-             inSubnet = false;
+            adapterBuilder.macAddress(current);
          }
+      } else if (qName.equals("NetworkAdapters")) {
+         inAdapters = false;
+      } else if (qName.equals("NetworkAdapter")) {
+         builder.networkAdapter(adapterBuilder.build());
+         adapterBuilder = NetworkAdapter.builder();
+      } else if (qName.equals("Subnet")) {
+         adapterBuilder.subnet(subnetBuilder.build());
+         subnetBuilder = Subnet.builder();
+         inSubnet = false;
+      } else if (qName.equals("ComputePoolReference")) {
+         builder.computePoolReference(poolBuilder.build());
+         poolBuilder = ComputePoolReference.builder();
+         inComputePool = false;
       }
       currentText = new StringBuilder();
    }
diff --git a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/compute/strategy/PopulateDefaultLoginCredentialsForVAppTemplateTest.java b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/compute/strategy/PopulateDefaultLoginCredentialsForVAppTemplateTest.java
index deed367..0c411d3 100644
--- a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/compute/strategy/PopulateDefaultLoginCredentialsForVAppTemplateTest.java
+++ b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/compute/strategy/PopulateDefaultLoginCredentialsForVAppTemplateTest.java
@@ -51,7 +51,7 @@
       replay(template);
       ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
                null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
-      Credentials creds = converter.execute(template);
+      Credentials creds = converter.apply(template);
       assertEquals(creds.identity, "vcloud");
       assertEquals(creds.credential, "$Ep455l0ud!2");
       verify(template);
@@ -66,7 +66,7 @@
       replay(template);
       ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
                null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
-      Credentials creds = converter.execute(template);
+      Credentials creds = converter.apply(template);
       assertEquals(creds.identity, "ecloud");
       assertEquals(creds.credential, "$Ep455l0ud!2");
       verify(template);
@@ -81,7 +81,7 @@
       replay(template);
       ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
                null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
-      Credentials creds = converter.execute(template);
+      Credentials creds = converter.apply(template);
       assertEquals(creds.identity, "vpncubed");
       assertEquals(creds.credential, "vpncubed");
       verify(template);
@@ -96,7 +96,7 @@
       replay(template);
       ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
                null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
-      Credentials creds = converter.execute(template);
+      Credentials creds = converter.apply(template);
       assertEquals(creds.identity, "ecloud");
       assertEquals(creds.credential, "TmrkCl0ud1s#1!");
       verify(template);
@@ -111,7 +111,7 @@
       replay(template);
       ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
                null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
-      Credentials creds = converter.execute(template);
+      Credentials creds = converter.apply(template);
       assertEquals(creds.identity, "Administrator");
       assertEquals(creds.credential, null);
       verify(template);
diff --git a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandlerTest.java b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandlerTest.java
new file mode 100644
index 0000000..51b0990
--- /dev/null
+++ b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/xml/VAppExtendedInfoHandlerTest.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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 org.jclouds.trmk.vcloud_0_8.xml;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.jclouds.trmk.vcloud_0_8.domain.ComputePoolReference;
+import org.jclouds.trmk.vcloud_0_8.domain.NetworkAdapter;
+import org.jclouds.trmk.vcloud_0_8.domain.Subnet;
+import org.jclouds.trmk.vcloud_0_8.domain.VAppExtendedInfo;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code VAppExtendedInfoHandler}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "VAppExtendedInfoHandlerTest")
+public class VAppExtendedInfoHandlerTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/vapp-ext.xml");
+
+      VAppExtendedInfo result = factory.create(injector.getInstance(VAppExtendedInfoHandler.class)).parse(is);
+      assertEquals(
+               result,
+               VAppExtendedInfo
+                        .builder()
+                        .id("392992")
+                        .href(
+                                 URI
+                                          .create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/vapp/392992"))
+                        .name("instance01")
+                        .networkAdapter(
+                                 NetworkAdapter
+                                          .builder()
+                                          .macAddress("00:50:56:95:12:96")
+                                          .name("Network adapter 1")
+                                          .subnet(
+                                                   Subnet
+                                                            .builder()
+                                                            .href(
+                                                                     URI
+                                                                              .create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/network/43781"))
+                                                            .name("10.122.213.192/27").build()).build())
+                        .computePoolReference(
+                                 ComputePoolReference
+                                          .builder()
+                                          .href(
+                                                   URI
+                                                            .create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/computePool/692"))
+                                          .name(
+
+                                          "Resource Pool 692").build()).build());
+
+   }
+}
\ No newline at end of file
diff --git a/common/trmk/src/test/resources/vapp-ext.xml b/common/trmk/src/test/resources/vapp-ext.xml
new file mode 100644
index 0000000..6739670
--- /dev/null
+++ b/common/trmk/src/test/resources/vapp-ext.xml
@@ -0,0 +1,21 @@
+<VApp xmlns="urn:tmrk:eCloudExtensions-2.8" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+    <Id>392992</Id>
+    <Href>https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/vapp/392992</Href>
+    <Name>instance01</Name>
+    <Tags></Tags>
+    <LongName></LongName>
+    <NetworkAdapters>
+        <NetworkAdapter>
+            <MacAddress>00:50:56:95:12:96</MacAddress>
+            <Name>Network adapter 1</Name>
+            <Subnet>
+                <Href>https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/network/43781</Href>
+                <Name>10.122.213.192/27</Name>
+            </Subnet>
+        </NetworkAdapter>
+    </NetworkAdapters>
+    <ComputePoolReference>
+        <Href>https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.8/extensions/computePool/692</Href>
+        <Name>Resource Pool 692</Name>
+    </ComputePoolReference>
+</VApp>
\ No newline at end of file
diff --git a/compute/src/main/java/org/jclouds/compute/domain/ExecResponse.java b/compute/src/main/java/org/jclouds/compute/domain/ExecResponse.java
index 595d4d3..99ec1ce 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/ExecResponse.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/ExecResponse.java
@@ -46,6 +46,8 @@
    }
 
    /**
+    * <h4>will be removed in jclouds 1.6.0</h4> <br/>
+    * 
     * @see #getExitStatus
     */
    @Deprecated
diff --git a/compute/src/main/java/org/jclouds/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java b/compute/src/main/java/org/jclouds/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
index 7549cf5..ad5a371 100644
--- a/compute/src/main/java/org/jclouds/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
+++ b/compute/src/main/java/org/jclouds/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
@@ -19,7 +19,6 @@
 package org.jclouds.compute.strategy;
 
 import org.jclouds.compute.strategy.impl.ReturnCredentialsBoundToImage;
-import org.jclouds.domain.Credentials;
 import org.jclouds.domain.LoginCredentials;
 
 import com.google.common.base.Function;
@@ -32,21 +31,6 @@
 public interface PopulateDefaultLoginCredentialsForImageStrategy extends Function<Object, LoginCredentials> {
 
    /**
-    * <h4>will be removed in jclouds 1.4.0</h4> <br/>
-    * 
-    * Processes the resource to determine credentials.
-    * 
-    * @param resourceToAuthenticate
-    *           this can be any resource, such as an image, running server
-    *           instance or other. It's the responsibility of an implementation
-    *           to apply the cloud-specific logic.
-    * @return credentials object. Note: the key may not be set, but the identity
-    *         must be set
-    */
-   @Deprecated
-   Credentials execute(Object resourceToAuthenticate);
-   
-   /**
     * Processes the cloud-specific resources to determine the login credentials.
     * 
     * @param image
diff --git a/compute/src/main/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImage.java b/compute/src/main/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImage.java
index 2bc3c15..2e51b9b 100644
--- a/compute/src/main/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImage.java
+++ b/compute/src/main/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImage.java
@@ -67,9 +67,4 @@
          return LoginCredentials.builder().user("root").build();
       }
    }
-
-   @Override
-   public Credentials execute(Object resourceToAuthenticate) {
-      return apply(resourceToAuthenticate);
-   }
 }
diff --git a/compute/src/test/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImageTest.java b/compute/src/test/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImageTest.java
index 58df466..12302fd 100644
--- a/compute/src/test/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImageTest.java
+++ b/compute/src/test/java/org/jclouds/compute/strategy/impl/ReturnCredentialsBoundToImageTest.java
@@ -46,7 +46,7 @@
 
       LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
       assertEquals(new ReturnCredentialsBoundToImage(creds, ImmutableMap.<String, Credentials> of(), ImmutableMap
-               .<OsFamily, LoginCredentials> of()).execute(image), creds);
+               .<OsFamily, LoginCredentials> of()).apply(image), creds);
 
       verify(image);
 
@@ -59,7 +59,7 @@
 
       LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
       assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of("image#1", creds),
-               ImmutableMap.<OsFamily, LoginCredentials> of()).execute(image), creds);
+               ImmutableMap.<OsFamily, LoginCredentials> of()).apply(image), creds);
 
       verify(image);
 
@@ -74,7 +74,7 @@
 
       Credentials creds = new Credentials("Administrator", null);
       assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of(), ImmutableMap.of(
-               OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build())).execute(image), creds);
+               OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build())).apply(image), creds);
 
       verify(image);
 
@@ -89,7 +89,7 @@
 
       Credentials creds = new Credentials("root", null);
       assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of(), ImmutableMap
-               .<OsFamily, LoginCredentials> of()).execute(image), creds);
+               .<OsFamily, LoginCredentials> of()).apply(image), creds);
 
       verify(image);
 
diff --git a/core/pom.xml b/core/pom.xml
index 138edaa..0bed6e7 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -41,6 +41,7 @@
     <properties>
         <jclouds.osgi.import>*</jclouds.osgi.import>
         <jclouds.osgi.export>org.jclouds*;version=${project.version};-noimport:=true</jclouds.osgi.export>
+        <jclouds.osgi.activator>org.jclouds.osgi.Activator</jclouds.osgi.activator>
     </properties>
 
     <dependencies>
@@ -106,6 +107,12 @@
             <artifactId>guava</artifactId>
             <version>12.0</version>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>4.2.0</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/core/src/main/java/org/jclouds/View.java b/core/src/main/java/org/jclouds/View.java
index e61a51a..0a6f18d 100644
--- a/core/src/main/java/org/jclouds/View.java
+++ b/core/src/main/java/org/jclouds/View.java
@@ -46,6 +46,10 @@
     * context. If the backend context is not assignable from the supplied type,
     * an {@link IllegalArgumentException} is thrown.
     * 
+    * ex.
+    * <pre>
+    * RestContext<NovaClient, NovaAsyncClient> backendApi = computeContext.unwrap(NovaApiMetadata.CONTEXT_TOKEN);
+    * </pre>
     * @param type
     *           the type of the context to be returned. The backend context must
     *           be assignable from this type.
diff --git a/core/src/main/java/org/jclouds/osgi/Activator.java b/core/src/main/java/org/jclouds/osgi/Activator.java
new file mode 100644
index 0000000..64de199
--- /dev/null
+++ b/core/src/main/java/org/jclouds/osgi/Activator.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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 org.jclouds.osgi;
+
+import org.jclouds.providers.ProviderRegistry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+  ProviderBundleListener bundleListener = new ProviderBundleListener();
+
+  /**
+   * Called when this bundle is started so the Framework can perform the
+   * bundle-specific activities necessary to start this bundle. This method
+   * can be used to register services or to allocate any resources that this
+   * bundle needs.
+   * <p/>
+   * <p/>
+   * This method must complete and return to its caller in a timely manner.
+   *
+   * @param context The execution context of the bundle being started.
+   * @throws Exception If this method throws an exception, this
+   *                   bundle is marked as stopped and the Framework will remove this
+   *                   bundle's listeners, unregister all services registered by this
+   *                   bundle, and release all services used by this bundle.
+   */
+  @Override
+  public void start(BundleContext context) throws Exception {
+    context.addBundleListener(bundleListener);
+  }
+
+  /**
+   * Called when this bundle is stopped so the Framework can perform the
+   * bundle-specific activities necessary to stop the bundle. In general, this
+   * method should undo the work that the <code>BundleActivator.start</code>
+   * method started. There should be no active threads that were started by
+   * this bundle when this bundle returns. A stopped bundle must not call any
+   * Framework objects.
+   * <p/>
+   * <p/>
+   * This method must complete and return to its caller in a timely manner.
+   *
+   * @param context The execution context of the bundle being stopped.
+   * @throws Exception If this method throws an exception, the
+   *                   bundle is still marked as stopped, and the Framework will remove
+   *                   the bundle's listeners, unregister all services registered by the
+   *                   bundle, and release all services used by the bundle.
+   */
+  @Override
+  public void stop(BundleContext context) throws Exception {
+    context.removeBundleListener(bundleListener);
+    ProviderRegistry.clear();
+  }
+}
diff --git a/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java b/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java
new file mode 100644
index 0000000..01d3a26
--- /dev/null
+++ b/core/src/main/java/org/jclouds/osgi/ProviderBundleListener.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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 org.jclouds.osgi;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.ProviderRegistry;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link BundleListener} that listens for {@link BundleEvent} and searches for {@link org.jclouds.providers.ProviderMetadata} in newly
+ * installed Bundles. This is used as a workaround for OSGi environments where the ServiceLoader cannot cross bundle
+ * boundaries.
+ */
+public class ProviderBundleListener implements BundleListener {
+
+  private Map<Long, ProviderMetadata> bundleMetadataMap = new HashMap<Long, ProviderMetadata>();
+
+  @Override
+  public void bundleChanged(BundleEvent event) {
+    ProviderMetadata metadata;
+    switch (event.getType()) {
+      case BundleEvent.STARTED:
+        metadata = getProviderMetadata(event.getBundle());
+        if (metadata != null) {
+          ProviderRegistry.registerProvider(metadata);
+          bundleMetadataMap.put(event.getBundle().getBundleId(), metadata);
+        }
+        break;
+      case BundleEvent.STOPPING:
+      case BundleEvent.STOPPED:
+        metadata = bundleMetadataMap.get(event.getBundle().getBundleId());
+        if (metadata != null) {
+          ProviderRegistry.uRegisterProvider(metadata);
+        }
+        break;
+    }
+  }
+
+  /**
+   * Creates an instance of {@link ProviderMetadata} from the {@link Bundle}.
+   *
+   * @param bundle
+   * @return
+   */
+  public ProviderMetadata getProviderMetadata(Bundle bundle) {
+    ProviderMetadata metadata = null;
+    String className = getProviderMetadataClassName(bundle);
+    if (className != null && !className.isEmpty()) {
+      try {
+        Class<? extends ProviderMetadata> provideClass = bundle.loadClass(className);
+        metadata = provideClass.newInstance();
+      } catch (ClassNotFoundException e) {
+        // ignore
+      } catch (InstantiationException e) {
+        // ignore
+      } catch (IllegalAccessException e) {
+        // ignore
+      }
+    }
+    return metadata;
+  }
+
+  /**
+   * Retrieves the {@link ProviderMetadata} class name for the bundle if it exists.
+   *
+   * @param bundle
+   * @return
+   */
+  public String getProviderMetadataClassName(Bundle bundle) {
+    URL resource = bundle.getEntry("/META-INF/services/org.jclouds.providers.ProviderMetadata");
+    InputStream is = null;
+    InputStreamReader reader = null;
+    BufferedReader bufferedReader = null;
+    StringBuilder sb = new StringBuilder();
+
+    try {
+      is = resource.openStream();
+      reader = new InputStreamReader(is, "UTF-8");
+      bufferedReader = new BufferedReader(reader);
+      String line;
+      while ((line = bufferedReader.readLine()) != null) {
+        sb.append(line).append("\n");
+      }
+    } catch (Throwable e) {
+    } finally {
+      try {
+        if (reader != null)
+          reader.close();
+      } catch (Throwable e) {
+      }
+      try {
+        if (bufferedReader != null)
+          bufferedReader.close();
+      } catch (Throwable e) {
+      }
+      try {
+        is.close();
+      } catch (Throwable e) {
+      }
+
+    }
+    return sb.toString().trim();
+  }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/providers/ProviderRegistry.java b/core/src/main/java/org/jclouds/providers/ProviderRegistry.java
new file mode 100644
index 0000000..ef96bf3
--- /dev/null
+++ b/core/src/main/java/org/jclouds/providers/ProviderRegistry.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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 org.jclouds.providers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A registry for holding {@link org.jclouds.providers.ProviderMetadata}.
+ */
+public class ProviderRegistry {
+
+  private static final Set<ProviderMetadata> providers = new HashSet<ProviderMetadata>();
+
+  public static void registerProvider(ProviderMetadata provider) {
+    providers.add(provider);
+  }
+
+  public static void uRegisterProvider(ProviderMetadata provider) {
+    providers.remove(provider);
+  }
+
+  public static Iterable<ProviderMetadata> fromRegistry() {
+    return Iterable.class.cast(providers);
+  }
+
+  public static void clear() {
+    providers.clear();
+  }
+}
diff --git a/core/src/main/java/org/jclouds/providers/Providers.java b/core/src/main/java/org/jclouds/providers/Providers.java
index da69a11..e57fb19 100644
--- a/core/src/main/java/org/jclouds/providers/Providers.java
+++ b/core/src/main/java/org/jclouds/providers/Providers.java
@@ -24,6 +24,7 @@
 import java.util.NoSuchElementException;
 import java.util.ServiceLoader;
 
+import com.google.common.collect.Iterables;
 import org.jclouds.Context;
 import org.jclouds.View;
 import org.jclouds.apis.ApiMetadata;
@@ -82,7 +83,7 @@
     * @return all available providers
     */
    public static Iterable<ProviderMetadata> all() {
-      return fromServiceLoader();
+     return Iterables.concat(fromServiceLoader(), ProviderRegistry.fromRegistry());
    }
 
    /**
diff --git a/project/pom.xml b/project/pom.xml
index 787c34b..d978027 100644
--- a/project/pom.xml
+++ b/project/pom.xml
@@ -560,6 +560,7 @@
                 <configuration>
                     <obrRepository>NONE</obrRepository>
                     <instructions>
+                        <Bundle-Activator>${jclouds.osgi.activator}</Bundle-Activator>
                         <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                         <Export-Package>${jclouds.osgi.export}</Export-Package>
                         <Import-Package>${jclouds.osgi.import}</Import-Package>
diff --git a/providers/cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/CloudServersUKProviderMetadata.java b/providers/cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/CloudServersUKProviderMetadata.java
index fcfb0f0..54e9294 100644
--- a/providers/cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/CloudServersUKProviderMetadata.java
+++ b/providers/cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/CloudServersUKProviderMetadata.java
@@ -65,6 +65,7 @@
          id("cloudservers-uk")
          .name("Rackspace Cloud Servers UK")
          .apiMetadata(new CloudServersApiMetadata())
+         .endpoint("https://lon.auth.api.rackspacecloud.com")
          .homepage(URI.create("http://www.rackspace.co.uk/cloud-hosting/cloud-products/cloud-servers"))
          .console(URI.create("https://lon.manage.rackspacecloud.com"))
          .linkedServices("cloudloadbalancers-uk", "cloudservers-uk", "cloudfiles-uk")