All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.brooklyn.entity.dns.geoscaling;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.brooklyn.util.http.HttpTool;
import org.apache.brooklyn.util.text.Strings;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;

/**
 * For interacting with the www.geoscaling.com DNS service.
 * 
 * If you get the SSL error "peer not authenticated", then it means the required certificate is
 * not in your trust store. For example, see:
 * {@linkplain http://stackoverflow.com/questions/373295/digital-certificate-how-to-import-cer-file-in-to-truststore-file-using}. 
 * The chain of certificates (as of October 2014, found by viewing in Chrome) is:
 * 
    *
  1. AddTrust External CA root *
  2. COMODO RSA Certification Authority *
  3. COMODO RSA Domain Validation Secure Server CA *
  4. www.geoscaling.com *
*/ public class GeoscalingWebClient { public static final Logger log = LoggerFactory.getLogger(GeoscalingWebClient.class); public static final long PROVIDE_NETWORK_INFO = 1 << 0; public static final long PROVIDE_CITY_INFO = 1 << 1; public static final long PROVIDE_COUNTRY_INFO = 1 << 2; public static final long PROVIDE_EXTRA_INFO = 1 << 3; public static final long PROVIDE_UPTIME_INFO = 1 << 4; private static final String HOST ="www.geoscaling.com"; private static final String PATH ="dns2/index.php"; private HttpClient httpClient; private Tidy tidy; private List primaryDomains = null; public class Domain { public final int id; public final String name; private List smartSubdomains = null; public Domain(int id, String name) { this.id = id; this.name = name.toLowerCase(); } public List getSmartSubdomains() { if (smartSubdomains == null) smartSubdomains = GeoscalingWebClient.this.fetchSmartSubdomains(this); return smartSubdomains; } public SmartSubdomain getSmartSubdomain(String name) { name = name.toLowerCase(); for (SmartSubdomain s : getSmartSubdomains()) { if (s.name.equals(name)) return s; } return null; } /** e.g. editRecord("foo", "A", "1.2.3.4"), which assuming this domain is "bar.com", will create A record for foo.bar.com. *

* or editRecord("*.foo", "CNAME", "foo.bar.com") to map everything at *.foo.bar.com to foo.bar.com */ public void editRecord(String subdomainPart, String type, String content) { subdomainPart = Strings.removeFromEnd(subdomainPart, "."+name); editSubdomainRecord(id, subdomainPart, type, content); } public SmartSubdomain getSmartSubdomain(int id) { for (SmartSubdomain s : getSmartSubdomains()) { if (s.id == id) return s; } return null; } public void createSmartSubdomain(String name) { GeoscalingWebClient.this.createSmartSubdomain(id, name); smartSubdomains = fetchSmartSubdomains(this); } public void delete() { deletePrimaryDomain(id); primaryDomains = fetchPrimaryDomains(); } @Override public String toString() { return "Domain["+name+" ("+id+")]"; } @Override public int hashCode() { return id; } } public class SmartSubdomain { public final Domain parent; public final int id; public String name; public SmartSubdomain(Domain parent, int id, String name) { this.parent = parent; this.id = id; this.name = name.toLowerCase(); } public void configure(long flags, String phpScript) { configureSmartSubdomain(parent.id, id, name, flags, phpScript); } public void delete() { deleteSmartSubdomain(parent.id, id); parent.smartSubdomains = fetchSmartSubdomains(parent); } @Override public String toString() { return "SmartSubdomain["+name+" ("+id+")]"; } @Override public int hashCode() { return id; } } public GeoscalingWebClient() { this(HttpTool.httpClientBuilder().build()); } public GeoscalingWebClient(HttpClient httpClient) { this.httpClient = httpClient; this.tidy = new Tidy(); // Silently swallow all HTML errors/warnings. tidy.setErrout(new PrintWriter(new OutputStream() { @Override public void write(int b) throws IOException { } })); } public GeoscalingWebClient(String username, String password) { this(); login(username, password); } public void login(String username, String password) { try { String url = MessageFormat.format("https://{0}/{1}?module=auth", HOST, PATH); HttpPost request = new HttpPost(url); List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("username", username)); nameValuePairs.add(new BasicNameValuePair("password", password)); request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); sendRequest(request, true); } catch (Exception e) { throw new RuntimeException("Failed to log-in to GeoScaling service: "+e, e); } } public void logout() { try { String url = MessageFormat.format("https://{0}/{1}?module=auth&logout", HOST, PATH); sendRequest(new HttpGet(url), true); } catch (Exception e) { throw new RuntimeException("Failed to log-out of GeoScaling service: "+e, e); } } public List getPrimaryDomains() { if (primaryDomains == null) primaryDomains = fetchPrimaryDomains(); return primaryDomains; } public Domain getPrimaryDomain(String name) { name = name.toLowerCase(); for (Domain d : getPrimaryDomains()) { if (d.name.equals(name)) return d; } return null; } public Domain getPrimaryDomain(int id) { for (Domain d : getPrimaryDomains()) { if (d.id == id) return d; } return null; } public void createPrimaryDomain(String name) { try { name = name.toLowerCase(); String url = MessageFormat.format("https://{0}/{1}?module=domains", HOST, PATH); HttpPost request = new HttpPost(url); List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); nameValuePairs.add(new BasicNameValuePair("domain", FilenameUtils.removeExtension(name))); nameValuePairs.add(new BasicNameValuePair("tld", FilenameUtils.getExtension(name))); request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); sendRequest(request, true); } catch (Exception e) { throw new RuntimeException("Failed to create GeoScaling smart subdomain: "+e, e); } primaryDomains = fetchPrimaryDomains(); } private List fetchPrimaryDomains() { try { List domains = new LinkedList(); String url = MessageFormat.format("https://{0}/{1}?module=domains", HOST, PATH); HttpResponse response = sendRequest(new HttpGet(url), false); HttpEntity entity = response.getEntity(); if (entity != null) { Document document = tidy.parseDOM(entity.getContent(), null); NodeList links = document.getElementsByTagName("a"); for (int i = 0; i < links.getLength(); ++i) { Element link = (Element) links.item(i); String href = link.getAttribute("href"); Pattern p = Pattern.compile("module=domain.*&id=(\\d+)"); Matcher m = p.matcher(href); if (!m.find(0)) continue; int id = Integer.parseInt(m.group(1)); String name = getTextContent(link).trim(); if (name.length() == 0) continue; domains.add(new Domain(id, name)); } EntityUtils.consume(entity); } return domains; } catch (Exception e) { throw new RuntimeException("Failed to retrieve GeoScaling subdomains: "+e, e); } } private void deletePrimaryDomain(int primaryDomainId) { try { String url = MessageFormat.format( "https://{0}/{1}?module=domain&id={2,number,#}&delete=1", HOST, PATH, primaryDomainId); sendRequest(new HttpGet(url), true); } catch (Exception e) { throw new RuntimeException("Failed to delete GeoScaling primary domain: "+e, e); } } private List fetchSmartSubdomains(Domain parent) { try { List subdomains = new LinkedList(); String url = MessageFormat.format( "https://{0}/{1}?module=smart_subdomains&id={2,number,#}", HOST, PATH, parent.id); HttpResponse response = sendRequest(new HttpGet(url), false); HttpEntity entity = response.getEntity(); if (entity != null) { Document document = tidy.parseDOM(entity.getContent(), null); NodeList links = document.getElementsByTagName("a"); for (int i = 0; i < links.getLength(); ++i) { Element link = (Element) links.item(i); String href = link.getAttribute("href"); Pattern p = Pattern.compile("module=smart_subdomain.*&subdomain_id=(\\d+)"); Matcher m = p.matcher(href); if (!m.find(0)) continue; int subdomainId = Integer.parseInt(m.group(1)); String name = getTextContent(link); if (name.trim().length() == 0) continue; name = name.substring(0, name.length() - parent.name.length() - 1); subdomains.add(new SmartSubdomain(parent, subdomainId, name)); } EntityUtils.consume(entity); } return subdomains; } catch (Exception e) { throw new RuntimeException("Failed to retrieve GeoScaling smart subdomains: "+e, e); } } private void createSmartSubdomain(int primaryDomainId, String smartSubdomainName) { try { smartSubdomainName = smartSubdomainName.toLowerCase(); String url = MessageFormat.format( "https://{0}/{1}?module=smart_subdomains&id={2,number,#}", HOST, PATH, primaryDomainId); HttpPost request = new HttpPost(url); List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); nameValuePairs.add(new BasicNameValuePair("smart_subdomain_name", smartSubdomainName)); request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); sendRequest(request, true); } catch (Exception e) { throw new RuntimeException("Failed to create GeoScaling smart subdomain: "+e, e); } } private void deleteSmartSubdomain(int primaryDomainId, int smartSubdomainId) { try { String url = MessageFormat.format( "https://{0}/{1}?module=smart_subdomains&id={2,number,#}&delete={3,number,#}", HOST, PATH, primaryDomainId, smartSubdomainId); sendRequest(new HttpGet(url), true); } catch (Exception e) { throw new RuntimeException("Failed to delete GeoScaling smart subdomain: "+e, e); } } private void configureSmartSubdomain(int primaryDomainId, int smartSubdomainId, String smartSubdomainName, long flags, String phpScript) { try { smartSubdomainName = smartSubdomainName.toLowerCase(); String url = MessageFormat.format( "https://{0}/{1}?module=smart_subdomain&id={2,number,#}&subdomain_id={3,number,#}", HOST, PATH, primaryDomainId, smartSubdomainId); HttpPost request = new HttpPost(url); List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("MAX_FILE_SIZE", "65536")); nameValuePairs.add(new BasicNameValuePair("name", smartSubdomainName)); if ((flags & PROVIDE_NETWORK_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_as_info", "on")); if ((flags & PROVIDE_CITY_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_city_info", "on")); if ((flags & PROVIDE_COUNTRY_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_country_info", "on")); if ((flags & PROVIDE_EXTRA_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_extra_info", "on")); if ((flags & PROVIDE_UPTIME_INFO) != 0) nameValuePairs.add(new BasicNameValuePair("share_uptime_info", "on")); nameValuePairs.add(new BasicNameValuePair("code", phpScript)); request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); sendRequest(request, true); } catch (Exception e) { throw new RuntimeException("Failed to update GeoScaling smart subdomain: "+e, e); } } private void editSubdomainRecord(int primaryDomainId, String record, String type, String content) { try { String url = MessageFormat.format( "https://{0}/{1}?", HOST, "dns2/ajax/add_record.php"); HttpPost request = new HttpPost(url); List nameValuePairs = new ArrayList(2); nameValuePairs.add(new BasicNameValuePair("id", ""+primaryDomainId)); nameValuePairs.add(new BasicNameValuePair("name", record)); nameValuePairs.add(new BasicNameValuePair("type", type)); nameValuePairs.add(new BasicNameValuePair("content", content)); nameValuePairs.add(new BasicNameValuePair("ttl", "300")); nameValuePairs.add(new BasicNameValuePair("prio", "0")); request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); sendRequest(request, true); } catch (Exception e) { throw new RuntimeException("Failed to update GeoScaling smart subdomain: "+e, e); } } protected HttpResponse sendRequest(HttpUriRequest request, boolean consumeResponse) throws ClientProtocolException, IOException { if (log.isDebugEnabled()) log.debug("Geoscaling request: "+ request.getURI()+ (request instanceof HttpPost ? " "+((HttpPost)request).getEntity() : "")); HttpResponse response = httpClient.execute(request); if (log.isDebugEnabled()) log.debug("Geoscaling response: "+response); if (consumeResponse) EntityUtils.consume(response.getEntity()); return response; } private static String getTextContent(Node n) { StringBuffer sb = new StringBuffer(); NodeList childNodes = n.getChildNodes(); for (int i = 0; i < childNodes.getLength(); ++i) { Node child = childNodes.item(i); if (child.getNodeType() == Node.TEXT_NODE) sb.append(child.getNodeValue()); else sb.append(getTextContent(child)); } return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy