org.nustaq.serialization.FSTClazzNameRegistry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fst Show documentation
Show all versions of fst Show documentation
A fast java serialization drop in-replacement and some serialization based utils such as Structs and OffHeap Memory.
/*
* Copyright 2014 Ruediger Moeller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nustaq.serialization;
import org.nustaq.serialization.util.FSTIdentity2IdMap;
import org.nustaq.serialization.util.FSTObject2IntMap;
import org.nustaq.serialization.util.FSTUtil;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Created with IntelliJ IDEA.
* User: ruedi
* Date: 10.11.12
* Time: 00:34
*
* maps classnames => id and vice versa.
*
* FSTConfiguration holds a parent containing default mappings (e.g. created by
* registerClass ). A stream instance then creates a temporary instance to record/id encode
* classes dynamically during serialization. This way a class name is only written once per
* object graph.
*
* This class is thread safe,
*
*/
public class FSTClazzNameRegistry {
public static final int LOWEST_CLZ_ID = 3;
public static final int FIRST_USER_CLZ_ID = 1000;
FSTIdentity2IdMap clzToId;
FSTClazzInfo idToClz[];
FSTClazzNameRegistry parent;
int classIdCount = LOWEST_CLZ_ID;
public FSTClazzNameRegistry(FSTClazzNameRegistry par) {
parent = par;
if ( parent != null ) {
classIdCount = Math.max(FIRST_USER_CLZ_ID,parent.classIdCount+1);
clzToId = new FSTIdentity2IdMap(13);
idToClz = new FSTClazzInfo[31];
} else {
clzToId = new FSTIdentity2IdMap(FSTObject2IntMap.adjustSize(400));
idToClz = new FSTClazzInfo[200];
}
}
public void clear() {
if ( clzToId.size() > 0 ) {
clzToId.clear();
//idToClz.clear();
}
classIdCount = LOWEST_CLZ_ID;
if ( parent != null ) {
classIdCount = Math.max(FIRST_USER_CLZ_ID,parent.classIdCount+1);
}
}
// for read => always increase handle (wg. replaceObject)
public void registerClass(Class c,FSTConfiguration conf) {
if ( getIdFromClazz(c) != Integer.MIN_VALUE ) {
return;
}
registerClassNoLookup(c,null,conf);
}
private void registerClassNoLookup(Class c,FSTClazzInfo cli, FSTConfiguration conf) {
addClassMapping(c, classIdCount++,cli,conf);
}
public void registerClass( Class c, int code, FSTConfiguration conf) {
if ( getIdFromClazz(c) != Integer.MIN_VALUE ) {
return;
}
addClassMapping(c, code, null,conf);
}
protected void addClassMapping( Class c, int id, FSTClazzInfo clInfo, FSTConfiguration conf ) {
clzToId.put(c, id);
if (clInfo==null)
clInfo = conf.getCLInfoRegistry().getCLInfo(c, conf);
if (idToClz.length<=id)
{
final FSTClazzInfo[] tmp = new FSTClazzInfo[id + 100];
System.arraycopy(idToClz,0,tmp,0,idToClz.length);
idToClz = tmp;
}
idToClz[id] = clInfo;
if ( parent == null ) {
clInfo.setClzId(id);
}
}
public int getIdFromClazz(Class c) {
int res = Integer.MIN_VALUE;
if ( parent != null ) {
res = parent.getIdFromClazz(c);
}
if ( res == Integer.MIN_VALUE ) {
res = clzToId.get(c);
}
return res;
}
public void encodeClass(FSTEncoder out, FSTClazzInfo ci) throws IOException {
int clzId = ci.getClzId();
if ( clzId >= 0 ) {
out.writeFShort((short) clzId); // > 2 !!
} else {
if ( ci.isAsciiNameShortString) {
final Class aClass = ci.getClazz();
int clid = getIdFromClazz(aClass);
if ( clid != Integer.MIN_VALUE ) {
out.writeFShort((short) clid); // > 2 !!
} else {
// ugly hack, also making assumptions about
// on how the encoder works internally
final byte[] bufferedName = ci.getBufferedName();
out.writeFShort((short) 1); // no direct cl id ascii enc
out.writeFInt((char) bufferedName.length);
out.writeRawBytes(bufferedName,0,bufferedName.length);
registerClassNoLookup(aClass,ci,ci.conf);
}
} else {
encodeClass(out,ci.getClazz());
}
}
}
public void encodeClass(FSTEncoder out, Class c) throws IOException {
int clid = getIdFromClazz(c);
if ( clid != Integer.MIN_VALUE ) {
out.writeFShort((short) clid); // > 2 !!
} else {
encodeClassName(out, c, out.getConf() );
}
}
private void encodeClassName(FSTEncoder out, Class c, FSTConfiguration conf) throws IOException {
out.writeFShort((short) 0); // no direct cl id
out.writeStringUTF(c.getName());
registerClassNoLookup(c,null,conf);
}
public FSTClazzInfo decodeClass(FSTDecoder in, FSTConfiguration conf) throws IOException, ClassNotFoundException {
short c = in.readFShort();
if ( c < LOWEST_CLZ_ID ) {
// full class name
String clName;
if ( c==0) {
clName = in.readStringUTF();
}
else {
clName = in.readStringAsc();
}
Class cl = classForName(clName,conf);
final FSTClazzInfo clInfo = conf.getCLInfoRegistry().getCLInfo(cl, conf);
registerClassNoLookup(cl,clInfo,conf);
return clInfo;
} else {
FSTClazzInfo aClass = getClazzFromId(c);
if ( aClass == null ) {
throw new RuntimeException("unable to find class for code "+c);
}
return aClass;
}
}
HashMap classCache = new HashMap(200);
AtomicBoolean classCacheLock = new AtomicBoolean(false);
public Class classForName(String clName, FSTConfiguration conf) throws ClassNotFoundException {
if ( parent != null ) {
return parent.classForName(clName,conf);
}
try {
while (!classCacheLock.compareAndSet(false, true)) ;
Class res = classCache.get(clName);
if (res == null) {
try {
res = Class.forName(clName, false, conf.getClassLoader());
} catch (Throwable th) {
if ( clName.endsWith("_ActorProxy") ) {
// same as above for actors. As there is a custom serializer defined for actors, just instantiate
// actor clazz
String clName0 = clName;
clName = clName.substring(0, clName.length() - "_ActorProxy".length());
Class actorClz = classCache.get(clName);
if (actorClz == null) {
try {
actorClz = Class.forName(clName, false, conf.getClassLoader());
} catch (ClassNotFoundException clf) {
if ( conf.getLastResortResolver() != null ) {
Class aClass = conf.getLastResortResolver().getClass(clName0);
if ( aClass != null )
return aClass;
}
FSTUtil.rethrow(clf);
}
}
return actorClz;
} else {
if ( conf.getLastResortResolver() != null ) {
Class aClass = conf.getLastResortResolver().getClass(clName);
if ( aClass != null )
return aClass;
}
throw new RuntimeException("class not found CLASSNAME:" + clName + " loader:"+conf.getClassLoader(), th);
}
}
if (res != null) {
classCache.put(clName, res);
}
}
return res;
} finally {
classCacheLock.set(false);
}
}
public void registerClazzFromOtherLoader( Class cl ) {
while( ! classCacheLock.compareAndSet(false,true) );
classCache.put(cl.getName(),cl);
classCacheLock.set(false);
}
public FSTClazzInfo getClazzFromId(int c) {
FSTClazzInfo res = null;
if ( parent != null ) {
res = parent.getClazzFromId(c);
}
if ( res == null ) {
if ( c < 0 || c >= idToClz.length )
return null;
return idToClz[c];
} else {
return res;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy