package fr.adrienbrault.idea.symfony2plugin.profiler; import com.intellij.util.containers.ContainerUtil; import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalDefaultDataCollector; import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalMailCollector; import fr.adrienbrault.idea.symfony2plugin.profiler.dict.LocalProfilerRequest; import fr.adrienbrault.idea.symfony2plugin.profiler.dict.ProfilerRequestInterface; import fr.adrienbrault.idea.symfony2plugin.profiler.reader.ReverseFileLineReader; import fr.adrienbrault.idea.symfony2plugin.profiler.utils.ProfilerUtil; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class LocalProfilerIndex implements ProfilerIndexInterface { @NotNull private File file; @Nullable private String baseUrl; public LocalProfilerIndex(@NotNull File file) { this.file = file; } public LocalProfilerIndex(@NotNull File file, @Nullable String baseUrl) { this.file = file; this.baseUrl = baseUrl; } @NotNull public List<ProfilerRequestInterface> getRequests() { List<String> lines = new ArrayList<>(); try { // empty line and end of line need +1 ContainerUtil.addAll(lines, new ReverseFileLineReader(this.file, "UTF-8", 11).readLines()); } catch (IOException ignored) { } Collection<Callable<ProfilerRequestInterface>> callable = new ArrayList<>(); // build thread callable collection lines.stream().filter(StringUtils::isNotBlank).forEachOrdered(line -> { // we need at least this information for a valid line: // "18e6b8,127.0.0.1,GET,http://127.0.0.1:8000/foobar" String[] split = line.split(","); if (split.length <= 4) { return; } callable.add(new MyProfilerRequestBuilderCallable(split)); }); return ProfilerUtil.getProfilerRequestCollectorDecorated(callable, 15); } @Nullable @Override public String getUrlForRequest(@NotNull ProfilerRequestInterface request) { if(this.baseUrl != null) { return this.baseUrl + "/" + StringUtils.stripStart(request.getProfilerUrl(), "/"); } return ProfilerUtil.getBaseProfilerUrlFromRequest(request.getProfilerUrl()); } @NotNull private String getPath(@NotNull String hash) { String[] hashSplit = hash.split("(?<=\\G.{2})"); return hashSplit[2] + "/" + hashSplit[1] + "/" + hash; } @Nullable private File getFile(@NotNull String hash) { String path = this.getPath(hash); File file = new File(this.file.getParentFile().getAbsolutePath() + "/" + path); if(!file.exists()) { return null; } return file; } @Nullable private String getContentForHash(@NotNull String hash) { File file = this.getFile(hash); if(file == null) { return null; } StringBuilder content = new StringBuilder(); try { BufferedReader in = new BufferedReader(new FileReader(file)); String str; while ((str = in.readLine()) != null) { content.append(str); } in.close(); } catch (IOException ignored) { } return content.toString(); } private class MyProfilerRequestBuilderCallable implements Callable<ProfilerRequestInterface> { private final String[] split; MyProfilerRequestBuilderCallable(String[] split) { this.split = split; } @Override public ProfilerRequestInterface call() throws Exception { String content = getContentForHash(split[0]); if(content == null) { return new LocalProfilerRequest(split); } return new LocalProfilerRequest( split, new LocalDefaultDataCollector(content), new LocalMailCollector(content) ); } } }