001/** 002 * 003 * Copyright © 2014-2016 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jxmpp.stringprep; 018 019import org.jxmpp.stringprep.simple.SimpleXmppStringprep; 020import org.jxmpp.util.cache.Cache; 021import org.jxmpp.util.cache.LruCache; 022 023public class XmppStringPrepUtil { 024 025 static { 026 // Ensure that there is always at least the simple XMPP stringprep implementation active 027 SimpleXmppStringprep.setup(); 028 } 029 030 private static final Cache<String, String> NODEPREP_CACHE = new LruCache<String, String>(100); 031 private static final Cache<String, String> DOMAINPREP_CACHE = new LruCache<String, String>(100); 032 private static final Cache<String, String> RESOURCEPREP_CACHE = new LruCache<String, String>(100); 033 034 private static XmppStringprep xmppStringprep; 035 036 /** 037 * Set the XMPP Stringprep implementation to use. 038 * 039 * @param xmppStringprep the XMPP Stringprep implementation to use. 040 */ 041 public static void setXmppStringprep(XmppStringprep xmppStringprep) { 042 XmppStringPrepUtil.xmppStringprep = xmppStringprep; 043 } 044 045 /** 046 * Perform localprep on the input String. 047 * 048 * @param string the input String. 049 * @return the localpreped String. 050 * @throws XmppStringprepException if the input String can not be transformed. 051 */ 052 public static String localprep(String string) throws XmppStringprepException { 053 if (xmppStringprep == null) { 054 return string; 055 } 056 // Avoid cache lookup if string is the empty string 057 throwIfEmptyString(string); 058 String res = NODEPREP_CACHE.lookup(string); 059 if (res != null) { 060 return res; 061 } 062 res = xmppStringprep.localprep(string); 063 NODEPREP_CACHE.put(string, res); 064 return res; 065 } 066 067 /** 068 * Perform domainprep on the input String. 069 * 070 * @param string the input String. 071 * @return the domainprep String. 072 * @throws XmppStringprepException if the input String can not be transformed. 073 */ 074 public static String domainprep(String string) throws XmppStringprepException { 075 if (xmppStringprep == null) { 076 return string; 077 } 078 // Avoid cache lookup if string is the empty string 079 throwIfEmptyString(string); 080 String res = DOMAINPREP_CACHE.lookup(string); 081 if (res != null) { 082 return res; 083 } 084 res = xmppStringprep.domainprep(string); 085 DOMAINPREP_CACHE.put(string, res); 086 return res; 087 } 088 089 /** 090 * Perform resourceprep on the input String. 091 * 092 * @param string the input String. 093 * @return the resourceprep String. 094 * @throws XmppStringprepException if the input String can not be transformed. 095 */ 096 public static String resourceprep(String string) throws XmppStringprepException { 097 if (xmppStringprep == null) { 098 return string; 099 } 100 // Avoid cache lookup if string is the empty string 101 throwIfEmptyString(string); 102 String res = RESOURCEPREP_CACHE.lookup(string); 103 if (res != null) { 104 return res; 105 } 106 res = xmppStringprep.resourceprep(string); 107 RESOURCEPREP_CACHE.put(string, res); 108 return res; 109 } 110 111 /** 112 * Set the maximum cache sizes. 113 * 114 * @param size the maximum cache size. 115 */ 116 public static void setMaxCacheSizes(int size) { 117 NODEPREP_CACHE.setMaxCacheSize(size); 118 DOMAINPREP_CACHE.setMaxCacheSize(size); 119 RESOURCEPREP_CACHE.setMaxCacheSize(size); 120 } 121 122 /** 123 * Throws a XMPP Stringprep exception if string is the empty string. 124 * 125 * @param string 126 * @throws XmppStringprepException 127 */ 128 private static void throwIfEmptyString(String string) throws XmppStringprepException { 129 // TODO replace with string.isEmpty() once Smack's min Android SDK level is > 8 130 if (string.length() == 0) { 131 throw new XmppStringprepException(string, "Argument can't be the empty string"); 132 } 133 } 134}