001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.messaging.jmf.codec.std.impl.util; 023 024import java.io.IOException; 025import java.io.OutputStream; 026import java.util.ArrayList; 027import java.util.List; 028 029import org.granite.messaging.jmf.InputContext; 030import org.granite.messaging.jmf.OutputContext; 031 032/** 033 * @author Franck WOLFF 034 */ 035public class ClassNameUtil { 036 037 private static final char[] ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$.".toCharArray(); 038 039 private static final byte[] ALPHABET_INDICES = new byte[128]; 040 static { 041 for (int i = 0; i < ALPHABET_INDICES.length; i++) 042 ALPHABET_INDICES[i] = -1; 043 for (int i = 0; i < ALPHABET.length; i++) 044 ALPHABET_INDICES[ALPHABET[i]] = (byte)i; 045 } 046 047 private static final int CLASS_NAME_END = ALPHABET.length; 048 private static final int INDEX_0 = CLASS_NAME_END + 1; 049 private static final int INDEX_OVERFLOW = 0xFF - INDEX_0; 050 051 private ClassNameUtil() { 052 throw new UnsupportedOperationException("Not instantiable"); 053 } 054 055 public static void initClassNameDictionary(List<String> dictionary, String className) { 056 if (!dictionary.contains(className)) { 057 List<String> lookups = new ArrayList<String>(); 058 059 String lookup = className; 060 do { 061 lookups.add(lookup); 062 int lastIndexOfDot = lookup.lastIndexOf('.'); 063 if (lastIndexOfDot == -1) { 064 lookup = ""; 065 break; 066 } 067 lookup = lookup.substring(0, lastIndexOfDot); 068 } 069 while (!dictionary.contains(lookup)); 070 071 for (int i = lookups.size() - 1; i >= 0; i--) 072 dictionary.add(lookups.get(i)); 073 } 074 } 075 076 public static void encodeClassName(OutputContext ctx, String className) throws IOException { 077 final OutputStream os = ctx.getOutputStream(); 078 079 String lookup = className; 080 081 int indexOfStoredClassName = ctx.indexOfClassName(lookup); 082 if (indexOfStoredClassName == -1) { 083 List<String> lookups = new ArrayList<String>(); 084 085 do { 086 lookups.add(lookup); 087 int lastIndexOfDot = lookup.lastIndexOf('.'); 088 if (lastIndexOfDot == -1) { 089 lookup = ""; 090 break; 091 } 092 lookup = lookup.substring(0, lastIndexOfDot); 093 indexOfStoredClassName = ctx.indexOfClassName(lookup); 094 } 095 while (indexOfStoredClassName == -1); 096 097 for (int i = lookups.size() - 1; i >= 0; i--) 098 ctx.addToClassNames(lookups.get(i)); 099 } 100 101 if (indexOfStoredClassName != -1) { 102 if (indexOfStoredClassName < INDEX_OVERFLOW) 103 os.write(indexOfStoredClassName + INDEX_0); 104 else { 105 os.write(0xFF); 106 IntegerUtil.encodeVariableUnsignedInteger(ctx, indexOfStoredClassName - INDEX_OVERFLOW); 107 } 108 } 109 110 if (lookup.length() != className.length()) { 111 int start = (lookup.length() == 0 ? 0 : lookup.length() + 1); 112 for (int i = start; i < className.length(); i++) { 113 int code = ALPHABET_INDICES[className.charAt(i)]; 114 if (code == -1) 115 throw new RuntimeException(); 116 os.write(code); 117 } 118 } 119 120 os.write(CLASS_NAME_END); 121 } 122 123 public static String decodeClassName(InputContext ctx) throws IOException { 124 String className = ""; 125 126 int code = ctx.safeRead(); 127 if (code > CLASS_NAME_END) { 128 if (code != 0xFF) 129 className = ctx.getClassName(code - INDEX_0); 130 else { 131 int index = IntegerUtil.decodeVariableUnsignedInteger(ctx) + INDEX_OVERFLOW; 132 className = ctx.getClassName(index); 133 } 134 135 code = ctx.safeRead(); 136 } 137 138 if (code != CLASS_NAME_END) { 139 StringBuilder sb = (className.length() > 0 ? new StringBuilder(className).append('.') : new StringBuilder(64)); 140 do { 141 char c = ALPHABET[code]; 142 if (c == '.') 143 ctx.addToClassNames(sb.toString()); 144 sb.append(c); 145 code = ctx.safeRead(); 146 } 147 while (code != CLASS_NAME_END); 148 149 className = sb.toString(); 150 151 ctx.addToClassNames(className); 152 } 153 154 return className; 155 } 156}