+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
package org.opendaylight.yangtools.sal.binding.generator.impl;
import java.lang.ref.WeakReference;
public class LazyGeneratedCodecRegistry implements //
CodecRegistry, //
- SchemaServiceListener, //
+ SchemaContextListener, //
GeneratorListener {
private final static Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
private TransformerGenerator generator;
// Concrete class to codecs
- private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, AugmentationCodec<?>> augmentationCodecs = new WeakHashMap<>();
- private static final Map<Class<?>, QName> identityQNames = new WeakHashMap<>();
+ private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, DataContainerCodec<?>>());
+ private static final Map<Class<?>, IdentifierCodec<?>> identifierCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, IdentifierCodec<?>>());
+ private static final Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, ChoiceCodecImpl<?>>());
+ private static final Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, ChoiceCaseCodecImpl<?>>());
+ private static final Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, AugmentableCompositeCodec>());
+ private static final Map<Class<?>, AugmentationCodec<?>> augmentationCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, AugmentationCodec<?>>());
+ private static final Map<Class<?>, QName> identityQNames = Collections
+ .synchronizedMap(new WeakHashMap<Class<?>, QName>());
private static final Map<QName, Type> qnamesToIdentityMap = new ConcurrentHashMap<>();
/** Binding type to encountered classes mapping **/
@SuppressWarnings("rawtypes")
private static final Map<List<QName>, Type> pathToInstantiatedType = new ConcurrentHashMap<>();
private static final Map<Type, QName> typeToQname = new ConcurrentHashMap<>();
+ private final SchemaLock lock;
+
private SchemaContext currentSchema;
+ private final GeneratedClassLoadingStrategy classLoadingStrategy;
+
+ LazyGeneratedCodecRegistry(SchemaLock lock, GeneratedClassLoadingStrategy identityClassLoadingStrategy) {
+ this.lock = Preconditions.checkNotNull(lock);
+ this.classLoadingStrategy = identityClassLoadingStrategy;
+ }
+
+ public SchemaLock getLock() {
+ return lock;
+ }
+
public TransformerGenerator getGenerator() {
return generator;
}
codec = potentialCodec;
} else
try {
+ lock.waitForSchema(object);
Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentRawCodec = generator
.augmentationTransformerFor(object);
BindingCodec<Map<QName, Object>, Object> rawCodec = augmentRawCodec.newInstance();
codec = new AugmentationCodecWrapper<T>(rawCodec);
- augmentationCodecs.put(augmentRawCodec, codec);
+ augmentationCodecs.put(object, codec);
} catch (InstantiationException e) {
LOG.error("Can not instantiate raw augmentation codec {}", object.getSimpleName(), e);
} catch (IllegalAccessException e) {
- LOG.debug("BUG: Constructor for {} is not accessible.", object.getSimpleName(), e);
+ LOG.debug(
+ "Run-time consistency issue: constructor {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.",
+ object.getSimpleName(), e);
}
Class<? extends Augmentable<?>> objectSupertype = getAugmentableArgumentFrom(object);
if (objectSupertype != null) {
@Override
public QName getQNameForAugmentation(Class<?> cls) {
Preconditions.checkArgument(Augmentation.class.isAssignableFrom(cls));
- return getCodecForAugmentation((Class<? extends Augmentation>)cls).getAugmentationQName();
+ return getCodecForAugmentation((Class<? extends Augmentation>) cls).getAugmentationQName();
}
private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
}
@Override
- public IdentitityCodec<?> getIdentityCodec() {
+ public IdentityCodec<?> getIdentityCodec() {
return identityRefCodec;
}
@Override
- public <T extends BaseIdentity> IdentitityCodec<T> getCodecForIdentity(Class<T> codec) {
+ public <T extends BaseIdentity> IdentityCodec<T> getCodecForIdentity(Class<T> codec) {
bindingClassEncountered(codec);
return identityRefCodec;
}
ConcreteType typeref = Types.typeForClass(caseClass);
ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
- Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
- Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
+ Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s",
+ caseClass.getName());
+ Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s",
+ caseClass.getName());
@SuppressWarnings("unchecked")
Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
BindingCodec newInstance = newInstanceOf(newCodec);
ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
if (node == null) {
- LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
+ LOG.warn("Failed to find YANG SchemaNode for {}, with path {} was not found in context.",
typeref.getFullyQualifiedName(), caseNode.getKey());
@SuppressWarnings("rawtypes")
ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
if (partialCodec.getSchema() == null) {
partialCodec.setSchema(caseNode);
}
-
- Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
- if (caseClass != null) {
+ try {
+ Class<?> caseClass = classLoadingStrategy.loadClass(type.getFullyQualifiedName());
getCaseCodecFor(caseClass);
+ } catch (ClassNotFoundException e) {
+ LOG.trace("Could not proactivelly create case codec for {}", type, e);
}
}
}
private ChoiceCaseNode schema;
public void setSchema(ChoiceCaseNode caseNode) {
- this.schema = schema;
this.schema = caseNode;
validNames = new HashSet<>();
validQNames = new HashSet<>();
private final BindingCodec<Map<QName, Object>, Object> delegate;
@SuppressWarnings("rawtypes")
- private final Map<Class, ChoiceCaseCodecImpl<?>> cases = new WeakHashMap<>();
+ private final Map<Class, ChoiceCaseCodecImpl<?>> cases = Collections
+ .synchronizedMap(new WeakHashMap<Class, ChoiceCaseCodecImpl<?>>());
private final CaseCompositeNodeMapFacade CompositeToCase;
}
/**
- * This map is used as only facade for {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
+ * This map is used as only facade for
+ * {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
* classloaders to retrieve codec dynamicly based on provided key.
*
* @param <T>
private final Class augmentableType;
- Map<Class, AugmentationCodec<?>> localAugmentationCodecs = new WeakHashMap<>();
+ Map<Class, AugmentationCodec<?>> localAugmentationCodecs = Collections
+ .synchronizedMap(new WeakHashMap<Class, AugmentationCodec<?>>());
public AugmentableCompositeCodec(Class type) {
Preconditions.checkArgument(Augmentable.class.isAssignableFrom(type));
}
}
- private class IdentityCompositeCodec implements IdentitityCodec {
+ private class IdentityCompositeCodec implements IdentityCodec {
@Override
public Object deserialize(Object input) {
ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
WeakReference<Class> softref = typeToClass.get(typeref);
if (softref == null) {
+
+ try {
+ Class<?> cls = classLoadingStrategy.loadClass(typeref.getFullyQualifiedName());
+ if (cls != null) {
+ serialize(cls);
+ return cls;
+ }
+ } catch (Exception e) {
+ LOG.warn("Identity {} was not deserialized, because of missing class {}", input,
+ typeref.getFullyQualifiedName());
+ }
return null;
}
return softref.get();