/* * 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.plugin.otr; import java.util.*; import net.java.sip.communicator.plugin.otr.authdialog.*; import net.java.sip.communicator.service.contactlist.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.msghistory.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; import org.jitsi.service.configuration.*; import org.jitsi.service.resources.*; import org.jitsi.util.*; import org.osgi.framework.*; /** * * @author George Politis * @author Pawel Domas */ public class OtrActivator extends AbstractServiceDependentActivator implements ServiceListener { /** * The {@link BundleContext} of the {@link OtrActivator}. */ public static BundleContext bundleContext; /** * The {@link ConfigurationService} of the {@link OtrActivator}. Can also be * obtained from the {@link OtrActivator#bundleContext} on demand, but we * add it here for convenience. */ public static ConfigurationService configService; /** * The <tt>Logger</tt> used by the <tt>OtrActivator</tt> class and its * instances for logging output. */ private static final Logger logger = Logger.getLogger(OtrActivator.class); /** * Indicates if the security/chat config form should be disabled, i.e. * not visible to the user. */ private static final String OTR_CHAT_CONFIG_DISABLED_PROP = "net.java.sip.communicator.plugin.otr.otrchatconfig.DISABLED"; /** * A property used in configuration to disable the OTR plugin. */ public static final String OTR_DISABLED_PROP = "net.java.sip.communicator.plugin.otr.DISABLED"; /** * A property specifying whether private messaging should be made mandatory. */ public static final String OTR_MANDATORY_PROP = "net.java.sip.communicator.plugin.otr.PRIVATE_MESSAGING_MANDATORY"; /** * The {@link ResourceManagementService} of the {@link OtrActivator}. Can * also be obtained from the {@link OtrActivator#bundleContext} on demand, * but we add it here for convenience. */ public static ResourceManagementService resourceService; /** * The {@link ScOtrEngine} of the {@link OtrActivator}. */ public static ScOtrEngineImpl scOtrEngine; /** * The {@link ScOtrKeyManager} of the {@link OtrActivator}. */ public static ScOtrKeyManager scOtrKeyManager = new ScOtrKeyManagerImpl(); /** * The {@link UIService} of the {@link OtrActivator}. Can also be obtained * from the {@link OtrActivator#bundleContext} on demand, but we add it here * for convenience. */ public static UIService uiService; /** * The <tt>MetaContactListService</tt> reference. */ private static MetaContactListService metaCListService; /** * The message history service. */ private static MessageHistoryService messageHistoryService; /** * The {@link OtrContactManager} of the {@link OtrActivator}. */ private static OtrContactManager otrContactManager; /** * Gets an {@link AccountID} by its UID. * * @param uid The {@link AccountID} UID. * @return The {@link AccountID} with the requested UID or null. */ public static AccountID getAccountIDByUID(String uid) { if (uid == null || uid.length() < 1) return null; Map<Object, ProtocolProviderFactory> providerFactoriesMap = OtrActivator.getProtocolProviderFactories(); if (providerFactoriesMap == null) return null; for (ProtocolProviderFactory providerFactory : providerFactoriesMap.values()) { for (AccountID accountID : providerFactory.getRegisteredAccounts()) { if (accountID.getAccountUniqueID().equals(uid)) return accountID; } } return null; } /** * Gets all the available accounts in SIP Communicator. * * @return a {@link List} of {@link AccountID}. */ public static List<AccountID> getAllAccountIDs() { Map<Object, ProtocolProviderFactory> providerFactoriesMap = OtrActivator.getProtocolProviderFactories(); if (providerFactoriesMap == null) return null; List<AccountID> accountIDs = new Vector<AccountID>(); for (ProtocolProviderFactory providerFactory : providerFactoriesMap.values()) { for (AccountID accountID : providerFactory.getRegisteredAccounts()) accountIDs.add(accountID); } return accountIDs; } private static Map<Object, ProtocolProviderFactory> getProtocolProviderFactories() { Collection<ServiceReference<ProtocolProviderFactory>> serRefs = ServiceUtils.getServiceReferences( bundleContext, ProtocolProviderFactory.class); Map<Object, ProtocolProviderFactory> providerFactoriesMap = new Hashtable<Object, ProtocolProviderFactory>(); if (!serRefs.isEmpty()) { for (ServiceReference<ProtocolProviderFactory> serRef : serRefs) { ProtocolProviderFactory providerFactory = bundleContext.getService(serRef); providerFactoriesMap.put( serRef.getProperty(ProtocolProviderFactory.PROTOCOL), providerFactory); } } return providerFactoriesMap; } private OtrTransformLayer otrTransformLayer; /** * The dependent class. We are waiting for the ui service. * @return the ui service class. */ @Override public Class<?> getDependentServiceClass() { return UIService.class; } private void handleProviderAdded(ProtocolProviderService provider) { OperationSetInstantMessageTransform opSetMessageTransform = provider.getOperationSet( OperationSetInstantMessageTransform.class); if (opSetMessageTransform != null) opSetMessageTransform.addTransformLayer(this.otrTransformLayer); else if (logger.isTraceEnabled()) logger.trace("Service did not have a transform op. set."); } private void handleProviderRemoved(ProtocolProviderService provider) { // check whether the provider has a basic im operation set OperationSetInstantMessageTransform opSetMessageTransform = provider.getOperationSet( OperationSetInstantMessageTransform.class); if (opSetMessageTransform != null) opSetMessageTransform.removeTransformLayer(this.otrTransformLayer); } /* * Implements ServiceListener#serviceChanged(ServiceEvent). */ @Override public void serviceChanged(ServiceEvent serviceEvent) { Object sService = bundleContext.getService(serviceEvent.getServiceReference()); if (logger.isTraceEnabled()) { logger.trace( "Received a service event for: " + sService.getClass().getName()); } // we don't care if the source service is not a protocol provider if (!(sService instanceof ProtocolProviderService)) return; if (logger.isDebugEnabled()) logger.debug("Service is a protocol provider."); if (serviceEvent.getType() == ServiceEvent.REGISTERED) { if (logger.isDebugEnabled()) { logger.debug( "Handling registration of a new Protocol Provider."); } this.handleProviderAdded((ProtocolProviderService) sService); } else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) { this.handleProviderRemoved((ProtocolProviderService) sService); } } /** * The bundle context to use. * @param context the context to set. */ @Override public void setBundleContext(BundleContext context) { bundleContext = context; } /* * Implements AbstractServiceDependentActivator#start(UIService). */ @Override public void start(Object dependentService) { configService = ServiceUtils.getService( bundleContext, ConfigurationService.class); // Check whether someone has disabled this plug-in. if(configService.getBoolean(OTR_DISABLED_PROP, false)) { configService = null; return; } resourceService = ResourceManagementServiceUtils.getService(bundleContext); if (resourceService == null) { configService = null; return; } uiService = (UIService) dependentService; // Init static variables, don't proceed without them. scOtrEngine = new ScOtrEngineImpl(); otrContactManager = new OtrContactManager(); otrTransformLayer = new OtrTransformLayer(); // Register Transformation Layer bundleContext.addServiceListener(this); bundleContext.addServiceListener(scOtrEngine); bundleContext.addServiceListener(otrContactManager); Collection<ServiceReference<ProtocolProviderService>> protocolProviderRefs = ServiceUtils.getServiceReferences( bundleContext, ProtocolProviderService.class); if (!protocolProviderRefs.isEmpty()) { if (logger.isDebugEnabled()) { logger.debug( "Found " + protocolProviderRefs.size() + " already installed providers."); } for (ServiceReference<ProtocolProviderService> protocolProviderRef : protocolProviderRefs) { ProtocolProviderService provider = bundleContext.getService(protocolProviderRef); handleProviderAdded(provider); } } if(!OSUtils.IS_ANDROID) { Hashtable<String, String> containerFilter = new Hashtable<String, String>(); // Register the right-click menu item. containerFilter.put(Container.CONTAINER_ID, Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID()); bundleContext.registerService( PluginComponentFactory.class.getName(), new OtrPluginComponentFactory( Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU), containerFilter); // Register the chat window menu bar item. containerFilter.put(Container.CONTAINER_ID, Container.CONTAINER_CHAT_MENU_BAR.getID()); bundleContext.registerService( PluginComponentFactory.class.getName(), new OtrPluginComponentFactory( Container.CONTAINER_CHAT_MENU_BAR), containerFilter); // Register the chat button bar default-action-button. containerFilter.put(Container.CONTAINER_ID, Container.CONTAINER_CHAT_TOOL_BAR.getID()); bundleContext.registerService( PluginComponentFactory.class.getName(), new OtrPluginComponentFactory( Container.CONTAINER_CHAT_TOOL_BAR), containerFilter); // Register Swing OTR action handler bundleContext.registerService( OtrActionHandler.class.getName(), new SwingOtrActionHandler(), null); containerFilter.put(Container.CONTAINER_ID, Container.CONTAINER_CHAT_WRITE_PANEL.getID()); bundleContext.registerService( PluginComponentFactory.class.getName(), new PluginComponentFactory(Container.CONTAINER_CHAT_WRITE_PANEL) { @Override protected PluginComponent getPluginInstance() { return new OTRv3OutgoingSessionSwitcher( getContainer(), this); } }, containerFilter); } // If the general configuration form is disabled don't register it. if (!configService.getBoolean(OTR_CHAT_CONFIG_DISABLED_PROP, false) && !OSUtils.IS_ANDROID) { Dictionary<String, String> properties = new Hashtable<String, String>(); properties.put( ConfigurationForm.FORM_TYPE, ConfigurationForm.SECURITY_TYPE); // Register the configuration form. bundleContext.registerService(ConfigurationForm.class.getName(), new LazyConfigurationForm( "net.java.sip.communicator.plugin.otr.authdialog." + "OtrConfigurationPanel", getClass().getClassLoader(), "plugin.otr.configform.ICON", "service.gui.CHAT", 1), properties); } } /* * Implements BundleActivator#stop(BundleContext). */ @Override public void stop(BundleContext bc) throws Exception { // Unregister transformation layer. // start listening for newly register or removed protocol providers bundleContext.removeServiceListener(this); if(scOtrEngine != null) bundleContext.removeServiceListener(scOtrEngine); if(otrContactManager != null) bundleContext.removeServiceListener(otrContactManager); Collection<ServiceReference<ProtocolProviderService>> protocolProviderRefs = ServiceUtils.getServiceReferences( bundleContext, ProtocolProviderService.class); if (!protocolProviderRefs.isEmpty()) { // in case we found any for (ServiceReference<ProtocolProviderService> protocolProviderRef : protocolProviderRefs) { ProtocolProviderService provider = bundleContext.getService(protocolProviderRef); handleProviderRemoved(provider); } } } /** * Returns the <tt>MetaContactListService</tt> obtained from the bundle * context. * @return the <tt>MetaContactListService</tt> obtained from the bundle * context */ public static MetaContactListService getContactListService() { if (metaCListService == null) { metaCListService = ServiceUtils.getService( bundleContext, MetaContactListService.class); } return metaCListService; } /** * Gets the service giving access to message history. * * @return the service giving access to message history. */ public static MessageHistoryService getMessageHistoryService() { if (messageHistoryService == null) { messageHistoryService = ServiceUtils.getService( bundleContext, MessageHistoryService.class); } return messageHistoryService; } /** * The factory that will be registered in OSGi and will create OTR menu * instances. */ private static class OtrPluginComponentFactory extends PluginComponentFactory { OtrPluginComponentFactory(Container c) { super(c); } @Override protected PluginComponent getPluginInstance() { Container container = getContainer(); if(container.equals(Container.CONTAINER_CHAT_TOOL_BAR)) return new OtrMetaContactButton(container, this); else return new OtrMetaContactMenu(container, this); } } }