*/
package org.opendaylight.mdsal.binding.dom.codec.gen.impl;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
+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;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Map.Entry;
import javassist.CannotCompileException;
import javassist.CtClass;
import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.util.Types;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+@Deprecated
abstract class AbstractStreamWriterGenerator extends AbstractGenerator implements DataObjectSerializerGenerator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractStreamWriterGenerator.class);
protected static final String SERIALIZE_METHOD_NAME = "serialize";
protected static final AugmentableDispatchSerializer AUGMENTABLE = new AugmentableDispatchSerializer();
- private static final Field FIELD_MODIFIERS;
+ private static final Field FIELD_MODIFIERS = getModifiersField();
private final LoadingCache<Class<?>, DataObjectSerializerImplementation> implementations;
private final CtClass[] serializeArguments;
private final JavassistUtils javassist;
private BindingRuntimeContext context;
- static {
+ private static Field getModifiersField() {
/*
* Cache reflection access to field modifiers field. We need this to set
* fix the static declared fields to final once we initialize them. If we
* cannot get access, that's fine, too.
*/
- Field field = null;
+ final Field field;
try {
field = Field.class.getDeclaredField("modifiers");
- field.setAccessible(true);
} catch (NoSuchFieldException | SecurityException e) {
- LOG.warn("Could not get Field modifiers field, serializers run at decreased efficiency", e);
+ LOG.warn("Could not get modifiers field, serializers run at decreased efficiency", e);
+ return null;
+ }
+
+ try {
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ field.setAccessible(true);
+ return null;
+ });
+ } catch (SecurityException e) {
+ LOG.warn("Could not get access to modifiers field, serializers run at decreased efficiency", e);
+ return null;
}
- FIELD_MODIFIERS = field;
+ return field;
}
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.implementations = CacheBuilder.newBuilder().weakKeys().build(new SerializerImplementationLoader());
+ 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()
+ .removalListener(notification -> LOG.debug("onRemoval: cause={}, wasEvicted={}",
+ notification.getCause(), notification.wasEvicted()))
+ .weakKeys().build(new SerializerImplementationLoader());
+ LOG.debug("AbstractStreamWriterGenerator constructor, new instance: {}", this);
}
@Override
@Override
public final void onBindingRuntimeContextUpdated(final BindingRuntimeContext runtime) {
this.context = runtime;
+ LOG.debug("onBindingRuntimeContextUpdated() : {}", runtime);
}
@Override
protected final String loadSerializerFor(final Class<?> cls) {
- return implementations.getUnchecked(cls).getClass().getName();
+ return getSerializer(cls).getClass().getName();
}
private final class 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);
final DataObjectSerializerImplementation obj =
(DataObjectSerializerImplementation) cls.getDeclaredMethod(GETINSTANCE_METHOD_NAME).invoke(null);
- LOG.debug("Loaded serializer {} for class {}", obj, type);
+ LOG.trace("Loaded serializer {} for class {}", obj, type);
return obj;
}
final String serializerName) throws CannotCompileException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException,
NoSuchFieldException {
+ LOG.debug("generateSerializer() due to Cache miss: typeName={}, typeClassLoader={}, serializerName={}",
+ type.getTypeName(), type.getClassLoader(), serializerName);
final DataObjectSerializerSource source = generateEmitterSource(type, serializerName);
final CtClass poolClass = generateEmitter0(type, source, serializerName);
- @SuppressWarnings("unchecked")
- final Class<? extends DataObjectSerializerImplementation> cls = poolClass.toClass(type.getClassLoader(),
- type.getProtectionDomain());
+ final Class<? extends DataObjectSerializerImplementation> cls =
+ poolClass.toClass(type.getClassLoader(), type.getProtectionDomain())
+ .asSubclass(DataObjectSerializerImplementation.class);
/*
* Due to OSGi class loader rules we cannot initialize the fields during
* care of this before calling instantiatePrototype(), as that will call our customizer with the lock held,
* hence any code generation will end up being blocked on the javassist lock.
*/
- final String body = ClassLoaderUtils.withClassLoader(type.getClassLoader(),
- (Supplier<String>) () -> source.getSerializerBody().toString());
+ final String body = ClassLoaderUtils.getWithClassLoader(type.getClassLoader(), source::getSerializerBody)
+ .toString();
try {
product = javassist.instantiatePrototype(DataObjectSerializerPrototype.class.getName(), serializerName,
// 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);
}