/* * Copyright 2016-present Facebook, 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.facebook.buck.jvm.java; import com.facebook.buck.event.BuckEventBus; import com.facebook.buck.event.BuckTracingEventBusBridge; import com.facebook.buck.event.ConsoleEvent; import com.facebook.buck.event.EventKey; import com.facebook.buck.event.ThrowableConsoleEvent; import com.facebook.buck.jvm.java.tracing.JavacPhaseEvent; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.Pair; import com.facebook.infer.annotation.Assertions; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.annotation.Nonnull; public class JavacEventSinkToBuckEventBusBridge implements JavacEventSink { private final BuckEventBus eventBus; private final LoadingCache<BuildTarget, BuckTracingEventBusBridge> buckTracingBridgeCache = CacheBuilder.newBuilder() .build( new CacheLoader<BuildTarget, BuckTracingEventBusBridge>() { @Override public BuckTracingEventBusBridge load(@Nonnull BuildTarget target) throws Exception { return new BuckTracingEventBusBridge(eventBus, target); } }); private final Map<Pair<BuildTarget, JavacPhaseEvent.Phase>, JavacPhaseEvent.Started> currentJavacPhaseEvents = new ConcurrentHashMap<>(); private final Map<String, EventKey> startedAnnotationProcessingEvents = new ConcurrentHashMap<>(); public JavacEventSinkToBuckEventBusBridge(BuckEventBus eventBus) { this.eventBus = eventBus; } @Override public void reportThrowable(Throwable throwable, String message, Object... args) { eventBus.post(ThrowableConsoleEvent.create(throwable, message, args)); } @Override public void reportEvent(Level level, String message, Object... args) { eventBus.post(ConsoleEvent.create(level, message, args)); } private BuckTracingEventBusBridge getBuckTracingEventBusBridgeForBuildTarget( BuildTarget buildTarget) { try { return buckTracingBridgeCache.get(buildTarget); } catch (ExecutionException e) { throw new RuntimeException(e); } } @Override public void reportCompilerPluginStarted( BuildTarget buildTarget, String pluginName, String durationName, ImmutableMap<String, String> args) { getBuckTracingEventBusBridgeForBuildTarget(buildTarget).begin(pluginName, durationName, args); } @Override public void reportCompilerPluginFinished( BuildTarget buildTarget, ImmutableMap<String, String> args) { getBuckTracingEventBusBridgeForBuildTarget(buildTarget).end(args); } @Override public void reportJavacPhaseStarted( BuildTarget buildTarget, String phaseAsString, ImmutableMap<String, String> args) { JavacPhaseEvent.Phase phase = JavacPhaseEvent.Phase.fromString(phaseAsString); JavacPhaseEvent.Started startedEvent = JavacPhaseEvent.started(buildTarget, phase, args); Pair<BuildTarget, JavacPhaseEvent.Phase> key = new Pair<>(buildTarget, phase); Assertions.assertCondition(currentJavacPhaseEvents.get(key) == null); currentJavacPhaseEvents.put(key, startedEvent); eventBus.post(startedEvent); } @Override public void reportJavacPhaseFinished( BuildTarget buildTarget, String phaseAsString, ImmutableMap<String, String> args) { Pair<BuildTarget, JavacPhaseEvent.Phase> key = new Pair<>(buildTarget, JavacPhaseEvent.Phase.fromString(phaseAsString)); JavacPhaseEvent.Finished finishedEvent = JavacPhaseEvent.finished(Assertions.assertNotNull(currentJavacPhaseEvents.get(key)), args); currentJavacPhaseEvents.remove(key); eventBus.post(finishedEvent); } @Override public void reportAnnotationProcessingEventStarted( BuildTarget buildTarget, String annotationProcessorName, String operationAsString, int round, boolean isLastRound) { AnnotationProcessingEvent.Started started = AnnotationProcessingEvent.started( buildTarget, annotationProcessorName, AnnotationProcessingEvent.Operation.valueOf(operationAsString), round, isLastRound); startedAnnotationProcessingEvents.put( getKeyForAnnotationProcessingEvent( buildTarget, annotationProcessorName, operationAsString, round, isLastRound), started.getEventKey()); eventBus.post(started); } @Override public void reportAnnotationProcessingEventFinished( BuildTarget buildTarget, String annotationProcessorName, String operationAsString, int round, boolean isLastRound) { EventKey startedEventKey = startedAnnotationProcessingEvents.get( getKeyForAnnotationProcessingEvent( buildTarget, annotationProcessorName, operationAsString, round, isLastRound)); AnnotationProcessingEvent.Finished finished = new AnnotationProcessingEvent.Finished( Preconditions.checkNotNull(startedEventKey), buildTarget, annotationProcessorName, AnnotationProcessingEvent.Operation.valueOf(operationAsString), round, isLastRound); eventBus.post(finished); } @Override public BuckEventBus getEventBus() { return eventBus; } private String getKeyForAnnotationProcessingEvent( BuildTarget buildTarget, String annotationProcessorName, String operationAsString, int round, boolean isLastRound) { return Joiner.on(":") .join( buildTarget.toString(), annotationProcessorName, operationAsString, round, isLastRound); } }