Project: AdServing
/**
 * Mad-Advertisement 
 * Copyright (C) 2011 Thorsten Marx <thmarx@gmx.net> 
 * 
 * This program is free software: you can redistribute it and/or modify it under 
 * the terms of the GNU General Public License as published by the Free Software 
 * Foundation, either version 3 of the License, or (at your option) any later 
 * version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
 * details. 
 * 
 * You should have received a copy of the GNU General Public License along with 
 * this program. If not, see <http://www.gnu.org/licenses/>. 
 */
package net.mad.ads.services.geo; 
 
 
 
import java.io.BufferedReader; 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Scanner; 
 
import net.mad.ads.services.geo.helper.ValidateIP; 
 
import org.hsqldb.jdbc.pool.JDBCPooledDataSource; 
 
import au.com.bytecode.opencsv.CSVReader; 
import biz.source_code.miniConnectionPoolManager.MiniConnectionPoolManager; 
 
/**
 * Reader zum einlesen 
 *  
 * "ip_start";"country_code";"country_name";"region_code";"region_name";"city"; 
 * "zipcode";"latitude";"longitude";"metrocode" 
 *  
 * @author tmarx 
 *  
 */
 
public class MaxmindIpLocationDB implements IPLocationDB { 
  
  
 private static final String jdbc_class_hsql = "org.hsqldb.jdbc.JDBCDriver"
 private static final String jdbc_url_hsql = "jdbc:hsqldb:"
  
// private Connection conn = null; 
  
 private String db; 
  
 private MiniConnectionPoolManager poolMgr = null
  
 public MaxmindIpLocationDB() { 
 
  
 /* (non-Javadoc)
  * @see de.marx.services.geo.IPLocationDB#open() 
  */
 
 @Override 
 public void open(String db) throws ClassNotFoundException, SQLException { 
  this.db = db; 
   
  Class.forName(jdbc_class_hsql); 
 
  JDBCPooledDataSource datasource = new JDBCPooledDataSource(); 
//  datasource.setUrl(jdbc_url_hsql + db); 
  datasource.setUser("SA"); 
  datasource.setPassword("SA"); 
  datasource.setDatabase(jdbc_url_hsql + db); 
 
  poolMgr = new MiniConnectionPoolManager(datasource, 50); 
 
 
 /* (non-Javadoc)
  * @see de.marx.services.geo.IPLocationDB#open(biz.source_code.miniConnectionPoolManager.MiniConnectionPoolManager) 
  */
 
 @Override 
 public void open(MiniConnectionPoolManager poolmgr) { 
  this.poolMgr = poolmgr; 
 
 
 /* (non-Javadoc)
  * @see de.marx.services.geo.IPLocationDB#close() 
  */
 
 @Override 
 public void close() throws SQLException { 
  poolMgr.dispose(); 
 
 
 /* (non-Javadoc)
  * @see de.marx.services.geo.IPLocationDB#importCountry(java.lang.String) 
  */
 
 @Override 
 public void importCountry(String path) { 
  Connection conn = null
  try { 
   if (!path.endsWith("/")) { 
    path += "/"
   
   conn = poolMgr.getConnection(); 
   conn.setAutoCommit(true); 
   Statement stat = conn.createStatement(); 
    
    
   StringBuilder builder = new StringBuilder(); 
   builder.append("CREATE CACHED TABLE IP_COUNTRY ("); 
      builder.append("ipFROM BIGINT NOT NULL ,"); 
      builder.append("ipTO BIGINT NOT NULL ,"); 
      builder.append("country VARCHAR(2),"); 
      builder.append("region VARCHAR(128),"); 
      builder.append("city VARCHAR(128),"); 
      builder.append("postalcode VARCHAR(10),"); 
      builder.append("latitude DOUBLE,"); 
      builder.append("longitude DOUBLE,"); 
      builder.append("PRIMARY KEY(ipFROM, ipTO)"); 
      builder.append(")"); 
       
      stat.execute(builder.toString()); 
   stat.close(); 
       
   builder = new StringBuilder(); 
   builder.append("INSERT INTO IP_COUNTRY ("); 
   builder.append("ipFROM,"); 
      builder.append("ipTO,"); 
      builder.append("country,"); 
      builder.append("region,"); 
      builder.append("city,"); 
      builder.append("postalcode,"); 
      builder.append("latitude,"); 
      builder.append("longitude) "); 
      builder.append(" VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); 
    
//   PreparedStatement ps = conn.prepareStatement("INSERT INTO IP_COUNTRY (ip_from, ip_to, country_code, region_name, city_name, city_zip, latitude, longitude, timezone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); 
      PreparedStatement ps = conn.prepareStatement(builder.toString()); 
    
   BufferedReader br = new BufferedReader(new FileReader(path + "GeoLiteCity-Blocks.csv")); 
   CSVReader reader = new CSVReader(br, ',', '\"', 2); 
    
//   Scanner scanner = new Scanner(new FileReader(filename)); 
//   boolean firstLine = true; 
   int count = 0
   String [] values; 
   Map<String, Map<String,String>> locations = getLocations(path); 
   while ((values = reader.readNext()) != null) { 
    String ipfrom = values[0]; 
    String ipto = values[1]; 
    String locid = values[2]; 
     
    Map<String,String> location = locations.get(locid); 
     
    ps.setLong(1, Long.valueOf(ipfrom)); 
    ps.setLong(2, Long.valueOf(ipto)); 
    ps.setString(3, location.get("country")); 
    ps.setString(4, location.get("region")); 
    ps.setString(5, location.get("city")); 
    ps.setString(6, location.get("postalcode")); 
    ps.setDouble(7, location.get("latitude").equals("") ? 0 : Double.valueOf(location.get("latitude"))); 
    ps.setDouble(8, location.get("longitude").equals("") ? 0 : Double.valueOf(location.get("longitude"))); 
 
    ps.execute(); 
    count++; 
   
   System.out.println(count + " Einträge importiert"); 
    
   ps.close(); 
  catch (Exception e) { 
   e.printStackTrace(); 
  finally { 
   try { 
    conn.close(); 
   catch (Exception e) { 
    e.printStackTrace(); 
   
  
 
  
 /* (non-Javadoc)
  * @see de.marx.services.geo.IPLocationDB#searchIp(java.lang.String) 
  */
 
 @Override 
 public Location searchIp(String ip) { 
  Connection conn = null
  Statement stat = null
  try { 
   conn = poolMgr.getConnection(); 
   stat = conn.createStatement(); 
          
         long inetAton = ValidateIP.ip2long(ip); 
          
         String query = "SELECT * FROM IP_COUNTRY WHERE ipFROM <= " + inetAton + " ORDER BY ipFROM DESC LIMIT 1"
          
//         String query = "SELECT * FROM IP_COUNTRY WHERE " + inetAton + " BETWEEN ipFROM AND ipTO"; 
          
         ResultSet result = stat.executeQuery(query); 
          
         while (result.next()) { 
          String c = result.getString("country"); 
          String rn = result.getString("region"); 
          String cn = result.getString("city"); 
           
          String lat = result.getString("latitude"); 
          String lng = result.getString("longitude"); 
           
          Location loc = new Location(c, rn, cn, lat, lng); 
          return loc; 
         } 
          
         return Location.UNKNOWN; 
  catch (Exception e) { 
   e.printStackTrace(); 
  finally { 
   try { 
    conn.close(); 
    stat.close(); 
   catch (Exception e) { 
    e.printStackTrace(); 
   
  
   
  return null
 
  
 private Map<String, Map<String, String>> getLocations (String path) throws IOException { 
  if (!path.endsWith("/")) { 
   path += "/"
  
  String filename = path + "GeoLiteCity-Location.csv"
  Map<String, Map<String, String>> result = new HashMap<String, Map<String,String>>(); 
   
 
  BufferedReader br = new BufferedReader(new FileReader(filename)); 
  CSVReader reader = new CSVReader(br, ',', '\"', 2); 
  String [] values; 
  while ((values = reader.readNext()) != null) { 
    
   Map<String, String> loc = new HashMap<String, String>(); 
   loc.put("locid", values[0]); 
   loc.put("country", values[1]); 
   loc.put("region", values[2]); 
   loc.put("city", values[3]); 
   loc.put("postalcode", values[4]); 
   loc.put("latitude", values[5]); 
   loc.put("longitude", values[6]); 
    
   result.put(values[0], loc); 
  
   
  return result; 
 
  
 private String mtrim (String text) { 
  if (text.startsWith("\"")) { 
   text = text.substring(1); 
  
  if (text.endsWith("\"")) { 
   text = text.substring(0, text.length()-1); 
  
  return text; 
 
}