/* * 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.impl.protocol.jabber; import java.util.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.jabber.*; import org.jivesoftware.smack.provider.*; import org.jivesoftware.smack.util.*; import org.osgi.framework.*; /** * The Jabber implementation of the ProtocolProviderFactory. * @author Damian Minkov */ public class ProtocolProviderFactoryJabberImpl extends ProtocolProviderFactory { /** * Indicates if ICE should be used. */ public static final String IS_USE_JINGLE_NODES = "JINGLE_NODES_ENABLED"; /** * Our provider manager instances. */ static ProviderManager providerManager = null; static { try { // Set the extension provider manager for classes that use // it directly ProviderManager.setInstance(new ProviderManagerExt()); // Set the Smack interop implementation for the classes that need // to support Smackv4 interoperation AbstractSmackInteroperabilityLayer.setImplementationClass( SmackV3InteroperabilityLayer.class); } catch(Throwable t) { // once loaded if we try to set instance second time // IllegalStateException is thrown } finally { providerManager = ProviderManager.getInstance(); } // checks class names, not using instanceof // tests do unloading and loading the protocol bundle and // ProviderManagerExt class get loaded two times from different // classloaders if (!(providerManager.getClass().getName() .equals(ProviderManagerExt.class.getName()))) { throw new RuntimeException( "ProviderManager set to the default one"); } } /** * Creates an instance of the ProtocolProviderFactoryJabberImpl. */ protected ProtocolProviderFactoryJabberImpl() { super(JabberActivator.getBundleContext(), ProtocolNames.JABBER); } /** * Ovverides the original in order give access to protocol implementation. * * @param accountID the account identifier. */ @Override protected void storeAccount(AccountID accountID) { super.storeAccount(accountID); } /** * Initializes and creates an account corresponding to the specified * accountProperties and registers the resulting ProtocolProvider in the * <tt>context</tt> BundleContext parameter. This method has a persistent * effect. Once created the resulting account will remain installed until * removed through the uninstall account method. * * @param userIDStr the user identifier for the new account * @param accountProperties a set of protocol (or implementation) * specific properties defining the new account. * @return the AccountID of the newly created account */ @Override public AccountID installAccount( String userIDStr, Map<String, String> accountProperties) { BundleContext context = JabberActivator.getBundleContext(); if (context == null) throw new NullPointerException( "The specified BundleContext was null"); if (userIDStr == null) throw new NullPointerException("The specified AccountID was null"); if (accountProperties == null) throw new NullPointerException( "The specified property map was null"); accountProperties.put(USER_ID, userIDStr); // if server address is null, we must extract it from userID if(accountProperties.get(SERVER_ADDRESS) == null) { String serverAddress = StringUtils.parseServer(userIDStr); if (serverAddress != null) accountProperties.put(SERVER_ADDRESS, StringUtils.parseServer(userIDStr)); else throw new IllegalArgumentException( "Should specify a server for user name " + userIDStr + "."); } // if server port is null, we will set default value if(accountProperties.get(SERVER_PORT) == null) { accountProperties.put(SERVER_PORT, "5222"); } AccountID accountID = new JabberAccountIDImpl(userIDStr, accountProperties); //make sure we haven't seen this account id before. if( registeredAccounts.containsKey(accountID) ) throw new IllegalStateException( "An account for id " + userIDStr + " was already installed!"); //first store the account and only then load it as the load generates //an osgi event, the osgi event triggers (through the UI) a call to //the register() method and it needs to access the configuration service //and check for a password. this.storeAccount(accountID, false); accountID = loadAccount(accountProperties); return accountID; } /** * Create an account. * * @param userID the user ID * @param accountProperties the properties associated with the user ID * @return new <tt>AccountID</tt> */ @Override protected AccountID createAccountID(String userID, Map<String, String> accountProperties) { return new JabberAccountIDImpl(userID, accountProperties); } @Override protected ProtocolProviderService createService(String userID, AccountID accountID) { ProtocolProviderServiceJabberImpl service = new ProtocolProviderServiceJabberImpl(); service.initialize(userID, (JabberAccountID) accountID); return service; } /** * Modify an existing account. * * @param protocolProvider the <tt>ProtocolProviderService</tt> responsible * of the account * @param accountProperties modified properties to be set */ @Override public void modifyAccount( ProtocolProviderService protocolProvider, Map<String, String> accountProperties) throws NullPointerException { BundleContext context = JabberActivator.getBundleContext(); if (context == null) throw new NullPointerException( "The specified BundleContext was null"); if (protocolProvider == null) throw new NullPointerException( "The specified Protocol Provider was null"); JabberAccountIDImpl accountID = (JabberAccountIDImpl) protocolProvider.getAccountID(); // If the given accountID doesn't correspond to an existing account // we return. if(!registeredAccounts.containsKey(accountID)) return; ServiceRegistration registration = registeredAccounts.get(accountID); // kill the service if (registration != null) { // unregister provider before removing it. try { if(protocolProvider.isRegistered()) { protocolProvider.unregister(); protocolProvider.shutdown(); } } catch (Throwable e) { // we don't care for this, cause we are modifying and // will unregister the service and will register again } registration.unregister(); } if (accountProperties == null) throw new NullPointerException( "The specified property map was null"); accountProperties.put(USER_ID, accountID.getUserID()); String serverAddress = accountProperties.get(SERVER_ADDRESS); if(serverAddress == null) throw new NullPointerException("null is not a valid ServerAddress"); // if server port is null, we will set default value if(accountProperties.get(SERVER_PORT) == null) { accountProperties.put(SERVER_PORT, "5222"); } if (!accountProperties.containsKey(PROTOCOL)) accountProperties.put(PROTOCOL, ProtocolNames.JABBER); accountID.setAccountProperties(accountProperties); // First store the account and only then load it as the load generates // an osgi event, the osgi event triggers (trhgough the UI) a call to // the register() method and it needs to acces the configuration service // and check for a password. this.storeAccount(accountID); Hashtable<String, String> properties = new Hashtable<String, String>(); properties.put(PROTOCOL, ProtocolNames.JABBER); properties.put(USER_ID, accountID.getUserID()); ((ProtocolProviderServiceJabberImpl) protocolProvider) .initialize(accountID.getUserID(), accountID); // We store again the account in order to store all properties added // during the protocol provider initialization. this.storeAccount(accountID); registration = context.registerService( ProtocolProviderService.class.getName(), protocolProvider, properties); registeredAccounts.put(accountID, registration); } }