*/
package org.opendaylight.mdsal.binding.dom.codec.gen.impl;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
}
protected AbstractStreamWriterGenerator(final JavassistUtils utils) {
- this.javassist = Preconditions.checkNotNull(utils, "JavassistUtils instance is required.");
- this.serializeArguments = new CtClass[] {
- javassist.asCtClass(DataObjectSerializerRegistry.class),
- javassist.asCtClass(DataObject.class),
- javassist.asCtClass(BindingStreamEventWriter.class),
- };
- javassist.appendClassLoaderIfMissing(DataObjectSerializerPrototype.class.getClassLoader());
+ this.javassist = requireNonNull(utils, "JavassistUtils instance is required.");
+ synchronized (javassist) {
+ this.serializeArguments = new CtClass[] {
+ javassist.asCtClass(DataObjectSerializerRegistry.class),
+ javassist.asCtClass(DataObject.class),
+ javassist.asCtClass(BindingStreamEventWriter.class),
+ };
+ javassist.appendClassLoaderIfMissing(DataObjectSerializerPrototype.class.getClassLoader());
+ }
this.implementations = CacheBuilder.newBuilder().weakKeys().build(new SerializerImplementationLoader());
}
@Override
@SuppressWarnings("unchecked")
public DataObjectSerializerImplementation load(final Class<?> type) throws Exception {
- Preconditions.checkArgument(BindingReflections.isBindingClass(type));
- Preconditions.checkArgument(DataContainer.class.isAssignableFrom(type),
+ checkArgument(BindingReflections.isBindingClass(type));
+ checkArgument(DataContainer.class.isAssignableFrom(type),
"DataContainer is not assingnable from %s from classloader %s.", type, type.getClassLoader());
final String serializerName = getSerializerName(type);
// The prototype is not visible, so we need to take care of that
cls.setModifiers(Modifier.setPublic(cls.getModifiers()));
});
- } catch (final NotFoundException e) {
+ } catch (NotFoundException | CannotCompileException e) {
LOG.error("Failed to instatiate serializer {}", source, e);
throw new LinkageError("Unexpected instantation problem: serializer prototype not found", e);
}
*/
package org.opendaylight.mdsal.binding.generator.util;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.Map;
import java.util.WeakHashMap;
import javassist.LoaderClassPath;
import javassist.Modifier;
import javassist.NotFoundException;
+import javax.annotation.concurrent.GuardedBy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public final class JavassistUtils {
private static final Logger LOG = LoggerFactory.getLogger(JavassistUtils.class);
-
private static final Map<ClassPool, JavassistUtils> INSTANCES = new WeakHashMap<>();
+
private final Map<ClassLoader, ClassPath> loaderClassPaths = new WeakHashMap<>();
private final ClassPool classPool;
private JavassistUtils(final ClassPool pool) {
- classPool = Preconditions.checkNotNull(pool);
+ classPool = requireNonNull(pool);
}
/**
* @return shared utility instance for specified pool
*/
public static synchronized JavassistUtils forClassPool(final ClassPool pool) {
- JavassistUtils ret = INSTANCES.get(Preconditions.checkNotNull(pool));
+ JavassistUtils ret = INSTANCES.get(requireNonNull(pool));
if (ret == null) {
ret = new JavassistUtils(pool);
INSTANCES.put(pool, ret);
}
public void method(final CtClass it, final Class<?> returnType, final String name,
- final Collection<? extends Class<?>> parameters, final MethodGenerator function1) throws CannotCompileException {
+ final Collection<? extends Class<?>> parameters, final MethodGenerator function1)
+ throws CannotCompileException {
final CtClass[] pa = new CtClass[parameters.size()];
int i = 0;
it.addMethod(method);
}
- public void implementMethodsFrom(final CtClass target, final CtClass source, final MethodGenerator function1) throws CannotCompileException {
+ public void implementMethodsFrom(final CtClass target, final CtClass source, final MethodGenerator function1)
+ throws CannotCompileException {
for (CtMethod method : source.getMethods()) {
if (method.getDeclaringClass() == source) {
CtMethod redeclaredMethod = new CtMethod(method, target, null);
return target;
}
- public CtClass createClass(final String fqn, final CtClass superInterface, final ClassGenerator cls) throws CannotCompileException {
+ public CtClass createClass(final String fqn, final CtClass superInterface, final ClassGenerator cls)
+ throws CannotCompileException {
CtClass target = classPool.makeClass(fqn);
implementsType(target, superInterface);
cls.process(target);
}
/**
- * Instantiate a new class based on a prototype. The class is set to automatically
- * prune.
+ * Instantiate a new class based on a prototype. The class is set to automatically prune. The {@code customizer}
+ * is guaranteed to run with this object locked.
*
* @param prototype Prototype class fully qualified name
* @param fqn Target class fully qualified name
* @throws NotFoundException when the prototype class is not found
*/
@Beta
- public synchronized CtClass instantiatePrototype(final String prototype, final String fqn, final ClassCustomizer customizer) throws NotFoundException {
+ public synchronized CtClass instantiatePrototype(final String prototype, final String fqn,
+ final ClassCustomizer customizer) throws CannotCompileException, NotFoundException {
final CtClass result = classPool.getAndRename(prototype, fqn);
try {
customizer.customizeClass(result);
+ } catch (CannotCompileException | NotFoundException e) {
+ result.detach();
+ throw e;
} catch (Exception e) {
LOG.warn("Failed to customize {} from prototype {}", fqn, prototype, e);
result.detach();
- throw new IllegalStateException(String.format("Failed to instantiate prototype %s as %s", prototype, fqn), e);
+ throw new IllegalStateException(String.format("Failed to instantiate prototype %s as %s", prototype, fqn),
+ e);
}
result.stopPruning(false);
return result;
}
- public void implementsType(final CtClass it, final CtClass supertype) {
- Preconditions.checkArgument(supertype.isInterface(), "Supertype must be interface");
+ private static void implementsType(final CtClass it, final CtClass supertype) {
+ checkArgument(supertype.isInterface(), "Supertype %s is not an interface", supertype);
it.addInterface(supertype);
}
+ @GuardedBy("this")
public CtClass asCtClass(final Class<?> class1) {
return get(this.classPool, class1);
}
import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableList;
+import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
+import javassist.NotFoundException;
import javassist.bytecode.AccessFlag;
import org.junit.Test;
-import org.opendaylight.mdsal.binding.generator.util.ClassCustomizer;
-import org.opendaylight.mdsal.binding.generator.util.ClassGenerator;
-import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
-import org.opendaylight.mdsal.binding.generator.util.MethodGenerator;
public class JavassistUtilsTest {
@Test
- public void forClassPool() throws Exception {
+ public void forClassPool() throws CannotCompileException, NotFoundException {
final JavassistUtils javassistUtils = JavassistUtils.forClassPool(ClassPool.getDefault());
final ClassGenerator classGenerator = mock(ClassGenerator.class);
doNothing().when(classGenerator).process(any());