From 7653c8fb1b65cb900636d1a1b9fee3cfcef42a0b Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 20 Jul 2016 10:34:39 +0200 Subject: [PATCH] DoNotStorePasswordTest --- .../testSrc/DoNotStorePasswordTest.kt | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 platform/configuration-store-impl/testSrc/DoNotStorePasswordTest.kt diff --git a/platform/configuration-store-impl/testSrc/DoNotStorePasswordTest.kt b/platform/configuration-store-impl/testSrc/DoNotStorePasswordTest.kt new file mode 100644 index 000000000000..bbeb2e3e7ea4 --- /dev/null +++ b/platform/configuration-store-impl/testSrc/DoNotStorePasswordTest.kt @@ -0,0 +1,99 @@ + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.impl.ApplicationImpl +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.impl.ComponentManagerImpl +import com.intellij.openapi.components.impl.ServiceManagerImpl +import com.intellij.openapi.components.impl.stores.StoreUtil +import com.intellij.openapi.extensions.PluginDescriptor +import com.intellij.testFramework.ProjectRule +import com.intellij.util.PairProcessor +import com.intellij.util.xmlb.XmlSerializerUtil +import org.jdom.Attribute +import org.jdom.Element +import org.junit.ClassRule +import org.junit.Test +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type +import java.util.Collection + +class DoNotStorePasswordTest { + companion object { + @JvmField + @ClassRule + val projectRule = ProjectRule() + } + + @Test + fun printPasswordComponents() { + checkPassword(ApplicationManager.getApplication() as ApplicationImpl) + // yes, we don't use default project here to be sure + checkPassword(projectRule.project as ComponentManagerImpl) + } + + fun isSavePasswordField(name: String) = name.contains("remember", ignoreCase = true) || name.contains("keep", ignoreCase = true) || name.contains("save", ignoreCase = true) + + fun check(clazz: Class<*>) { + if (clazz === Attribute::class.java || clazz === Element::class.java) { + return + } + + for (accessor in XmlSerializerUtil.getAccessors(clazz)) { + val name = accessor.name + if (name.contains("password", ignoreCase = true) && !isSavePasswordField(name)) { + System.out.println("${clazz.typeName}.${accessor.name}") + } + else if (!accessor.valueClass.isPrimitive) { + @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") + if (Collection::class.java.isAssignableFrom(accessor.valueClass)) { + val genericType = accessor.genericType + if (genericType is ParameterizedType) { + check(genericType.actualTypeArguments[0] as Class<*>) + } + } + else if (accessor.valueClass != clazz) { + check(accessor.valueClass) + } + } + } + } + + private fun checkPassword(componentManager: ComponentManagerImpl) { + ServiceManagerImpl.processAllImplementationClasses(componentManager, + PairProcessor, PluginDescriptor> { aClass, pluginDescriptor -> + val stateAnnotation = StoreUtil.getStateSpec(aClass) + if (stateAnnotation == null || stateAnnotation.name.isNullOrEmpty()) { + return@PairProcessor true + } + + for (i in aClass.genericInterfaces) { + if (checkType(i)) { + return@PairProcessor true + } + } + + + // public static class Project extends WebServersConfigManagerBaseImpl { + // so, we check not only PersistentStateComponent + checkType(aClass.genericSuperclass) + + true + }) + } + + private fun checkType(type: Type): Boolean { + if (type !is ParameterizedType || !PersistentStateComponent::class.java.isAssignableFrom(type.rawType as Class<*>)) { + return false + } + + type.actualTypeArguments[0].let { + if (it is ParameterizedType) { + check(it.rawType as Class<*>) + } + else { + check(it as Class<*>) + } + } + return true + } +} \ No newline at end of file