/* * Copyright 2000-2012 JetBrains s.r.o. * * 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.intellij.internal.statistic; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.internal.statistic.beans.GroupDescriptor; import com.intellij.internal.statistic.beans.PatchedUsage; import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.internal.statistic.connect.RemotelyConfigurableStatisticsService; import com.intellij.internal.statistic.connect.StatisticsConnectionService; import com.intellij.internal.statistic.connect.StatisticsHttpClientSender; import com.intellij.internal.statistic.connect.StatisticsService; import com.intellij.internal.statistic.persistence.SentUsagesPersistence; import com.intellij.internal.statistic.persistence.UsageStatisticsPersistenceComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; public class StatisticsUploadAssistant { private static final Logger LOG = Logger.getInstance("#com.intellij.internal.statistic.StatisticsUploadAssistant"); public String getData() { return getData(Collections.<String>emptySet()); } public static boolean isTimeToSend() { return isTimeToSend(UsageStatisticsPersistenceComponent.getInstance()); } public static boolean isTimeToSend(UsageStatisticsPersistenceComponent settings) { final long timeDelta = System.currentTimeMillis() - settings.getLastTimeSent(); return Math.abs(timeDelta) > settings.getPeriod().getMillis(); } public static boolean isSendAllowed() { return isSendAllowed(UsageStatisticsPersistenceComponent.getInstance()); } public static boolean isSendAllowed(final SentUsagesPersistence settings) { return settings != null && settings.isAllowed(); } public String getData(@NotNull Set<String> disabledGroups) { return getStringPatch(disabledGroups, ProjectManager.getInstance().getOpenProjects()); } public static void persistSentPatch(@NotNull String patchStr) { persistSentPatch(patchStr, UsageStatisticsPersistenceComponent.getInstance()); } public static void persistSentPatch(@NotNull String patchStr, @NotNull SentUsagesPersistence persistenceComponent) { Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages = mapToPatchedUsagesMap(ConvertUsagesUtil.convertString(patchStr)); if (patchedUsages.size() > 0) persistenceComponent.persistPatch(patchedUsages); } @NotNull public static String getStringPatch(@NotNull Set<String> disabledGroups, Project... project) { return getStringPatch(disabledGroups, project, UsageStatisticsPersistenceComponent.getInstance(), 0); } @NotNull public static String getStringPatch(@NotNull Set<String> disabledGroups, @NotNull Project[] projects, @NotNull SentUsagesPersistence usagesPersistence, int maxSize) { final Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages = getPatchedUsages(disabledGroups, projects, usagesPersistence); return getStringPatch(patchedUsages, maxSize); } public static String getStringPatch(@NotNull Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages, int maxSize) { if (patchedUsages.size() == 0) return ""; String patchStr = ConvertUsagesUtil.convertUsages(patchedUsages); if (maxSize > 0 && patchStr.getBytes().length > maxSize) { patchStr = ConvertUsagesUtil.cutPatchString(patchStr, maxSize); } return patchStr; } @NotNull public static Map<GroupDescriptor, Set<PatchedUsage>> getPatchedUsages(@NotNull Set<String> disabledGroups, @NotNull Project[] projects, @NotNull SentUsagesPersistence usagesPersistence) { Map<GroupDescriptor, Set<PatchedUsage>> usages = new LinkedHashMap<GroupDescriptor, Set<PatchedUsage>>(); for (Project project : projects) { final Map<GroupDescriptor, Set<UsageDescriptor>> allUsages = getAllUsages(project, disabledGroups); final Map<GroupDescriptor, Set<UsageDescriptor>> sentUsages = filterDisabled(disabledGroups, usagesPersistence.getSentUsages()); usages.putAll(getPatchedUsages(allUsages, sentUsages)); } return usages; } @NotNull private static Map<GroupDescriptor, Set<UsageDescriptor>> filterDisabled(@NotNull Set<String> disabledGroups, @NotNull Map<GroupDescriptor, Set<UsageDescriptor>> usages) { Map<GroupDescriptor, Set<UsageDescriptor>> filtered = new LinkedHashMap<GroupDescriptor, Set<UsageDescriptor>>(); for (Map.Entry<GroupDescriptor, Set<UsageDescriptor>> usage : usages.entrySet()) { if (!disabledGroups.contains(usage.getKey().getId())) { filtered.put(usage.getKey(), usage.getValue()); } } return filtered; } @NotNull public static Map<GroupDescriptor, Set<PatchedUsage>> getPatchedUsages(@NotNull final Map<GroupDescriptor, Set<UsageDescriptor>> allUsages, @NotNull SentUsagesPersistence usagesPersistence) { return getPatchedUsages(allUsages, usagesPersistence.getSentUsages()); } @NotNull public static Map<GroupDescriptor, Set<PatchedUsage>> getPatchedUsages(@NotNull final Map<GroupDescriptor, Set<UsageDescriptor>> allUsages, final Map<GroupDescriptor, Set<UsageDescriptor>> sentUsageMap) { Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages = mapToPatchedUsagesMap(allUsages); for (Map.Entry<GroupDescriptor, Set<UsageDescriptor>> sentUsageEntry : sentUsageMap.entrySet()) { final GroupDescriptor sentUsageGroupDescriptor = sentUsageEntry.getKey(); final Set<UsageDescriptor> sentUsages = sentUsageEntry.getValue(); for (UsageDescriptor sentUsage : sentUsages) { final PatchedUsage descriptor = findDescriptor(patchedUsages, Pair.create(sentUsageGroupDescriptor, sentUsage.getKey())); if (descriptor == null) { if (!patchedUsages.containsKey(sentUsageGroupDescriptor)) { patchedUsages.put(sentUsageGroupDescriptor, new LinkedHashSet<PatchedUsage>()); } patchedUsages.get(sentUsageGroupDescriptor).add(new PatchedUsage(sentUsage.getKey(), -sentUsage.getValue())); } else { descriptor.subValue(sentUsage.getValue()); } } } return packCollection(patchedUsages, new Condition<PatchedUsage>() { @Override public boolean value(PatchedUsage patchedUsage) { return patchedUsage.getDelta() != 0; } }); } private static Map<GroupDescriptor, Set<PatchedUsage>> mapToPatchedUsagesMap(Map<GroupDescriptor, Set<UsageDescriptor>> allUsages) { Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages = new LinkedHashMap<GroupDescriptor, Set<PatchedUsage>>(); for (Map.Entry<GroupDescriptor, Set<UsageDescriptor>> entry : allUsages.entrySet()) { patchedUsages.put(entry.getKey(), new HashSet<PatchedUsage>(ContainerUtil.map2Set(entry.getValue(), new Function<UsageDescriptor, PatchedUsage>() { @Override public PatchedUsage fun(UsageDescriptor usageDescriptor) { return new PatchedUsage(usageDescriptor); } }))); } return patchedUsages; } @NotNull private static Map<GroupDescriptor, Set<PatchedUsage>> packCollection(@NotNull Map<GroupDescriptor, Set<PatchedUsage>> patchedUsages, Condition<PatchedUsage> condition) { Map<GroupDescriptor, Set<PatchedUsage>> result = new LinkedHashMap<GroupDescriptor, Set<PatchedUsage>>(); for (GroupDescriptor descriptor : patchedUsages.keySet()) { final Set<PatchedUsage> usages = packCollection(patchedUsages.get(descriptor), condition); if (usages.size() > 0) { result.put(descriptor, usages); } } return result; } @NotNull private static <T> Set<T> packCollection(@NotNull Collection<T> set, @NotNull Condition<T> condition) { final Set<T> result = new LinkedHashSet<T>(); for (T t : set) { if (condition.value(t)) { result.add(t); } } return result; } @Nullable public static <T extends UsageDescriptor> T findDescriptor(@NotNull Map<GroupDescriptor, Set<T>> descriptors, @NotNull final Pair<GroupDescriptor, String> id) { final Set<T> usages = descriptors.get(id.getFirst()); if (usages == null) return null; return ContainerUtil.find(usages, new Condition<T>() { @Override public boolean value(T t) { return id.getSecond().equals(t.getKey()); } }); } @NotNull public static Map<GroupDescriptor, Set<UsageDescriptor>> getAllUsages(@Nullable Project project, @NotNull Set<String> disabledGroups) { Map<GroupDescriptor, Set<UsageDescriptor>> usageDescriptors = new LinkedHashMap<GroupDescriptor, Set<UsageDescriptor>>(); for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) { final GroupDescriptor groupDescriptor = usagesCollector.getGroupId(); if (!disabledGroups.contains(groupDescriptor.getId())) { try { final Set<UsageDescriptor> usages = usagesCollector.getUsages(project); usageDescriptors.put(groupDescriptor, usages); } catch (CollectUsagesException e) { LOG.info(e); } } } return usageDescriptors; } public static StatisticsService getStatisticsService() { return new RemotelyConfigurableStatisticsService(new StatisticsConnectionService(), new StatisticsHttpClientSender(), new StatisticsUploadAssistant()); } }