/******************************************************************************* * Copyright 2011 André Rouél * * Licensed 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 net.sf.jacclog.geoip.internal; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.zip.GZIPInputStream; import net.sf.jacclog.csv.CommaSeparatedValuesReader; import net.sf.jacclog.service.repository.CountryRepositoryService; import net.sf.jacclog.service.repository.domain.Country; import net.sf.jacclog.service.repository.domain.NonPersistentCountry; import net.sf.jacclog.util.net.IpAddressTranslator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CountryGeolocationReader { public static class Mapper { private static final Logger LOG = LoggerFactory.getLogger(Mapper.class); public static Country mapFieldsToCountry(final List<String> fields) { if (fields == null) { throw new IllegalArgumentException("Argument 'fields' can not be null."); } if (fields.size() != 6) { throw new IllegalArgumentException("There are not enough fields in the given list."); } validateIpAddressAndIpNumber(fields.get(0), fields.get(2)); validateIpAddressAndIpNumber(fields.get(1), fields.get(3)); final Country country = new NonPersistentCountry(); country.setBeginIpAddress(fields.get(0)); country.setBeginIpAddressAsNumber(Long.parseLong(fields.get(2))); country.setCode(fields.get(4)); country.setEndIpAddress(fields.get(1)); country.setEndIpAddressAsNumber(Long.parseLong(fields.get(3))); country.setName(fields.get(5)); return country; } /** * Checks the equality of the calculated numeric IP address (of the given textual) with the given numeric * address. * * @param ipAddress * Textual representation of an IP address * @param ipNumber * Numerical representation of an IP address as <code>String</code> (will be parsed as * <code>long</code>) * @return <code>true</code> if equals, otherwise <code>false</code> */ private static boolean validateIpAddressAndIpNumber(final String ipAddress, final String ipNumber) { if (ipAddress == null) { throw new IllegalArgumentException("Argument 'ipAddress' can not be null."); } if (ipNumber == null) { throw new IllegalArgumentException("Argument 'ipNumber' can not be null."); } final long startIpNum = IpAddressTranslator.toLong(ipAddress); final boolean equals = Long.parseLong(ipNumber) == startIpNum; if (!equals) { LOG.warn("Calculated IP number '" + startIpNum + "' does not equals with read one '" + ipNumber + "'."); } return equals; } } /** * Potential number of countries to be read */ private static final int DEFAULT_SIZE = 150000; private static final Logger LOG = LoggerFactory.getLogger(CountryGeolocationReader.class); public CountryGeolocationReader(final GZIPInputStream gzipInputStream, final CountryRepositoryService<Country> service) throws IOException { this(new InputStreamReader(gzipInputStream), service); } public CountryGeolocationReader(final InputStream inputStream, final CountryRepositoryService<Country> service) throws IOException { this(new InputStreamReader(inputStream), service); } public CountryGeolocationReader(final Reader reader, final CountryRepositoryService<Country> service) throws IOException { if (reader == null) { throw new IllegalArgumentException("Argument 'reader' can not be null."); } if (service == null) { throw new IllegalArgumentException("Argument 'service' can not be null."); } final List<List<String>> lines = CommaSeparatedValuesReader.read(reader); final List<Country> countries = new ArrayList<Country>(DEFAULT_SIZE); for (final List<String> fields : lines) { countries.add(Mapper.mapFieldsToCountry(fields)); } service.create(countries); LOG.info("... read " + countries.size() + " countries"); } }