Skip to content

Commit

Permalink
better Listener API
Browse files Browse the repository at this point in the history
- the API now has a single register() method
- listeners registering for events will also be notified for event
subtypes
- added tests for the new API
- added new events during minimisation to improve status updates in the
plugins
- removed some jar-extraction related leftovers
  • Loading branch information
ayld committed Jul 11, 2016
1 parent a3cbab3 commit 2a5d968
Show file tree
Hide file tree
Showing 19 changed files with 270 additions and 145 deletions.
47 changes: 36 additions & 11 deletions src/main/java/org/codarama/diet/api/ListenerRegistrar.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,51 @@
package org.codarama.diet.api;

import com.google.common.annotations.Beta;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.codarama.diet.api.reporting.listener.EventListener;
import org.codarama.diet.event.model.ComponentEvent;
import org.codarama.diet.util.Components;

import com.google.common.eventbus.EventBus;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

@Beta
public final class ListenerRegistrar {

private final Object[] listeners;

private ListenerRegistrar(Object[] listeners) {
this.listeners = listeners;
private ListenerRegistrar() {
}

public static ListenerRegistrar listeners(Object... listeners) {
return new ListenerRegistrar(listeners);
public static <E extends ComponentEvent> void register(EventListener<E> listener) {
Components.EVENT_BUS.<EventBus>getInstance().register(new GuavaListener<E>(listener));
}

public void register() {
for (Object l : listeners) {
Components.EVENT_BUS.<EventBus>getInstance().register(l);

private static class GuavaListener<E extends ComponentEvent> {
private final EventListener<E> listener;

private GuavaListener(EventListener listener) {
this.listener = listener;
}

@Subscribe
private void on(E event) {
final Class listenerGenericType = getListenerGenericType();
final Class eventGenericType = event.getClass();

final boolean listenerTypeIsSuperclassOfEventType = listenerGenericType.isAssignableFrom(eventGenericType);
if (listenerTypeIsSuperclassOfEventType) {
listener.on(event);
}
}

private Class getListenerGenericType() {
final ParameterizedType listenerGenericType = (ParameterizedType) listener.getClass().getGenericInterfaces()[0];
final String listenerGenericTypeName = listenerGenericType.getActualTypeArguments()[0].getTypeName();
try {
return Class.forName(listenerGenericTypeName);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Unknown generic type for listener: " + listener.getClass());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.codarama.diet.api.reporting.listener;

import org.codarama.diet.event.model.ComponentEvent;

/**
* Implementers of the interface can subscribe to be notified for events during minimization.
*
* @see org.codarama.diet.api.ListenerRegistrar
* @see org.codarama.diet.event.model.ComponentEvent
*
* Created by Ayld on 7/10/16.
*/
public interface EventListener<E extends ComponentEvent> {

void on(E event);
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package org.codarama.diet.dependency.resolver.impl;

import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.bcel.classfile.*;
import org.codarama.diet.component.ListenableComponent;
import org.codarama.diet.dependency.resolver.DependencyResolver;
import org.codarama.diet.event.model.ClassDependencyResolutionEndEvent;
import org.codarama.diet.event.model.ClassDependencyResolutionStartEvent;
import org.codarama.diet.model.ClassName;
import org.codarama.diet.model.ClassStream;
import org.codarama.diet.util.Java;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
* Resolves the dependencies of {@link org.codarama.diet.model.ClassStream} which is essentially a byte stream.
* The model class validates whether said stream is actually a compiled Java class.
*
* Created by ayld on 6/21/2015.
*/
public class ClassStreamDependencyResolver implements DependencyResolver<ClassStream> {
public class ClassStreamDependencyResolver extends ListenableComponent implements DependencyResolver<ClassStream> {

private static final String BINARY_ARRAY_ID_PREFIX = "[";
private static final String BINARY_TYPE_PREFIX = "L";
Expand All @@ -29,14 +34,26 @@ public class ClassStreamDependencyResolver implements DependencyResolver<ClassSt
@Override
public Set<ClassName> resolve(ClassStream classStream) throws IOException {

// TODO AOP for the stopwatch and the events
final Stopwatch stopwatch = Stopwatch.createStarted();
eventBus.post(new ClassDependencyResolutionStartEvent("Resolving: " + classStream.toString(), this.getClass()));

final JavaClass javaClass = new ClassParser(classStream.content(), classStream.name().toString()).parse();

final DependencyVisitor dependencyVisitor = new DependencyVisitor(javaClass);
final DescendingVisitor classWalker = new DescendingVisitor(javaClass, dependencyVisitor);

classWalker.visit();

return dependencyVisitor.getFoundDependencies();
final Set<ClassName> result = dependencyVisitor.getFoundDependencies();

stopwatch.stop();
eventBus.post(
new ClassDependencyResolutionEndEvent("Class dependency resolution took: "
+ stopwatch.elapsed(TimeUnit.SECONDS), this.getClass())
);

return result;
}

@Override
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.codarama.diet.event.model;

import org.codarama.diet.component.ListenableComponent;

/**
* Created by Ayld on 7/11/16.
*/
public class MinimizationEndEvent extends MinimizationEvent{
public MinimizationEndEvent(String message, Class<? extends ListenableComponent> by) {
super(message, by);
}
}
13 changes: 13 additions & 0 deletions src/main/java/org/codarama/diet/event/model/MinimizationEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.codarama.diet.event.model;

import org.codarama.diet.component.ListenableComponent;

/**
* Created by Ayld on 7/11/16.
*/
public class MinimizationEvent extends ComponentEvent {

public MinimizationEvent(String message, Class<? extends ListenableComponent> by) {
super(message, by);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.codarama.diet.event.model;

import org.codarama.diet.component.ListenableComponent;

/**
* Created by Ayld on 7/11/16.
*/
public class MinimizationStartEvent extends MinimizationEvent {
public MinimizationStartEvent(String message, Class<? extends ListenableComponent> by) {
super(message, by);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package org.codarama.diet.minimization.impl;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Sets;
import org.codarama.diet.component.ListenableComponent;
import org.codarama.diet.dependency.resolver.DependencyResolver;
import org.codarama.diet.event.model.MinimizationEndEvent;
import org.codarama.diet.event.model.MinimizationEvent;
import org.codarama.diet.event.model.MinimizationStartEvent;
import org.codarama.diet.index.LibraryIndex;
import org.codarama.diet.minimization.MinimizationStrategy;
import org.codarama.diet.model.ClassName;
Expand All @@ -13,6 +18,7 @@

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarFile;

/**
Expand All @@ -21,7 +27,7 @@
*
* Created by ayld on 20.06.15.
*/
public class IndexedMinimizationStrategy implements MinimizationStrategy<SourceFile, JarFile, ClassStream>{
public class IndexedMinimizationStrategy extends ListenableComponent implements MinimizationStrategy<SourceFile, JarFile, ClassStream>{

private static final Logger LOG = LoggerFactory.getLogger(IndexedMinimizationStrategy.class);

Expand All @@ -32,22 +38,60 @@ public class IndexedMinimizationStrategy implements MinimizationStrategy<SourceF
@Override
public Set<ClassStream> minimize(Set<SourceFile> sources, Set<JarFile> libraries) throws IOException {
final Set<ClassName> sourceDependencies = sourceDependencyResolver.resolve(sources);

eventBus.post(
new MinimizationStartEvent("Minimization starting on: " + sources.size() + " sources, " + libraries.size() + " libs",
this.getClass())
);
final Stopwatch stopwatch = Stopwatch.createStarted();
eventBus.post(
new MinimizationEvent("Starting indexing",
this.getClass())
);

index.index(libraries);

eventBus.post(
new MinimizationEvent("Indexing done in: " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds",
this.getClass())
);
eventBus.post(
new MinimizationEvent("Index querying starting.",
this.getClass())
);

final Set<ClassStream> result = Sets.newHashSet();
final Set<ClassName> resultNames = Sets.newHashSet();
for (ClassName sourceDep : sourceDependencies) {
resolveAndAddAllFromIndex(sourceDep, result, resultNames);
}

stopwatch.stop();
eventBus.post(
new MinimizationEndEvent("Minimization done in: " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds",
this.getClass())
);

return result;
}

private void resolveAndAddAllFromIndex(ClassName depName, Set<ClassStream> deps, Set<ClassName> depNames) {
if (!depNames.contains(depName) && index.contains(depName)) {

final Stopwatch stopwatch = Stopwatch.createStarted();
eventBus.post(
new MinimizationEvent("Index.get called for: " + depName,
this.getClass())
);

final ClassStream dep = index.get(depName);

stopwatch.stop();
eventBus.post(
new MinimizationEvent("Index.get done in: " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " millis",
this.getClass())
);

deps.add(dep);
depNames.add(depName);

Expand Down
20 changes: 1 addition & 19 deletions src/main/resources/META-INF/components/concurrent.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,14 @@

profile="concurrent">

<bean id="jarExploder" class="org.codarama.diet.bundle.impl.CuncurrentManualJarExploder" parent="listenableComponent">
<property name="workDir" value="#{workDir}"/>
<property name="threadPool">
<bean class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg value="${cuncurrent.jar.extration.thread.pool.size}" type="int"/>
</bean>
</property>
</bean>

<bean id="explicitJarExploder" class="org.codarama.diet.bundle.impl.CuncurrentManualJarExploder" parent="listenableComponent">
<property name="workDir" value="#{mandatoryWorkDir}"/>
<property name="threadPool">
<bean class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg value="${cuncurrent.jar.extration.thread.pool.size}" type="int"/>
</bean>
</property>
</bean>

<bean id="classDependencyResolver" class="org.codarama.diet.dependency.resolver.impl.ConcurrentClassFileDependencyResolver" parent="listenableComponent">
<property name="threadPool">
<bean class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg value="${cuncurrent.class.resolver.thread.pool.size}" type="int"/>
</bean>
</property>
<property name="classStreamResolver">
<bean class="org.codarama.diet.dependency.resolver.impl.ClassStreamDependencyResolver"/>
<bean class="org.codarama.diet.dependency.resolver.impl.ClassStreamDependencyResolver" parent="listenableComponent"/>
</property>
</bean>

Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/META-INF/components/service.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<property name="classStreamResolver" ref="classStreamResolver"/>
</bean>

<bean id="classStreamResolver" class="org.codarama.diet.dependency.resolver.impl.ClassStreamDependencyResolver"/>
<bean id="classStreamResolver" class="org.codarama.diet.dependency.resolver.impl.ClassStreamDependencyResolver" parent="listenableComponent"/>

<bean id="sourceDependencyResolver" class="org.codarama.diet.dependency.resolver.impl.ManualParseSourceDependencyResolver" parent="listenableComponent"/>

Expand All @@ -35,7 +35,7 @@
</property>
</bean>

<bean id="indexedMinimizationStrategy" class="org.codarama.diet.minimization.impl.IndexedMinimizationStrategy">
<bean id="indexedMinimizationStrategy" class="org.codarama.diet.minimization.impl.IndexedMinimizationStrategy" parent="listenableComponent">
<property name="index" ref="modeShapeIndex"/>
<property name="sourceDependencyResolver" ref="sourceDependencyResolver"/>
<property name="classDependencyResolver" ref="classStreamResolver"/>
Expand Down
10 changes: 8 additions & 2 deletions src/main/resources/META-INF/context.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@
<constructor-arg value="#{workDir.concat(defaultOutJarName)}" type="java.lang.Object"/>
</bean>

<bean id="statusUpdateEventBus" class="com.google.common.eventbus.EventBus"/>

<bean id="statusUpdateEventBus" class="com.google.common.eventbus.AsyncEventBus">
<constructor-arg ref="eventBusExecutor"/>
</bean>

<bean id="eventBusExecutor" class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg value="1"/>
</bean>

<bean id="listenableComponent" class="org.codarama.diet.component.ListenableComponent" abstract="true">
<property name="eventBus" ref="statusUpdateEventBus"/>
</bean>
Expand Down
Loading

0 comments on commit 2a5d968

Please sign in to comment.