/** * Copyright 2014 Microsoft Open Technologies Inc. * * 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 com.microsoftopentechnologies.intellij.components; import com.google.gson.Gson; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectLocator; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.*; import com.microsoftopentechnologies.intellij.helpers.AndroidStudioHelper; import com.microsoftopentechnologies.intellij.helpers.StringHelper; import com.microsoftopentechnologies.intellij.helpers.UIHelper; import com.microsoftopentechnologies.intellij.wizards.activityConfiguration.AddServiceWizard; import org.jetbrains.annotations.NotNull; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.Collection; public class MSOpenTechToolsApplication extends ApplicationComponent.Adapter { // NOTE: If you add new setting names to this list, evaluate whether it should be cleared // when the plugin is upgraded/uninstalled and add the setting to the array "settings" in // the "cleanTempData" function below. Otherwise your setting will get retained across // upgrades which can potentially cause issues. public static class AppSettingsNames { public static final String O365_AUTHENTICATION_TOKEN = "com.microsoftopentechnologies.intellij.O365AuthenticationToken"; public static final String SUBSCRIPTION_FILE = "com.microsoftopentechnologies.intellij.SubscriptionFile"; public static final String SELECTED_SUBSCRIPTIONS = "com.microsoftopentechnologies.intellij.SelectedSubscriptions"; public static final String AZURE_AUTHENTICATION_MODE = "com.microsoftopentechnologies.intellij.AzureAuthenticationMode"; public static final String AZURE_AUTHENTICATION_TOKEN = "com.microsoftopentechnologies.intellij.AzureAuthenticationToken"; public static final String CURRENT_PLUGIN_VERSION = "com.microsoftopentechnologies.intellij.PluginVersion"; } private static final String MOBILE_SERVICE_CODE = "//010fa0c4-5af1-4f81-95c1-720d9fab8d96"; private static final String NOTIFICATION_HUBS_CODE = "//46cca6b7-ff7d-4e05-9ef2-d7eb4798222e"; private static final String NOTIFICATION_HUBS_MOBILE_SERVICE_CODE = "//657555dc-6167-466a-9536-071307770d46"; private static final String OUTLOOK_SERVICES_CODE = "//fa684d69-70b3-41ec-83ff-2f8fa77aeeba"; private static final String FILE_SERVICES_CODE = "//1073bed4-78c3-4b4a-8a4d-ad874a286d86"; private static final String LIST_SERVICES_CODE = "//6695fd94-10cc-4274-b5df-46a3bc63a33d"; private static final String OUTLOOK_FILE_SERVICES_CODE = "//c4c2fd13-4abf-4785-a410-1887c5a1f1fc"; private static final String OUTLOOK_LIST_SERVICES_CODE = "//322e22fa-c249-4805-b057-c7b282acb605"; private static final String FILE_LIST_SERVICES_CODE = "//7193e8e2-dcec-4eb9-a3d6-02d86f88eaed"; private static final String OUTLOOK_FILE_LIST_SERVICES_CODE = "//25fdea0c-8a15-457f-9b15-dacb4e7dc2b2"; private static final VirtualFileListener vfl = getVirtualFileListener(); private static MSOpenTechToolsApplication current = null; private PluginSettings settings; // TODO: This needs to be the plugin ID from plugin.xml somehow. public static final String PLUGIN_ID = "com.microsoftopentechnologies.intellij"; public MSOpenTechToolsApplication() { } public static MSOpenTechToolsApplication getCurrent() { return current; } @Override @NotNull public String getComponentName() { return "MSOpenTechTools"; } @Override public void initComponent() { // save the object instance current = this; // load up the plugin settings try { loadPluginSettings(); } catch (IOException e) { UIHelper.showException("An error occurred while attempting to load " + "settings for the MSOpenTech Tools plugin.", e); } cleanTempData(PropertiesComponent.getInstance()); VirtualFileManager.getInstance().addVirtualFileListener(vfl); } @Override public void disposeComponent() { VirtualFileManager.getInstance().removeVirtualFileListener(vfl); } public PluginSettings getSettings() { return settings; } private void loadPluginSettings() throws IOException { BufferedReader reader = null; try { reader = new BufferedReader( new InputStreamReader( MSOpenTechToolsApplication.class.getResourceAsStream("/settings.json"))); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } Gson gson = new Gson(); settings = gson.fromJson(sb.toString(), PluginSettings.class); } finally { if (reader != null) { try { reader.close(); } catch (IOException ignored) { } } } } private void cleanTempData(PropertiesComponent propComp) { // check the plugin version stored in the properties; if it // doesn't match with the current plugin version then we clear // all stored options // TODO: The authentication tokens are stored with the subscription id appended as a // suffix to AZURE_AUTHENTICATION_TOKEN. So clearing that requires that we enumerate the // current subscriptions and iterate over that list to clear the auth tokens for those // subscriptions. PropertiesComponent properties = PropertiesComponent.getInstance(); String currentPluginVersion = properties.getValue(AppSettingsNames.CURRENT_PLUGIN_VERSION); if (StringHelper.isNullOrWhiteSpace(currentPluginVersion) || !getSettings().getPluginVersion().equals(currentPluginVersion)) { String[] settings = new String[]{ AppSettingsNames.AZURE_AUTHENTICATION_MODE, AppSettingsNames.AZURE_AUTHENTICATION_TOKEN, AppSettingsNames.O365_AUTHENTICATION_TOKEN, AppSettingsNames.SUBSCRIPTION_FILE }; for (String setting : settings) { properties.unsetValue(setting); } } // save the current plugin version properties.setValue(AppSettingsNames.CURRENT_PLUGIN_VERSION, getSettings().getPluginVersion()); } private static VirtualFileListener getVirtualFileListener() { return new VirtualFileListener() { @Override public void propertyChanged(@NotNull VirtualFilePropertyEvent virtualFilePropertyEvent) { } @Override public void contentsChanged(@NotNull VirtualFileEvent virtualFileEvent) { } @Override public void fileCreated(@NotNull final VirtualFileEvent virtualFileEvent) { } @Override public void fileDeleted(@NotNull VirtualFileEvent virtualFileEvent) { } @Override public void fileMoved(@NotNull VirtualFileMoveEvent virtualFileMoveEvent) { } @Override public void fileCopied(@NotNull VirtualFileCopyEvent virtualFileCopyEvent) { } @Override public void beforePropertyChange(@NotNull VirtualFilePropertyEvent virtualFilePropertyEvent) { } @Override public void beforeContentsChange(@NotNull VirtualFileEvent virtualFileEvent) { if (virtualFileEvent.isFromSave()) { final VirtualFile vf = virtualFileEvent.getFile(); Object requestor = virtualFileEvent.getRequestor(); if ("java".equals(vf.getExtension()) && (requestor instanceof FileDocumentManagerImpl)) { FileDocumentManagerImpl fdm = (FileDocumentManagerImpl) requestor; final Document document = fdm.getDocument(vf); if (document != null) { final int codeLineStart = document.getLineStartOffset(0); int codeLineEnd = document.getLineEndOffset(0); TextRange codeLineRange = new TextRange(codeLineStart, codeLineEnd); String codeLine = document.getText(codeLineRange); final boolean isMobileService = codeLine.equals(MOBILE_SERVICE_CODE) || codeLine.equals(NOTIFICATION_HUBS_MOBILE_SERVICE_CODE); final boolean isNotificationHub = codeLine.equals(NOTIFICATION_HUBS_CODE) || codeLine.equals(NOTIFICATION_HUBS_MOBILE_SERVICE_CODE); final boolean isOutlookServices = codeLine.equals(OUTLOOK_SERVICES_CODE) || codeLine.equals(OUTLOOK_FILE_SERVICES_CODE) || codeLine.equals(OUTLOOK_LIST_SERVICES_CODE) || codeLine.equals(OUTLOOK_FILE_LIST_SERVICES_CODE); final boolean isFileServices = codeLine.equals(FILE_SERVICES_CODE) || codeLine.equals(OUTLOOK_FILE_SERVICES_CODE) || codeLine.equals(FILE_LIST_SERVICES_CODE) || codeLine.equals(OUTLOOK_FILE_LIST_SERVICES_CODE); final boolean isListServices = codeLine.equals(LIST_SERVICES_CODE) || codeLine.equals(OUTLOOK_LIST_SERVICES_CODE) || codeLine.equals(FILE_LIST_SERVICES_CODE) || codeLine.equals(OUTLOOK_FILE_LIST_SERVICES_CODE); if (isMobileService || isNotificationHub || isOutlookServices || isFileServices || isListServices) { final int packageLineStart = document.getLineStartOffset(1); CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { @Override public void run() { document.deleteString(codeLineStart, packageLineStart); } }); fdm.saveDocument(document); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { Collection<Project> projects = ProjectLocator.getInstance().getProjectsForFile(vf); if (projects.size() == 1) { AddServiceWizard.run( (Project) projects.toArray()[0], ModuleUtil.findModuleForFile(vf, (Project) projects.toArray()[0]), vf.getNameWithoutExtension(), isMobileService, isNotificationHub, isOutlookServices, isFileServices, isListServices); } } }); } } } } } @Override public void beforeFileDeletion(@NotNull VirtualFileEvent virtualFileEvent) { } @Override public void beforeFileMovement(@NotNull VirtualFileMoveEvent virtualFileMoveEvent) { } }; } }