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

com.maxmind.geoip2.DatabaseReader Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
package com.maxmind.geoip2;

import com.maxmind.db.*;
import com.maxmind.db.Reader.FileMode;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Modified and simplified for I2P
 *
 * 

* The class {@code DatabaseReader} provides a reader for the GeoIP2 database * format. *

*

Usage

*

* To use the database API, you must create a new {@code DatabaseReader} using * the {@code DatabaseReader.Builder}. You must provide the {@code Builder} * constructor either an {@code InputStream} or {@code File} for your GeoIP2 * database. You may also specify the {@code fileMode} and the {@code locales} * fallback order using the methods on the {@code Builder} object. After you * have created the {@code DatabaseReader}, you may then call the appropriate * method (e.g., {@code city}) for your database, passing it the IP address * you want to look up. *

*

* If the lookup succeeds, the method call will return a response class for * the GeoIP2 lookup. The class in turn contains multiple record classes, * each of which represents part of the data returned by the database. *

*

* We recommend reusing the {@code DatabaseReader} object rather than creating * a new one for each lookup. The creation of this object is relatively * expensive as it must read in metadata for the file. It is safe to share the * object across threads. *

*

Caching

*

* The database API supports pluggable caching (by default, no caching is * performed). A simple implementation is provided by * {@code com.maxmind.db.CHMCache}. Using this cache, lookup performance is * significantly improved at the cost of a small (~2MB) memory overhead. *

* * @since 0.9.38 */ public class DatabaseReader implements Closeable { private final Reader reader; private final List locales; private DatabaseReader(Builder builder) throws IOException { if (builder.stream != null) { this.reader = new Reader(builder.stream, builder.cache); } else if (builder.database != null) { this.reader = new Reader(builder.database, builder.mode, builder.cache); } else { // This should never happen. If it does, review the Builder class // constructors for errors. throw new IllegalArgumentException( "Unsupported Builder configuration: expected either File or URL"); } this.locales = builder.locales; } /** *

* Constructs a Builder for the {@code DatabaseReader}. The file passed to * it must be a valid GeoIP2 database file. *

*

* {@code Builder} creates instances of {@code DatabaseReader} * from values set by the methods. *

*

* Only the values set in the {@code Builder} constructor are required. *

*/ public static final class Builder { final File database; final InputStream stream; List locales = Collections.singletonList("en"); FileMode mode = FileMode.MEMORY_MAPPED; NodeCache cache = NoCache.getInstance(); /** * @param stream the stream containing the GeoIP2 database to use. */ public Builder(InputStream stream) { this.stream = stream; this.database = null; } /** * @param database the GeoIP2 database file to use. */ public Builder(File database) { this.database = database; this.stream = null; } /** * @param val List of locale codes to use in name property from most * preferred to least preferred. * @return Builder object */ public Builder locales(List val) { this.locales = val; return this; } /** * @param cache backing cache instance * @return Builder object */ public Builder withCache(NodeCache cache) { this.cache = cache; return this; } /** * @param val The file mode used to open the GeoIP2 database * @return Builder object * @throws java.lang.IllegalArgumentException if you initialized the Builder with a URL, which uses * {@link FileMode#MEMORY}, but you provided a different * FileMode to this method. */ public Builder fileMode(FileMode val) { if (this.stream != null && FileMode.MEMORY != val) { throw new IllegalArgumentException( "Only FileMode.MEMORY is supported when using an InputStream."); } this.mode = val; return this; } /** * @return an instance of {@code DatabaseReader} created from the * fields set on this builder. * @throws IOException if there is an error reading the database */ public DatabaseReader build() throws IOException { return new DatabaseReader(this); } } /** * Returns a map containing: * *
  • continent: Map containing: *
    • code: String *
    • names: Map of lang to translated name *
    • geoname_id: Long *
    *
    • country: Map containing: *
      • iso_code: String *
      • names: Map of lang to translated name *
      • geoname_id: Long *
      *
      • registered_country: Map containing: *
        • iso_code: String *
        • names: Map of lang to translated name *
        • geoname_id: Long *
        *
      * * @param ipAddress IPv4 or IPv6 address to lookup. * @return A Map with the data for the IP address * @throws IOException if there is an error opening or reading from the file. */ private Object get(InetAddress ipAddress, String type) throws IOException { String databaseType = this.getMetadata().getDatabaseType(); if (!databaseType.contains(type)) { String caller = Thread.currentThread().getStackTrace()[2] .getMethodName(); throw new UnsupportedOperationException( "Invalid attempt to open a " + databaseType + " database using the " + caller + " method"); } return reader.get(ipAddress); } /** *

      * Closes the database. *

      *

      * If you are using {@code FileMode.MEMORY_MAPPED}, this will * not unmap the underlying file due to a limitation in Java's * {@code MappedByteBuffer}. It will however set the reference to * the buffer to {@code null}, allowing the garbage collector to * collect it. *

      * * @throws IOException if an I/O error occurs. */ @Override public void close() throws IOException { this.reader.close(); } public String country(String ipAddress) throws IOException { InetAddress ia = InetAddress.getByName(ipAddress); Object o = get(ia, "Country"); if (!(o instanceof Map)) return null; Map m = (Map) o; o = m.get("country"); if (!(o instanceof Map)) return null; m = (Map) o; o = m.get("iso_code"); if (!(o instanceof String)) return null; return (String) o; } /** * I2P - * Write all IPv4 address ranges for the given country to out. * * @param country two-letter case-insensitive * @param out caller must close * @since 0.9.48 */ public void countryToIP(String country, Writer out) throws IOException { reader.countryToIP(country.toUpperCase(Locale.US), out); } /** * @return the metadata for the open MaxMind DB file. */ public Metadata getMetadata() { return this.reader.getMetadata(); } public static void main(String[] args) throws Exception { if (args.length != 2) { System.err.println("Usage: DatabaseReader geoip2-file.mmdb ip"); System.exit(1); } File f = new File(args[0]); Builder b = new Builder(f); b.withCache(new CHMCache(256)); DatabaseReader r = b.build(); System.out.println("Database Metadata: " + r.getMetadata()); String c = r.country(args[1]); System.out.println("IP: " + args[1] + " country: " + c); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy