Java tutorial
/** * 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.metron.stellar.dsl.functions; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.net.InternetDomainName; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.util.SubnetUtils; import org.apache.metron.stellar.dsl.BaseStellarFunction; import org.apache.metron.stellar.dsl.Stellar; import java.net.MalformedURLException; import java.net.URL; import java.util.List; public class NetworkFunctions { @Stellar(name = "IN_SUBNET", description = "Returns true if an IP is within a subnet range.", params = { "ip - The IP address in string form", "cidr+ - One or more IP ranges specified in CIDR notation (for example 192.168.0.0/24)" }, returns = "True if the IP address is within at least one of the network ranges and false if otherwise") public static class InSubnet extends BaseStellarFunction { @Override public Object apply(List<Object> list) { if (list.size() < 2) { throw new IllegalStateException("IN_SUBNET expects at least two args: [ip, cidr1, cidr2, ...]" + " where cidr is the subnet mask in cidr form"); } String ip = (String) list.get(0); if (ip == null) { return false; } boolean inSubnet = false; for (int i = 1; i < list.size() && !inSubnet; ++i) { String cidr = (String) list.get(i); if (cidr == null) { continue; } inSubnet |= new SubnetUtils(cidr).getInfo().isInRange(ip); } return inSubnet; } } @Stellar(name = "REMOVE_SUBDOMAINS", namespace = "DOMAIN", description = "Removes the subdomains from a domain.", params = { "domain - Fully qualified domain name" }, returns = "The domain without the subdomains. " + "(for example, DOMAIN_REMOVE_SUBDOMAINS('mail.yahoo.com') yields 'yahoo.com')") public static class RemoveSubdomains extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { if (objects.isEmpty()) { return null; } Object dnObj = objects.get(0); InternetDomainName idn = toDomainName(dnObj); if (idn != null) { String dn = dnObj.toString(); String tld = extractTld(idn, dn); if (!StringUtils.isEmpty(dn)) { String suffix = safeSubstring(dn, 0, dn.length() - tld.length()); String hostnameWithoutTLD = safeSubstring(suffix, 0, suffix.length() - 1); if (hostnameWithoutTLD == null) { return dn; } String hostnameWithoutSubsAndTLD = Iterables.getLast(Splitter.on(".").split(hostnameWithoutTLD), null); if (hostnameWithoutSubsAndTLD == null) { return null; } return hostnameWithoutSubsAndTLD + "." + tld; } } return null; } } @Stellar(name = "REMOVE_TLD", namespace = "DOMAIN", description = "Removes the top level domain (TLD) suffix from a domain.", params = { "domain - Fully qualified domain name" }, returns = "The domain without the TLD. " + "(for example, DOMAIN_REMOVE_TLD('mail.yahoo.co.uk') yields 'mail.yahoo')") public static class RemoveTLD extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { Object dnObj = objects.get(0); InternetDomainName idn = toDomainName(dnObj); if (idn != null) { String dn = dnObj.toString(); String tld = extractTld(idn, dn); String suffix = safeSubstring(dn, 0, dn.length() - tld.length()); if (StringUtils.isEmpty(suffix)) { return suffix; } else { return suffix.substring(0, suffix.length() - 1); } } return null; } } @Stellar(name = "TO_TLD", namespace = "DOMAIN", description = "Extracts the top level domain from a domain", params = { "domain - Fully qualified domain name" }, returns = "The TLD of the domain. " + "(for example, DOMAIN_TO_TLD('mail.yahoo.co.uk') yields 'co.uk')") public static class ExtractTLD extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { Object dnObj = objects.get(0); InternetDomainName idn = toDomainName(dnObj); return extractTld(idn, dnObj + ""); } } @Stellar(name = "TO_PORT", namespace = "URL", description = "Extract the port from a URL. " + "If the port is not explicitly stated in the URL, then an implicit port is inferred based on the protocol.", params = { "url - URL in string form" }, returns = "The port used in the URL as an integer (for example, URL_TO_PORT('http://www.yahoo.com/foo') would yield 80)") public static class URLToPort extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { URL url = toUrl(objects.get(0)); if (url == null) { return null; } int port = url.getPort(); return port >= 0 ? port : url.getDefaultPort(); } } @Stellar(name = "TO_PATH", namespace = "URL", description = "Extract the path from a URL.", params = { "url - URL in String form" }, returns = "The path from the URL as a String. e.g. URL_TO_PATH('http://www.yahoo.com/foo') would yield 'foo'") public static class URLToPath extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { URL url = toUrl(objects.get(0)); return url == null ? null : url.getPath(); } } @Stellar(name = "TO_HOST", namespace = "URL", description = "Extract the hostname from a URL.", params = { "url - URL in String form" }, returns = "The hostname from the URL as a String. e.g. URL_TO_HOST('http://www.yahoo.com/foo') would yield 'www.yahoo.com'") public static class URLToHost extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { URL url = toUrl(objects.get(0)); return url == null ? null : url.getHost(); } } @Stellar(name = "TO_PROTOCOL", namespace = "URL", description = "Extract the protocol from a URL.", params = { "url - URL in String form" }, returns = "The protocol from the URL as a String. e.g. URL_TO_PROTOCOL('http://www.yahoo.com/foo') would yield 'http'") public static class URLToProtocol extends BaseStellarFunction { @Override public Object apply(List<Object> objects) { URL url = toUrl(objects.get(0)); return url == null ? null : url.getProtocol(); } } /** * Extract the TLD. If the domain is a normal domain, then we can handle the TLD via the InternetDomainName object. * If it is not, then we default to returning the last segment after the final '.' * @param idn * @param dn * @return The TLD of the domain */ private static String extractTld(InternetDomainName idn, String dn) { if (idn != null && idn.hasPublicSuffix()) { String ret = idn.publicSuffix().toString(); if (ret.startsWith("InternetDomainName")) { return Joiner.on(".").join(idn.publicSuffix().parts()); } else { return ret; } } else if (dn != null) { StringBuffer tld = new StringBuffer(""); for (int idx = dn.length() - 1; idx >= 0; idx--) { char c = dn.charAt(idx); if (c == '.') { break; } else { tld.append(dn.charAt(idx)); } } return tld.reverse().toString(); } else { return null; } } private static String safeSubstring(String val, int start, int end) { if (!StringUtils.isEmpty(val)) { return val.substring(start, end); } return null; } private static InternetDomainName toDomainName(Object dnObj) { if (dnObj != null) { if (dnObj instanceof String) { String dn = dnObj.toString(); try { return InternetDomainName.from(dn); } catch (IllegalArgumentException iae) { return null; } } else { throw new IllegalArgumentException(dnObj + " is not a string and therefore also not a domain."); } } return null; } private static URL toUrl(Object urlObj) { if (urlObj == null) { return null; } if (urlObj instanceof String) { String url = urlObj.toString(); try { return new URL(url); } catch (MalformedURLException e) { return null; } } else { throw new IllegalArgumentException(urlObj + " is not a string and therefore also not a URL."); } } }