/******************************************************************************* * Copyright (c) 2012, Directors of the Tyndale STEP Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * Neither the name of the Tyndale House, Cambridge (www.TyndaleHouse.com) * nor the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ package com.tyndalehouse.step.core.guice.providers; import static com.tyndalehouse.step.core.utils.StringUtils.commaSeparate; import static com.tyndalehouse.step.core.utils.StringUtils.isNotBlank; import static java.net.Proxy.NO_PROXY; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; import com.tyndalehouse.step.core.data.StepHttpSwordInstaller; import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.install.sword.HttpSwordInstaller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.tyndalehouse.step.core.exceptions.StepInternalException; /** * Provides a set of installers for installing Bibles, modules, etc e.g. from Crosswire * * @author chrisburrell * */ @Singleton public class DefaultInstallersProvider implements Provider<List<Installer>> { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultInstallersProvider.class); private static final String CROSSWIRE_ROOT = "http://crosswire.org/"; private volatile List<Installer> installers; private final Properties stepProperties; private final String proxyHost; private final String proxyPort; /** * @param stepProperties the properties for the whole STEP application * @param proxyHost the host name of the proxy * @param proxyPort the port of a proxy to go through */ @Inject public DefaultInstallersProvider(@Named("StepCoreProperties") final Properties stepProperties, @Named("app.proxy.host") final String proxyHost, @Named("app.proxy.port") final String proxyPort) { this.stepProperties = stepProperties; this.proxyHost = proxyHost; this.proxyPort = proxyPort; } /** * Initialises the installers from the passed in properties * * @return a list of installers that have been created */ private synchronized List<Installer> initialiseInstallers() { final List<Installer> newInstallers = new ArrayList<Installer>(); final Set<Entry<Object, Object>> entrySet = this.stepProperties.entrySet(); for (final Entry<Object, Object> entry : entrySet) { if (entry.getKey() instanceof String && ((String) entry.getKey()).startsWith("installer")) { // add to list final String[] split = commaSeparate(entry.getValue().toString()); final Installer i = getInstaller(split); if (i != null) { newInstallers.add(i); } } } return newInstallers; } /** * @param splitParts the various parts of the installer property * @return an installer, properly configured with any relevant proxy */ protected synchronized Installer getInstaller(final String[] splitParts) { if (splitParts.length < 4) { return null; } final StepHttpSwordInstaller installer = new StepHttpSwordInstaller(); installer.setInstallerName(splitParts[0]); installer.setHost(splitParts[1]); installer.setPackageDirectory(splitParts[2]); installer.setCatalogDirectory(splitParts[3]); if (isNotBlank(this.proxyHost) || isNotBlank(this.proxyPort)) { setManualProxy(installer); } else { setAvailableSystemProxy(installer); } return installer; } /** * Sets the proxy manually * * @param installer the installer that requires configuration */ private void setManualProxy(final HttpSwordInstaller installer) { // set the host if (isNotBlank(this.proxyHost)) { installer.setProxyHost(this.proxyHost); } // set the port if (isNotBlank(this.proxyPort)) { try { final Integer p = Integer.parseInt(this.proxyPort); installer.setProxyPort(p.intValue()); } catch (final NumberFormatException e) { throw new StepInternalException("Unable to parse port number " + this.proxyPort, e); } } } /** * if available, then sets the default proxy and port * * @param installer an installer to be configured with a potential proxy */ private void setAvailableSystemProxy(final HttpSwordInstaller installer) { System.setProperty("java.net.useSystemProxies", "true"); List<Proxy> l = null; try { l = ProxySelector.getDefault().select(new URI(CROSSWIRE_ROOT)); } catch (final URISyntaxException e) { LOGGER.warn("Unable to parse URL for Crosswire: [{}]", CROSSWIRE_ROOT); LOGGER.trace("Root exception was", e); return; } if (l != null && !l.isEmpty()) { final Proxy p = l.get(0); if (NO_PROXY.equals(p)) { return; } final InetSocketAddress address = (InetSocketAddress) p.address(); if (address == null) { return; } // finally set to what the address actually says installer.setProxyHost(address.getHostName()); installer.setProxyPort(address.getPort()); } } @Override public List<Installer> get() { if (this.installers == null) { synchronized (this) { if (this.installers == null) { this.installers = initialiseInstallers(); } } } return this.installers; } }