package org.infinispan.marshall.core; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Map; import java.util.Set; import org.infinispan.commons.CacheConfigurationException; import org.infinispan.commons.marshall.AdvancedExternalizer; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; final class ExternalExternalizers { private static final Log log = LogFactory.getLog(ExternalExternalizers.class); private ExternalExternalizers() { } static ClassToExternalizerMap load(GlobalConfiguration globalCfg) { ClassToExternalizerMap exts = new ClassToExternalizerMap(4, 0.375f); Map<Integer, AdvancedExternalizer<?>> cfgExts = globalCfg.serialization().advancedExternalizers(); for (Map.Entry<Integer, AdvancedExternalizer<?>> config : cfgExts.entrySet()) { AdvancedExternalizer ext = config.getValue(); // If no XML or programmatic config, id in annotation is used // as long as it's not default one (meaning, user did not set it). // If XML or programmatic config in use ignore @Marshalls annotation and use value in config. Integer id = ext.getId(); if (config.getKey() == null && id == null) throw new CacheConfigurationException(String.format( "No advanced externalizer identifier set for externalizer %s", ext.getClass().getName())); else if (config.getKey() != null) id = config.getKey(); checkForeignIdLimit(id, ext); Set<Class> subTypes = ext.getTypeClasses(); ForeignAdvancedExternalizer foreignExt = new ForeignAdvancedExternalizer(id, ext); for (Class<?> subType : subTypes) exts.put(subType, foreignExt); } return exts; } private static void checkForeignIdLimit(int id, AdvancedExternalizer<?> ext) { if (id < 0) throw log.foreignExternalizerUsingNegativeId(ext, id); } private static final class ForeignAdvancedExternalizer implements AdvancedExternalizer<Object> { final AdvancedExternalizer<Object> ext; final int id; private ForeignAdvancedExternalizer(int id, AdvancedExternalizer<Object> ext) { this.id = id; this.ext = ext; } @Override public Set<Class<?>> getTypeClasses() { return ext.getTypeClasses(); } @Override public Integer getId() { return id; } @Override public void writeObject(ObjectOutput output, Object object) throws IOException { ext.writeObject(output, object); } @Override public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException { return ext.readObject(input); } @Override public String toString() { // Each adapter is represented by the externalizer it delegates to, so just return the class name return ext.getClass().getName(); } } }