/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * 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.java.sip.communicator.service.protocol.jabber; import java.io.*; import java.util.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; import org.jitsi.service.configuration.*; import org.jitsi.service.neomedia.*; import org.osgi.framework.*; /** * The <tt>JabberAccountRegistration</tt> is used to store all user input data * through the <tt>JabberAccountRegistrationWizard</tt>. * * @author Yana Stamcheva * @author Boris Grozev */ public class JabberAccountRegistration extends JabberAccountID implements Serializable { /** * The default domain. */ private String defaultUserSufix; /** * Indicates if the password should be remembered. */ private boolean rememberPassword = true; /** * UID of edited account */ private String editedAccUID; /** * The list of additional STUN servers entered by user. */ private List<StunServerDescriptor> additionalStunServers = new ArrayList<StunServerDescriptor>(); /** * The list of additional JingleNodes (tracker or relay) entered by user. */ private List<JingleNodeDescriptor> additionalJingleNodes = new ArrayList<JingleNodeDescriptor>(); /** * The encodings registration object */ private EncodingsRegistrationUtil encodingsRegistration = new EncodingsRegistrationUtil(); /** * The security registration object */ private SecurityAccountRegistration securityRegistration = new SecurityAccountRegistration() { /** * Sets the method used for RTP/SAVP indication. */ @Override public void setSavpOption(int savpOption) { // SAVP option is not useful for XMPP account. // Thereby, do nothing. } /** * RTP/SAVP is disabled for Jabber protocol. * * @return Always <tt>ProtocolProviderFactory.SAVP_OFF</tt>. */ @Override public int getSavpOption() { return ProtocolProviderFactory.SAVP_OFF; } }; /** * Initializes a new JabberAccountRegistration. */ public JabberAccountRegistration() { super(null, new HashMap<String, String>()); } /** * Overrides to return UID loaded from edited AccountID. * @return UID of edited account. */ public String getAccountUniqueID() { return editedAccUID; } /** * Returns the user sufix. * * @return the user sufix */ public String getDefaultUserSufix() { return defaultUserSufix; } /** * Sets the User ID of the jabber registration account. * * @param userID the identifier of the jabber registration account. */ public void setUserID(String userID) { setOrRemoveIfEmpty(ProtocolProviderFactory.USER_ID, userID); } /** * {@inheritDoc} */ public String getUserID() { return getAccountPropertyString(ProtocolProviderFactory.USER_ID); } /** * Sets the default value of the user sufix. * * @param userSufix the user name sufix (the domain name after the @ sign) */ public void setDefaultUserSufix(String userSufix) { this.defaultUserSufix = userSufix; } /** * Returns TRUE if password has to remembered, FALSE otherwise. * @return TRUE if password has to remembered, FALSE otherwise */ public boolean isRememberPassword() { return rememberPassword; } /** * Sets the rememberPassword value of this jabber account registration. * @param rememberPassword TRUE if password has to remembered, FALSE * otherwise */ public void setRememberPassword(boolean rememberPassword) { this.rememberPassword = rememberPassword; } /** * Adds the given <tt>stunServer</tt> to the list of additional stun servers. * * @param stunServer the <tt>StunServer</tt> to add */ public void addStunServer(StunServerDescriptor stunServer) { additionalStunServers.add(stunServer); } /** * Returns the <tt>List</tt> of all additional stun servers entered by the * user. The list is guaranteed not to be <tt>null</tt>. * * @return the <tt>List</tt> of all additional stun servers entered by the * user. */ public List<StunServerDescriptor> getAdditionalStunServers() { return additionalStunServers; } /** * Adds the given <tt>node</tt> to the list of additional JingleNodes. * * @param node the <tt>node</tt> to add */ public void addJingleNodes(JingleNodeDescriptor node) { additionalJingleNodes.add(node); } /** * Returns the <tt>List</tt> of all additional stun servers entered by the * user. The list is guaranteed not to be <tt>null</tt>. * * @return the <tt>List</tt> of all additional stun servers entered by the * user. */ public List<JingleNodeDescriptor> getAdditionalJingleNodes() { return additionalJingleNodes; } /** * Returns <tt>EncodingsRegistrationUtil</tt> object which stores encodings * configuration. * @return <tt>EncodingsRegistrationUtil</tt> object which stores encodings * configuration. */ public EncodingsRegistrationUtil getEncodingsRegistration() { return encodingsRegistration; } /** * Returns <tt>SecurityAccountRegistration</tt> object which stores security * settings. * @return <tt>SecurityAccountRegistration</tt> object which stores security * settings. */ public SecurityAccountRegistration getSecurityRegistration() { return securityRegistration; } /** * Stores Jabber account configuration held by this registration object into * given<tt>accountProperties</tt> map. * * @param userName the user name that will be used. * @param passwd the password for this account. * @param protocolIconPath the path to protocol icon if used, or * <tt>null</tt> otherwise. * @param accountIconPath the path to account icon if used, or * <tt>null</tt> otherwise. * @param accountProperties the map used for storings account properties. * * @throws OperationFailedException if properties are invalid. */ public void storeProperties(String userName, String passwd, String protocolIconPath, String accountIconPath, Map<String, String> accountProperties) throws OperationFailedException { if(rememberPassword) setPassword(passwd); else setPassword(null); String serverName = null; if (getServerAddress() != null && getServerAddress().length() > 0) { serverName = getServerAddress(); } else { serverName = getServerFromUserName(userName); } if (serverName == null || serverName.length() <= 0) throw new OperationFailedException( "Should specify a server for user name " + userName + ".", OperationFailedException.SERVER_NOT_SPECIFIED); // Remove additional STUN servers and Jingle Nodes properties, // before entering new from lists BundleContext bContext = ProtocolProviderActivator.getBundleContext(); ProtocolProviderFactory jbfFactory = ProtocolProviderFactory .getProtocolProviderFactory( bContext, ProtocolNames.JABBER ); AccountManager accManager = ProtocolProviderActivator.getAccountManager(); String accountNodeName = accManager.getAccountNodeName(jbfFactory, editedAccUID); // Only if the account is stored in config if(accountNodeName != null) { ConfigurationService configSrvc = ProtocolProviderActivator.getConfigurationService(); String factoryPackage = accManager.getFactoryImplPackageName(jbfFactory); String accountPrefix = factoryPackage + "." + accountNodeName; List<String> allProperties = configSrvc.getAllPropertyNames(); String stunPrefix = accountPrefix+"."+ProtocolProviderFactory.STUN_PREFIX; String jinglePrefix = accountPrefix+"."+JingleNodeDescriptor.JN_PREFIX; for(String property : allProperties) { if( property.startsWith(stunPrefix) || property.startsWith(jinglePrefix) ) { configSrvc.removeProperty(property); } } // Also from this instance String[] accKeys = this.accountProperties.keySet().toArray( new String[accountProperties.size()]); for(String property : accKeys) { if(property.startsWith(ProtocolProviderFactory.STUN_PREFIX) || property.startsWith(JingleNodeDescriptor.JN_PREFIX)) { this.accountProperties.remove(property); } } } List<StunServerDescriptor> stunServers = getAdditionalStunServers(); int serverIndex = -1; for(StunServerDescriptor stunServer : stunServers) { serverIndex ++; stunServer.storeDescriptor( this.accountProperties, ProtocolProviderFactory.STUN_PREFIX + serverIndex); } List<JingleNodeDescriptor> jnRelays = getAdditionalJingleNodes(); serverIndex = -1; for(JingleNodeDescriptor jnRelay : jnRelays) { serverIndex ++; jnRelay.storeDescriptor(this.accountProperties, JingleNodeDescriptor.JN_PREFIX+serverIndex); } securityRegistration.storeProperties(this.accountProperties); encodingsRegistration.storeProperties(this.accountProperties); super.storeProperties( protocolIconPath, accountIconPath, accountProperties); } /** * Fills this registration object with configuration properties from given * <tt>account</tt>. * @param account the account object that will be used. * @param bundleContext the OSGi bundle context required for some * operations. */ public void loadAccount(AccountID account, BundleContext bundleContext) { mergeProperties(account.getAccountProperties(), accountProperties); String password = ProtocolProviderFactory.getProtocolProviderFactory( bundleContext, ProtocolNames.JABBER).loadPassword(account); setUserID(account.getUserID()); editedAccUID = account.getAccountUniqueID(); setPassword(password); rememberPassword = password != null; //Security properties securityRegistration.loadAccount(account); // ICE this.additionalStunServers.clear(); for (int i = 0; i < StunServerDescriptor.MAX_STUN_SERVER_COUNT; i ++) { StunServerDescriptor stunServer = StunServerDescriptor.loadDescriptor( accountProperties, ProtocolProviderFactory.STUN_PREFIX + i); // If we don't find a stun server with the given index, it means // that there're no more servers left in the table so we've nothing // more to do here. if (stunServer == null) break; String stunPassword = loadStunPassword( bundleContext, account, ProtocolProviderFactory.STUN_PREFIX + i); if(stunPassword != null) { stunServer.setPassword(stunPassword); } addStunServer(stunServer); } this.additionalJingleNodes.clear(); for (int i = 0; i < JingleNodeDescriptor.MAX_JN_RELAY_COUNT ; i ++) { JingleNodeDescriptor jn = JingleNodeDescriptor.loadDescriptor( accountProperties, JingleNodeDescriptor.JN_PREFIX + i); // If we don't find a stun server with the given index, it means // that there're no more servers left in the table so we've nothing // more to do here. if (jn == null) break; addJingleNodes(jn); } // Encodings encodingsRegistration.loadAccount( account, ServiceUtils.getService(bundleContext, MediaService.class)); } /** * Parse the server part from the jabber id and set it to server as default * value. If Advanced option is enabled Do nothing. * * @param userName the full JID that we'd like to parse. * * @return returns the server part of a full JID */ protected String getServerFromUserName(String userName) { int delimIndex = userName.indexOf("@"); if (delimIndex != -1) { String newServerAddr = userName.substring(delimIndex + 1); if (newServerAddr.equals(GOOGLE_USER_SUFFIX)) { return GOOGLE_CONNECT_SRV; } else { return newServerAddr; } } return null; } }