/*
* Copyright 2015 Philip Cronje
*
* 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.za.slyfox.dyn53.extip;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Provider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLConnection;
import java.util.Objects;
import java.util.function.Consumer;
/**
* Implements the task logic to obtain the external IP address of the network the application is running in.
*/
final class ExternalIpDiscoveryCommand implements Runnable {
private final Provider<Consumer<InetAddress>> consumerProvider;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final InetAddressPredicate updatePredicate;
/**
* Injects dependencies into the instance.
*
* @param consumerProvider a provider used to obtain a {@link Consumer} that will process the discovered IP address
* @param updatePredicate a predicate used to evaluate whether the command will invoke the consumer or not
* @throws NullPointerException if {@code consumerProvider} is {@code null}
*/
@Inject
ExternalIpDiscoveryCommand(Provider<Consumer<InetAddress>> consumerProvider, InetAddressPredicate updatePredicate) {
this.consumerProvider = Objects.requireNonNull(consumerProvider);
this.updatePredicate = Objects.requireNonNull(updatePredicate);
}
/**
* Requests the external IP from the ipify web service, and passes it on to the {@link Consumer} obtained from the
* {@link Provider} this object was initialized with.
*/
@Override
public void run() {
try {
logger.info("Requesting external IP from https://api.ipify.org/");
final InetAddress address;
try {
URLConnection connection = URI.create("https://api.ipify.org").toURL().openConnection();
final String ip;
try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
ip = reader.readLine();
}
address = InetAddress.getByName(ip);
} catch(IOException e) {
logger.warn("Failed to retrieve external IP from remote service", e);
return;
} catch(RuntimeException e) {
logger.error("Failed to retrieve external IP from remote service", e);
return;
}
try {
if(updatePredicate.test(address)) consumerProvider.get().accept(address);
} catch(RuntimeException e) {
logger.error("Failed to process external IP ({}) received from remote service", address, e);
}
} catch(Error e) {
logger.error("JVM encountered error while executing command, aborting application execution", e);
System.exit(1);
}
}
}