diff options
author | Sebastien Vincent <seb@jitsi.org> | 2011-12-19 10:08:07 +0000 |
---|---|---|
committer | Sebastien Vincent <seb@jitsi.org> | 2011-12-19 10:08:07 +0000 |
commit | 2bcf9fe2dedac5eb1f8aa2149fcbcf31d97b25cb (patch) | |
tree | ea4a424322830972ca12c18b727c1f50cad9079b /src/net/java | |
parent | b48863e19bcbb5c655389f9a90fe1de5f1da70a1 (diff) | |
download | jitsi-2bcf9fe2dedac5eb1f8aa2149fcbcf31d97b25cb.zip jitsi-2bcf9fe2dedac5eb1f8aa2149fcbcf31d97b25cb.tar.gz jitsi-2bcf9fe2dedac5eb1f8aa2149fcbcf31d97b25cb.tar.bz2 |
Refactor provisioning.
Diffstat (limited to 'src/net/java')
6 files changed, 836 insertions, 607 deletions
diff --git a/src/net/java/sip/communicator/plugin/provisioning/ProvisioningActivator.java b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningActivator.java index 6736fa7..b5aac39 100644 --- a/src/net/java/sip/communicator/plugin/provisioning/ProvisioningActivator.java +++ b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningActivator.java @@ -6,23 +6,16 @@ */ package net.java.sip.communicator.plugin.provisioning; -import java.awt.*; -import java.io.*; -import java.net.*; import java.util.*; -import java.util.List; //disambiguation - -import javax.swing.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.credentialsstorage.*; import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.httputil.*; import net.java.sip.communicator.service.netaddr.*; import net.java.sip.communicator.service.provdisc.*; +import net.java.sip.communicator.service.provisioning.*; import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; -import net.java.sip.communicator.util.swing.*; import org.osgi.framework.*; @@ -33,7 +26,7 @@ import org.osgi.framework.*; */ public class ProvisioningActivator implements BundleActivator -{ +{ /** * Logger of this class */ @@ -46,54 +39,6 @@ public class ProvisioningActivator private static BundleContext bundleContext = null; /** - * Name of the provisioning URL in the configuration service. - */ - private static final String PROPERTY_PROVISIONING_URL - = "net.java.sip.communicator.plugin.provisioning.URL"; - - /** - * Name of the provisioning username in the configuration service - * authentication). - */ - static final String PROPERTY_PROVISIONING_USERNAME - = "net.java.sip.communicator.plugin.provisioning.auth.USERNAME"; - - /** - * Name of the provisioning password in the configuration service (HTTP - * authentication). - */ - static final String PROPERTY_PROVISIONING_PASSWORD - = "net.java.sip.communicator.plugin.provisioning.auth"; - - /** - * Name of the property that contains the provisioning method (i.e. DHCP, - * DNS, manual, ...). - */ - private static final String PROVISIONING_METHOD_PROP - = "net.java.sip.communicator.plugin.provisioning.METHOD"; - - /** - * Name of the property that contains enforce prefix list (separated by - * pipe) for the provisioning. The retrieved configuration properties will - * be checked against these prefixes to avoid having incorrect content in - * the configuration file (such as HTML content resulting of HTTP error). - */ - private static final String PROVISIONING_ALLOW_PREFIX_PROP - = "provisioning.ALLOW_PREFIX"; - - /** - * Name of the enforce prefix property. - */ - private static final String PROVISIONING_ENFORCE_PREFIX_PROP - = "provisioning.ENFORCE_PREFIX"; - - /** - * Name of the UUID property. - */ - public static final String PROVISIONING_UUID_PROP - = "net.java.sip.communicator.UUID"; - - /** * A reference to the ConfigurationService implementation instance that * is currently registered with the bundle context. */ @@ -120,11 +65,11 @@ public class ProvisioningActivator * The resource service. */ private static ResourceManagementService resourceService; - + /** - * List of allowed configuration prefixes. + * Provisioning service. */ - private List<String> allowedPrefixes = new ArrayList<String>(); + private static ProvisioningServiceImpl provisioningService = null; /** * Starts this bundle @@ -134,21 +79,13 @@ public class ProvisioningActivator */ public void start(BundleContext bundleContext) throws Exception { - String url = null; - if (logger.isDebugEnabled()) logger.debug("Provisioning discovery [STARTED]"); ProvisioningActivator.bundleContext = bundleContext; - - String uuid = (String)getConfigurationService().getProperty( - PROVISIONING_UUID_PROP); - - if(uuid == null || uuid.equals("")) - { - uuid = UUID.randomUUID().toString(); - getConfigurationService().setProperty(PROVISIONING_UUID_PROP, uuid); - } + String url = null; + + provisioningService = new ProvisioningServiceImpl(); Dictionary<String, String> properties = new Hashtable<String, String>(); properties.put( ConfigurationForm.FORM_TYPE, @@ -164,7 +101,7 @@ public class ProvisioningActivator 2000, true), properties); - String method = getProvisioningMethod(); + String method = provisioningService.getProvisioningMethod(); if(method == null || method.equals("NONE")) { @@ -193,28 +130,11 @@ public class ProvisioningActivator } } } - - if(url == null) - { - /* try to see if provisioning URL is stored in properties */ - url = getProvisioningUri(); - } - - if(url != null) - { - File file = retrieveConfigurationFile(url); - - if(file != null) - { - /* store the provisioning URL in local configuration in case - * the provisioning discovery failed (DHCP/DNS unavailable, ...) - */ - getConfigurationService().setProperty( - PROPERTY_PROVISIONING_URL, url); - - updateConfiguration(file); - } - } + + provisioningService.start(url); + + bundleContext.registerService( + ProvisioningService.class.getName(), provisioningService, null); if (logger.isDebugEnabled()) logger.debug("Provisioning discovery [REGISTERED]"); @@ -235,73 +155,6 @@ public class ProvisioningActivator } /** - * Indicates if the provisioning has been enabled. - * - * @return <tt>true</tt> if the provisioning is enabled, <tt>false</tt> - - * otherwise - */ - public static String getProvisioningMethod() - { - String provMethod - = getConfigurationService().getString(PROVISIONING_METHOD_PROP); - - if (provMethod == null || provMethod.length() <= 0) - { - provMethod = getResourceService().getSettingsString( - "plugin.provisioning.DEFAULT_PROVISIONING_METHOD"); - - if (provMethod != null && provMethod.length() > 0) - setProvisioningMethod(provMethod); - } - - return provMethod; - } - - /** - * Enables the provisioning with the given method. If the provisioningMethod - * is null disables the provisioning. - * - * @param provisioningMethod the provisioning method - */ - public static void setProvisioningMethod(String provisioningMethod) - { - getConfigurationService().setProperty( - PROVISIONING_METHOD_PROP, provisioningMethod); - } - - /** - * Returns the provisioning URI. - * - * @return the provisioning URI - */ - public static String getProvisioningUri() - { - String provUri - = getConfigurationService().getString(PROPERTY_PROVISIONING_URL); - - if (provUri == null || provUri.length() <= 0) - { - provUri = getResourceService().getSettingsString( - "plugin.provisioning.DEFAULT_PROVISIONING_URI"); - - if (provUri != null && provUri.length() > 0) - setProvisioningUri(provUri); - } - return provUri; - } - - /** - * Sets the provisioning URI. - * - * @param uri the provisioning URI to set - */ - public static void setProvisioningUri(String uri) - { - getConfigurationService().setProperty( - PROPERTY_PROVISIONING_URL, uri); - } - - /** * Returns the <tt>UIService</tt> obtained from the bundle context. * * @return the <tt>UIService</tt> obtained from the bundle context @@ -345,426 +198,6 @@ public class ProvisioningActivator } /** - * Retrieve configuration file from provisioning URL. - * This method is blocking until configuration file is retrieved from the - * network or if an exception happen - * - * @param url provisioning URL - * @return provisioning file downloaded - */ - private File retrieveConfigurationFile(String url) - { - File tmpFile = null; - - try - { - String arg = null; - String args[] = null; - final File temp = File.createTempFile("provisioning", - ".properties"); - - tmpFile = temp; - - URL u = new URL(url); - InetAddress ipaddr = getNetworkAddressManagerService(). - getLocalHost(InetAddress.getByName(u.getHost())); - - if(url.indexOf("${uuid}") != -1) - { - url = url.replace("${uuid}", (String)getConfigurationService() - .getProperty(PROVISIONING_UUID_PROP)); - } - - if(url.indexOf("${osname}") != -1) - { - url = url.replace("${osname}", System.getProperty("os.name")); - } - - if(url.indexOf("${arch}") != -1) - { - url = url.replace("${arch}", System.getProperty("os.arch")); - } - - if(url.indexOf("${resx}") != -1 || url.indexOf("${resy}") != -1) - { - Rectangle screen = ScreenInformation.getScreenBounds(); - - if(url.indexOf("${resx}") != -1) - { - url = url.replace("${resx}", String.valueOf(screen.width)); - } - - if(url.indexOf("${resy}") != -1) - { - url = url.replace("${resy}", String.valueOf(screen.height)); - } - } - - if(url.indexOf("${build}") != -1) - { - url = url.replace("${build}", - System.getProperty("sip-communicator.version")); - } - - if(url.indexOf("${ipaddr}") != -1) - { - url = url.replace("${ipaddr}", ipaddr.getHostAddress()); - } - - if(url.indexOf("${hwaddr}") != -1) - { - if(ipaddr != null) - { - /* find the hardware address of the interface - * that has this IP address - */ - Enumeration<NetworkInterface> en = - NetworkInterface.getNetworkInterfaces(); - - while(en.hasMoreElements()) - { - NetworkInterface iface = en.nextElement(); - - Enumeration<InetAddress> enInet = - iface.getInetAddresses(); - - while(enInet.hasMoreElements()) - { - InetAddress inet = enInet.nextElement(); - - if(inet.equals(ipaddr)) - { - byte hw[] = - getNetworkAddressManagerService(). - getHardwareAddress(iface); - - if(hw == null) - continue; - - StringBuffer buf = - new StringBuffer(); - - for(byte h : hw) - { - int hi = h >= 0 ? h : h + 256; - String t = new String( - (hi <= 0xf) ? "0" : ""); - t += Integer.toHexString(hi); - buf.append(t); - buf.append(":"); - } - - buf.deleteCharAt(buf.length() - 1); - - url = url.replace("${hwaddr}", - buf.toString()); - - break; - } - } - } - } - } - - if(url.contains("?")) - { - /* do not handle URL of type http://domain/index.php? (no - * parameters) - */ - if((url.indexOf('?') + 1) != url.length()) - { - arg = url.substring(url.indexOf('?') + 1); - args = arg.split("&"); - } - url = url.substring(0, url.indexOf('?')); - } - - String[] paramNames = null; - String[] paramValues = null; - int usernameIx = -1; - int passwordIx = -1; - - if(args != null && args.length > 0) - { - paramNames = new String[args.length]; - paramValues = new String[args.length]; - - for(int i = 0; i < args.length; i++) - { - String s = args[i]; - - String usernameParam = "${username}"; - String passwordParam = "${password}"; - - // If we find the username or password parameter at this - // stage we replace it with an empty string. - if(s.indexOf(usernameParam) != -1) - { - s = s.replace(usernameParam, ""); - usernameIx = i; - } - else if(s.indexOf(passwordParam) != -1) - { - s = s.replace(passwordParam, ""); - passwordIx = i; - } - - int equalsIndex = s.indexOf("="); - if (equalsIndex > 0) - { - paramNames[i] = s.substring(0, equalsIndex); - paramValues[i] = s.substring(equalsIndex + 1); - } - } - } - - HttpUtils.HTTPResponseResult res = - HttpUtils.postForm( - url, - PROPERTY_PROVISIONING_USERNAME, - PROPERTY_PROVISIONING_PASSWORD, - paramNames, - paramValues, - usernameIx, - passwordIx); - - // if there was an error in retrieving stop - if(res == null) - return null; - - InputStream in = res.getContent(); - - // Chain a ProgressMonitorInputStream to the - // URLConnection's InputStream - final ProgressMonitorInputStream pin - = new ProgressMonitorInputStream(null, u.toString(), in); - - // Set the maximum value of the ProgressMonitor - ProgressMonitor pm = pin.getProgressMonitor(); - pm.setMaximum((int)res.getContentLength()); - - final BufferedOutputStream bout - = new BufferedOutputStream(new FileOutputStream(temp)); - - try - { - int read = -1; - byte[] buff = new byte[1024]; - - while((read = pin.read(buff)) != -1) - { - bout.write(buff, 0, read); - } - - pin.close(); - bout.flush(); - bout.close(); - - return temp; - } - catch (Exception e) - { - logger.error("Error saving", e); - - try - { - pin.close(); - bout.close(); - } - catch (Exception e1) - { - } - - return null; - } - } - catch (Exception e) - { - if (logger.isInfoEnabled()) - logger.info("Error retrieving provisioning file!", e); - tmpFile.delete(); - return null; - } - } - - /** - * Update configuration with properties retrieved from provisioning URL. - * - * @param file provisioning file - */ - private void updateConfiguration(final File file) - { - Properties fileProps = new OrderedProperties(); - InputStream in = null; - - try - { - in = new BufferedInputStream(new FileInputStream(file)); - fileProps.load(in); - - Iterator<Map.Entry<Object, Object> > it - = fileProps.entrySet().iterator(); - - while(it.hasNext()) - { - Map.Entry<Object, Object> entry = it.next(); - String key = (String)entry.getKey(); - Object value = entry.getValue(); - - if(key.equals(PROVISIONING_ALLOW_PREFIX_PROP)) - { - String prefixes[] = ((String)value).split("\\|"); - - /* updates allowed prefixes list */ - for(String s : prefixes) - { - allowedPrefixes.add(s); - } - continue; - } - else if(key.equals(PROVISIONING_ENFORCE_PREFIX_PROP)) - { - checkEnforcePrefix((String)value); - continue; - } - - /* check that properties is allowed */ - if(!isPrefixAllowed(key)) - { - continue; - } - - processProperty(key, value); - } - - try - { - /* save and reload the "new" configuration */ - getConfigurationService().storeConfiguration(); - getConfigurationService().reloadConfiguration(); - } - catch(Exception e) - { - logger.error("Cannot reload configuration"); - } - } - catch(IOException e) - { - logger.warn("Error during load of provisioning file"); - } - finally - { - try - { - in.close(); - file.delete(); - } - catch(IOException e) - { - } - } - } - - /** - * Check if a property name belongs to the allowed prefixes. - * - * @param key property key name - * @return true if key is allowed, false otherwise - */ - private boolean isPrefixAllowed(String key) - { - if(allowedPrefixes.size() > 0) - { - for(String s : allowedPrefixes) - { - if(key.startsWith(s)) - { - return true; - } - } - - /* current property prefix is not allowed */ - return false; - } - else - { - /* no allowed prefixes configured so key is valid by default */ - return true; - } - } - - /** - * Process a new property. If value equals "${null}", it means to remove the - * property in the configuration service. If the key name end with - * "PASSWORD", its value is encrypted through credentials storage service, - * otherwise the property is added/updated in the configuration service. - * - * @param key property key name - * @param value property value - */ - private void processProperty(String key, Object value) - { - if((value instanceof String) && ((String)value).equals("${null}")) - { - getConfigurationService().removeProperty(key); - } - else if(key.endsWith(".PASSWORD")) - { - /* password => credentials storage service */ - getCredentialsStorageService().storePassword( - key.substring(0, key.lastIndexOf(".")), - (String)value); - } - else - { - getConfigurationService().setProperty(key, value); - } - } - - /** - * Walk through all properties and make sure all properties keys match - * a specific set of prefixes defined in configuration. - * - * @param enforcePrefix list of enforce prefix. - */ - private void checkEnforcePrefix(String enforcePrefix) - { - ConfigurationService config = getConfigurationService(); - String prefixes[] = null; - - if(enforcePrefix == null) - { - return; - } - - /* must escape the | character */ - prefixes = enforcePrefix.split("\\|"); - - /* get all properties */ - for (String key : config.getAllPropertyNames()) - { - boolean isValid = false; - - for(String k : prefixes) - { - if(key.startsWith(k)) - { - isValid = true; - break; - } - } - - /* property name does is not in the enforce prefix list - * so remove it - */ - if(!isValid) - { - config.removeProperty(key); - } - } - } - - /** * Returns a reference to a ConfigurationService implementation currently * registered in the bundle context or null if no such implementation was * found. @@ -827,4 +260,14 @@ public class ProvisioningActivator } return netaddrService; } + + /** + * Returns a reference to a <tt>ProvisioningService</tt> implementation. + * + * @return a currently valid implementation of <tt>ProvisioningService</tt> + */ + public static ProvisioningServiceImpl getProvisioningService() + { + return provisioningService; + } } diff --git a/src/net/java/sip/communicator/plugin/provisioning/ProvisioningForm.java b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningForm.java index 50cc9f2..151a119 100644 --- a/src/net/java/sip/communicator/plugin/provisioning/ProvisioningForm.java +++ b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningForm.java @@ -169,7 +169,8 @@ public class ProvisioningForm uuidPane.setEditable(false); uuidPane.setOpaque(false); uuidPane.setText( - config.getString(ProvisioningActivator.PROVISIONING_UUID_PROP)); + config.getString(ProvisioningServiceImpl. + PROVISIONING_UUID_PROP)); uuidPanel.add(new JLabel(resources.getI18NString( "plugin.provisioning.UUID"))); @@ -276,7 +277,8 @@ public class ProvisioningForm */ private void initButtonStates() { - String provMethod = ProvisioningActivator.getProvisioningMethod(); + String provMethod = ProvisioningActivator.getProvisioningService(). + getProvisioningMethod(); boolean isProvEnabled = (provMethod != null && provMethod.length() > 0 @@ -296,7 +298,8 @@ public class ProvisioningForm { manualButton.setSelected(true); - String uri = ProvisioningActivator.getProvisioningUri(); + String uri = ProvisioningActivator.getProvisioningService(). + getProvisioningUri(); if (uri != null) uriField.setText(uri); } @@ -311,16 +314,16 @@ public class ProvisioningForm // creadentials forgetPasswordButton.setEnabled(isProvEnabled); usernameField.setText(ProvisioningActivator.getConfigurationService() - .getString(ProvisioningActivator.PROPERTY_PROVISIONING_USERNAME)); + .getString(ProvisioningServiceImpl.PROPERTY_PROVISIONING_USERNAME)); if(ProvisioningActivator.getCredentialsStorageService() .isStoredEncrypted( - ProvisioningActivator.PROPERTY_PROVISIONING_PASSWORD)) + ProvisioningServiceImpl.PROPERTY_PROVISIONING_PASSWORD)) { passwordField.setText( ProvisioningActivator.getCredentialsStorageService() .loadPassword( - ProvisioningActivator.PROPERTY_PROVISIONING_PASSWORD)); + ProvisioningServiceImpl.PROPERTY_PROVISIONING_PASSWORD)); } } @@ -367,8 +370,8 @@ public class ProvisioningForm } } - ProvisioningActivator - .setProvisioningMethod(provisioningMethod); + ProvisioningActivator.getProvisioningService(). + setProvisioningMethod(provisioningMethod); } }); @@ -377,8 +380,8 @@ public class ProvisioningForm public void stateChanged(ChangeEvent e) { if (dhcpButton.isSelected()) - ProvisioningActivator - .setProvisioningMethod("DHCP"); + ProvisioningActivator.getProvisioningService(). + setProvisioningMethod("DHCP"); } }); @@ -387,8 +390,8 @@ public class ProvisioningForm public void stateChanged(ChangeEvent e) { if (dnsButton.isSelected()) - ProvisioningActivator - .setProvisioningMethod("DNS"); + ProvisioningActivator.getProvisioningService(). + setProvisioningMethod("DNS"); } }); @@ -397,8 +400,8 @@ public class ProvisioningForm public void stateChanged(ChangeEvent e) { if (bonjourButton.isSelected()) - ProvisioningActivator - .setProvisioningMethod("Bonjour"); + ProvisioningActivator.getProvisioningService(). + setProvisioningMethod("Bonjour"); } }); @@ -412,15 +415,19 @@ public class ProvisioningForm if (isSelected) { - ProvisioningActivator - .setProvisioningMethod("Manual"); + ProvisioningActivator.getProvisioningService(). + setProvisioningMethod("Manual"); String uriText = uriField.getText(); if (uriText != null && uriText.length() > 0) - ProvisioningActivator.setProvisioningUri(uriText); + ProvisioningActivator.getProvisioningService(). + setProvisioningUri(uriText); } else - ProvisioningActivator.setProvisioningUri(null); + { + ProvisioningActivator.getProvisioningService(). + setProvisioningUri(null); + } } }); @@ -435,7 +442,8 @@ public class ProvisioningForm String uriText = uriField.getText(); if (uriText != null && uriText.length() > 0) - ProvisioningActivator.setProvisioningUri(uriText); + ProvisioningActivator.getProvisioningService(). + setProvisioningUri(uriText); } public void focusGained(FocusEvent e) {} @@ -453,7 +461,8 @@ public class ProvisioningForm int result = JOptionPane.showConfirmDialog( (Component)ProvisioningActivator.getUIService() - .getExportedWindow(ExportedWindow.MAIN_WINDOW).getSource(), + .getExportedWindow(ExportedWindow.MAIN_WINDOW). + getSource(), ProvisioningActivator.getResourceService().getI18NString( "plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE"), ProvisioningActivator.getResourceService().getI18NString( @@ -463,11 +472,11 @@ public class ProvisioningForm if (result == JOptionPane.YES_OPTION) { ProvisioningActivator.getCredentialsStorageService() - .removePassword( - ProvisioningActivator.PROPERTY_PROVISIONING_PASSWORD); + .removePassword(ProvisioningServiceImpl. + PROPERTY_PROVISIONING_PASSWORD); ProvisioningActivator.getConfigurationService() - .removeProperty( - ProvisioningActivator.PROPERTY_PROVISIONING_USERNAME); + .removeProperty(ProvisioningServiceImpl. + PROPERTY_PROVISIONING_USERNAME); usernameField.setText(""); passwordField.setText(""); diff --git a/src/net/java/sip/communicator/plugin/provisioning/ProvisioningServiceImpl.java b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningServiceImpl.java new file mode 100644 index 0000000..58d2e57 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/provisioning/ProvisioningServiceImpl.java @@ -0,0 +1,667 @@ +package net.java.sip.communicator.plugin.provisioning; + +import java.awt.*; +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.List; // disambiguation + +import javax.swing.*; + +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.httputil.*; +import net.java.sip.communicator.service.provisioning.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; + +/** + * Provisioning service. + * + * @author Sebastien Vincent + */ +public class ProvisioningServiceImpl + implements ProvisioningService +{ + /** + * Logger of this class + */ + private static final Logger logger + = Logger.getLogger(ProvisioningServiceImpl.class); + + /** + * Name of the UUID property. + */ + public static final String PROVISIONING_UUID_PROP + = "net.java.sip.communicator.UUID"; + + /** + * Name of the provisioning URL in the configuration service. + */ + private static final String PROPERTY_PROVISIONING_URL + = "net.java.sip.communicator.plugin.provisioning.URL"; + + /** + * Name of the provisioning username in the configuration service + * authentication). + */ + static final String PROPERTY_PROVISIONING_USERNAME + = "net.java.sip.communicator.plugin.provisioning.auth.USERNAME"; + + /** + * Name of the provisioning password in the configuration service (HTTP + * authentication). + */ + static final String PROPERTY_PROVISIONING_PASSWORD + = "net.java.sip.communicator.plugin.provisioning.auth"; + + /** + * Name of the property that contains the provisioning method (i.e. DHCP, + * DNS, manual, ...). + */ + private static final String PROVISIONING_METHOD_PROP + = "net.java.sip.communicator.plugin.provisioning.METHOD"; + + /** + * Name of the property that contains enforce prefix list (separated by + * pipe) for the provisioning. The retrieved configuration properties will + * be checked against these prefixes to avoid having incorrect content in + * the configuration file (such as HTML content resulting of HTTP error). + */ + private static final String PROVISIONING_ALLOW_PREFIX_PROP + = "provisioning.ALLOW_PREFIX"; + + /** + * Name of the enforce prefix property. + */ + private static final String PROVISIONING_ENFORCE_PREFIX_PROP + = "provisioning.ENFORCE_PREFIX"; + + + /** + * List of allowed configuration prefixes. + */ + private List<String> allowedPrefixes = new ArrayList<String>(); + + /** + * Authentication username. + */ + private static String provUsername = null; + + /** + * Authentication password. + */ + private static String provPassword = null; + + /** + * Constructor. + */ + public ProvisioningServiceImpl() + { + // check if UUID is already configured + String uuid = (String)ProvisioningActivator.getConfigurationService(). + getProperty(PROVISIONING_UUID_PROP); + + if(uuid == null || uuid.equals("")) + { + uuid = UUID.randomUUID().toString(); + ProvisioningActivator.getConfigurationService().setProperty( + PROVISIONING_UUID_PROP, uuid); + } + + } + + /** + * Starts provisioning. + * + * @param url provisioning URL + */ + void start(String url) + { + if(url == null) + { + /* try to see if provisioning URL is stored in properties */ + url = getProvisioningUri(); + } + + if(url != null) + { + File file = retrieveConfigurationFile(url); + + if(file != null) + { + /* store the provisioning URL in local configuration in case + * the provisioning discovery failed (DHCP/DNS unavailable, ...) + */ + ProvisioningActivator.getConfigurationService().setProperty( + PROPERTY_PROVISIONING_URL, url); + + updateConfiguration(file); + } + } + } + + /** + * Indicates if the provisioning has been enabled. + * + * @return <tt>true</tt> if the provisioning is enabled, <tt>false</tt> - + * otherwise + */ + public String getProvisioningMethod() + { + String provMethod + = ProvisioningActivator.getConfigurationService().getString( + PROVISIONING_METHOD_PROP); + + if (provMethod == null || provMethod.length() <= 0) + { + provMethod = ProvisioningActivator.getResourceService(). + getSettingsString( + "plugin.provisioning.DEFAULT_PROVISIONING_METHOD"); + + if (provMethod != null && provMethod.length() > 0) + setProvisioningMethod(provMethod); + } + + return provMethod; + } + + /** + * Enables the provisioning with the given method. If the provisioningMethod + * is null disables the provisioning. + * + * @param provisioningMethod the provisioning method + */ + public void setProvisioningMethod(String provisioningMethod) + { + ProvisioningActivator.getConfigurationService().setProperty( + PROVISIONING_METHOD_PROP, provisioningMethod); + } + + /** + * Returns the provisioning URI. + * + * @return the provisioning URI + */ + public String getProvisioningUri() + { + String provUri + = ProvisioningActivator.getConfigurationService().getString( + PROPERTY_PROVISIONING_URL); + + if (provUri == null || provUri.length() <= 0) + { + provUri = ProvisioningActivator.getResourceService(). + getSettingsString( + "plugin.provisioning.DEFAULT_PROVISIONING_URI"); + + if (provUri != null && provUri.length() > 0) + setProvisioningUri(provUri); + } + return provUri; + } + + /** + * Sets the provisioning URI. + * + * @param uri the provisioning URI to set + */ + public void setProvisioningUri(String uri) + { + ProvisioningActivator.getConfigurationService().setProperty( + PROPERTY_PROVISIONING_URL, uri); + } + + /** + * Returns provisioning username. + * + * @return provisioning username + */ + public String getProvisioningUsername() + { + return provUsername; + } + + /** + * Returns provisioning password. + * + * @return provisioning password + */ + public String getProvisioningPassword() + { + return provPassword; + } + + /** + * Retrieve configuration file from provisioning URL. + * This method is blocking until configuration file is retrieved from the + * network or if an exception happen + * + * @param url provisioning URL + * @return provisioning file downloaded + */ + private File retrieveConfigurationFile(String url) + { + File tmpFile = null; + + try + { + String arg = null; + String args[] = null; + final File temp = File.createTempFile("provisioning", + ".properties"); + + tmpFile = temp; + + URL u = new URL(url); + InetAddress ipaddr = + ProvisioningActivator.getNetworkAddressManagerService(). + getLocalHost(InetAddress.getByName(u.getHost())); + + if(url.indexOf("${uuid}") != -1) + { + url = url.replace("${uuid}", + (String)ProvisioningActivator.getConfigurationService() + .getProperty(PROVISIONING_UUID_PROP)); + } + + if(url.indexOf("${osname}") != -1) + { + url = url.replace("${osname}", System.getProperty("os.name")); + } + + if(url.indexOf("${arch}") != -1) + { + url = url.replace("${arch}", System.getProperty("os.arch")); + } + + if(url.indexOf("${resx}") != -1 || url.indexOf("${resy}") != -1) + { + Rectangle screen = ScreenInformation.getScreenBounds(); + + if(url.indexOf("${resx}") != -1) + { + url = url.replace("${resx}", String.valueOf(screen.width)); + } + + if(url.indexOf("${resy}") != -1) + { + url = url.replace("${resy}", String.valueOf(screen.height)); + } + } + + if(url.indexOf("${build}") != -1) + { + url = url.replace("${build}", + System.getProperty("sip-communicator.version")); + } + + if(url.indexOf("${ipaddr}") != -1) + { + url = url.replace("${ipaddr}", ipaddr.getHostAddress()); + } + + if(url.indexOf("${hwaddr}") != -1) + { + if(ipaddr != null) + { + /* find the hardware address of the interface + * that has this IP address + */ + Enumeration<NetworkInterface> en = + NetworkInterface.getNetworkInterfaces(); + + while(en.hasMoreElements()) + { + NetworkInterface iface = en.nextElement(); + + Enumeration<InetAddress> enInet = + iface.getInetAddresses(); + + while(enInet.hasMoreElements()) + { + InetAddress inet = enInet.nextElement(); + + if(inet.equals(ipaddr)) + { + byte hw[] = + ProvisioningActivator. + getNetworkAddressManagerService(). + getHardwareAddress(iface); + + if(hw == null) + continue; + + StringBuffer buf = + new StringBuffer(); + + for(byte h : hw) + { + int hi = h >= 0 ? h : h + 256; + String t = new String( + (hi <= 0xf) ? "0" : ""); + t += Integer.toHexString(hi); + buf.append(t); + buf.append(":"); + } + + buf.deleteCharAt(buf.length() - 1); + + url = url.replace("${hwaddr}", + buf.toString()); + + break; + } + } + } + } + } + + if(url.contains("?")) + { + /* do not handle URL of type http://domain/index.php? (no + * parameters) + */ + if((url.indexOf('?') + 1) != url.length()) + { + arg = url.substring(url.indexOf('?') + 1); + args = arg.split("&"); + } + url = url.substring(0, url.indexOf('?')); + } + + String[] paramNames = null; + String[] paramValues = null; + int usernameIx = -1; + int passwordIx = -1; + + if(args != null && args.length > 0) + { + paramNames = new String[args.length]; + paramValues = new String[args.length]; + + for(int i = 0; i < args.length; i++) + { + String s = args[i]; + + String usernameParam = "${username}"; + String passwordParam = "${password}"; + + // If we find the username or password parameter at this + // stage we replace it with an empty string. + if(s.indexOf(usernameParam) != -1) + { + s = s.replace(usernameParam, ""); + usernameIx = i; + } + else if(s.indexOf(passwordParam) != -1) + { + s = s.replace(passwordParam, ""); + passwordIx = i; + } + + int equalsIndex = s.indexOf("="); + if (equalsIndex > 0) + { + paramNames[i] = s.substring(0, equalsIndex); + paramValues[i] = s.substring(equalsIndex + 1); + } + } + } + + HttpUtils.HTTPResponseResult res = + HttpUtils.postForm( + url, + PROPERTY_PROVISIONING_USERNAME, + PROPERTY_PROVISIONING_PASSWORD, + paramNames, + paramValues, + usernameIx, + passwordIx); + + // if there was an error in retrieving stop + if(res == null) + return null; + + String userPass[] = res.getCredentials(); + if(userPass[0] != null && userPass[1] != null) + { + provUsername = userPass[0]; + provPassword = userPass[1]; + } + + InputStream in = res.getContent(); + + // Chain a ProgressMonitorInputStream to the + // URLConnection's InputStream + final ProgressMonitorInputStream pin + = new ProgressMonitorInputStream(null, u.toString(), in); + + // Set the maximum value of the ProgressMonitor + ProgressMonitor pm = pin.getProgressMonitor(); + pm.setMaximum((int)res.getContentLength()); + + final BufferedOutputStream bout + = new BufferedOutputStream(new FileOutputStream(temp)); + + try + { + int read = -1; + byte[] buff = new byte[1024]; + + while((read = pin.read(buff)) != -1) + { + bout.write(buff, 0, read); + } + + pin.close(); + bout.flush(); + bout.close(); + + return temp; + } + catch (Exception e) + { + logger.error("Error saving", e); + + try + { + pin.close(); + bout.close(); + } + catch (Exception e1) + { + } + + return null; + } + } + catch (Exception e) + { + if (logger.isInfoEnabled()) + logger.info("Error retrieving provisioning file!", e); + tmpFile.delete(); + return null; + } + } + + /** + * Update configuration with properties retrieved from provisioning URL. + * + * @param file provisioning file + */ + private void updateConfiguration(final File file) + { + Properties fileProps = new OrderedProperties(); + InputStream in = null; + + try + { + in = new BufferedInputStream(new FileInputStream(file)); + fileProps.load(in); + + Iterator<Map.Entry<Object, Object> > it + = fileProps.entrySet().iterator(); + + while(it.hasNext()) + { + Map.Entry<Object, Object> entry = it.next(); + String key = (String)entry.getKey(); + Object value = entry.getValue(); + + if(key.equals(PROVISIONING_ALLOW_PREFIX_PROP)) + { + String prefixes[] = ((String)value).split("\\|"); + + /* updates allowed prefixes list */ + for(String s : prefixes) + { + allowedPrefixes.add(s); + } + continue; + } + else if(key.equals(PROVISIONING_ENFORCE_PREFIX_PROP)) + { + checkEnforcePrefix((String)value); + continue; + } + + /* check that properties is allowed */ + if(!isPrefixAllowed(key)) + { + continue; + } + + processProperty(key, value); + } + + try + { + /* save and reload the "new" configuration */ + ProvisioningActivator.getConfigurationService(). + storeConfiguration(); + ProvisioningActivator.getConfigurationService(). + reloadConfiguration(); + } + catch(Exception e) + { + logger.error("Cannot reload configuration"); + } + } + catch(IOException e) + { + logger.warn("Error during load of provisioning file"); + } + finally + { + try + { + in.close(); + file.delete(); + } + catch(IOException e) + { + } + } + } + + /** + * Check if a property name belongs to the allowed prefixes. + * + * @param key property key name + * @return true if key is allowed, false otherwise + */ + private boolean isPrefixAllowed(String key) + { + if(allowedPrefixes.size() > 0) + { + for(String s : allowedPrefixes) + { + if(key.startsWith(s)) + { + return true; + } + } + + /* current property prefix is not allowed */ + return false; + } + else + { + /* no allowed prefixes configured so key is valid by default */ + return true; + } + } + + /** + * Process a new property. If value equals "${null}", it means to remove the + * property in the configuration service. If the key name end with + * "PASSWORD", its value is encrypted through credentials storage service, + * otherwise the property is added/updated in the configuration service. + * + * @param key property key name + * @param value property value + */ + private void processProperty(String key, Object value) + { + if((value instanceof String) && ((String)value).equals("${null}")) + { + ProvisioningActivator.getConfigurationService().removeProperty(key); + } + else if(key.endsWith(".PASSWORD")) + { + /* password => credentials storage service */ + ProvisioningActivator.getCredentialsStorageService().storePassword( + key.substring(0, key.lastIndexOf(".")), + (String)value); + } + else + { + ProvisioningActivator.getConfigurationService().setProperty(key, + value); + } + } + + /** + * Walk through all properties and make sure all properties keys match + * a specific set of prefixes defined in configuration. + * + * @param enforcePrefix list of enforce prefix. + */ + private void checkEnforcePrefix(String enforcePrefix) + { + ConfigurationService config = + ProvisioningActivator.getConfigurationService(); + String prefixes[] = null; + + if(enforcePrefix == null) + { + return; + } + + /* must escape the | character */ + prefixes = enforcePrefix.split("\\|"); + + /* get all properties */ + for (String key : config.getAllPropertyNames()) + { + boolean isValid = false; + + for(String k : prefixes) + { + if(key.startsWith(k)) + { + isValid = true; + break; + } + } + + /* property name does is not in the enforce prefix list + * so remove it + */ + if(!isValid) + { + config.removeProperty(key); + } + } + } +} diff --git a/src/net/java/sip/communicator/plugin/provisioning/provisioning.manifest.mf b/src/net/java/sip/communicator/plugin/provisioning/provisioning.manifest.mf index 7f8503a..ea2d941 100644 --- a/src/net/java/sip/communicator/plugin/provisioning/provisioning.manifest.mf +++ b/src/net/java/sip/communicator/plugin/provisioning/provisioning.manifest.mf @@ -14,6 +14,7 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.netaddr, net.java.sip.communicator.service.credentialsstorage, + net.java.sip.communicator.service.provisioning, net.java.sip.communicator.util, net.java.sip.communicator.util.swing, javax.swing, @@ -31,3 +32,4 @@ Import-Package: org.osgi.framework, javax.swing.tree, javax.swing.undo, javax.swing.border +Export-Package: net.java.sip.communicator.service.provisioning diff --git a/src/net/java/sip/communicator/service/httputil/HttpUtils.java b/src/net/java/sip/communicator/service/httputil/HttpUtils.java index f72b4b2..bc3f839 100644 --- a/src/net/java/sip/communicator/service/httputil/HttpUtils.java +++ b/src/net/java/sip/communicator/service/httputil/HttpUtils.java @@ -608,6 +608,16 @@ public class HttpUtils private boolean challengedForCredentials = false; /** + * Authentication username if any. + */ + private String authUsername = null; + + /** + * Authentication password if any. + */ + private String authPassword = null; + + /** * Creates HTTPCredentialsProvider. * @param usernamePropertyName the property to use to retrieve/store * username value if protected site is hit, for username @@ -670,6 +680,9 @@ public class HttpUtils new String(authWindow.getPassword()) ); + authUsername = authWindow.getUserName(); + authPassword = new String(authWindow.getPassword()); + // if password remember is checked lets save passwords, // if they seem not correct later will be removed. if(authWindow.isRememberPassword()) @@ -693,6 +706,11 @@ public class HttpUtils else { // we have saved values lets return them + authUsername = + HttpUtilActivator.getConfigurationService().getString( + usernamePropertyName); + authPassword = pass; + return new UsernamePasswordCredentials( HttpUtilActivator.getConfigurationService().getString( usernamePropertyName), @@ -721,6 +739,8 @@ public class HttpUtils passwordPropertyName); } this.challengedForCredentials = false; + authUsername = null; + authPassword = null; } /** @@ -760,6 +780,24 @@ public class HttpUtils { return this.challengedForCredentials; } + + /** + * Returns authentication username if any + * @return authentication username or null + */ + public String getAuthenticationUsername() + { + return authUsername; + } + + /** + * Returns authentication password if any + * @return authentication password or null + */ + public String getAuthenticationPassword() + { + return authPassword; + } } /** @@ -839,14 +877,14 @@ public class HttpUtils /** * The httpclient. */ - HttpClient httpClient; + DefaultHttpClient httpClient; /** * Creates HTTPResponseResult. * @param entity the httpclient entity. * @param httpClient the httpclient. */ - HTTPResponseResult(HttpEntity entity, HttpClient httpClient) + HTTPResponseResult(HttpEntity entity, DefaultHttpClient httpClient) { this.entity = entity; this.httpClient = httpClient; @@ -900,5 +938,23 @@ public class HttpUtils httpClient.getConnectionManager().shutdown(); } } + + /** + * Get the credentials used by the request. + */ + public String[] getCredentials() + { + String cred[] = new String[2]; + + if(httpClient != null) + { + HTTPCredentialsProvider prov = (HTTPCredentialsProvider) + httpClient.getCredentialsProvider(); + cred[0] = prov.getAuthenticationUsername(); + cred[1] = prov.getAuthenticationPassword(); + } + + return cred; + } } } diff --git a/src/net/java/sip/communicator/service/provisioning/ProvisioningService.java b/src/net/java/sip/communicator/service/provisioning/ProvisioningService.java new file mode 100644 index 0000000..5887bdb --- /dev/null +++ b/src/net/java/sip/communicator/service/provisioning/ProvisioningService.java @@ -0,0 +1,52 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.service.provisioning; + +/** + * Provisioning service. + * + * @author Sebastien Vincent + */ +public interface ProvisioningService +{ + /** + * Indicates if the provisioning has been enabled. + * + * @return <tt>true</tt> if the provisioning is enabled, <tt>false</tt> - + * otherwise + */ + public String getProvisioningMethod(); + + /** + * Enables the provisioning with the given method. If the provisioningMethod + * is null disables the provisioning. + * + * @param provisioningMethod the provisioning method + */ + public void setProvisioningMethod(String provisioningMethod); + + /** + * Returns provisioning username if any. + * + * @return provisioning username + */ + public String getProvisioningUsername(); + + /** + * Returns provisioning password if any. + * + * @return provisioning password + */ + public String getProvisioningPassword(); + + /** + * Returns the provisioning URI. + * + * @return the provisioning URI + */ + public String getProvisioningUri(); +} |