001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.property; 017 018import static com.google.common.base.Preconditions.checkArgument; 019import static org.kuali.common.util.base.Precondition.checkNotNull; 020 021import java.io.InputStream; 022import java.io.Reader; 023import java.util.Collection; 024import java.util.Map; 025import java.util.Properties; 026import java.util.Set; 027 028import com.google.common.collect.ImmutableList; 029import com.google.common.collect.ImmutableSet; 030 031/** 032 * Immutable version of <code>java.util.Properties</code> that is guaranteed to only contain string keys and values 033 */ 034public final class ImmutableProperties extends Properties { 035 036 private static final long serialVersionUID = 0L; 037 private static final String UOE_MSG = "Immutable properties cannot be changed"; 038 private static final Properties EMPTY = copyOf(new Properties()); 039 040 public ImmutableProperties(Properties mutable) { 041 checkNotNull(mutable, "mutable"); 042 043 // Prevent anything from changing original until we are done 044 synchronized (mutable) { 045 046 // Extract only those keys where both the key and its corresponding value are strings 047 Set<String> keys = mutable.stringPropertyNames(); 048 049 // If the sizes are different, original contains at least one key or value that is not a string 050 checkArgument(keys.size() == mutable.size(), "Immutable properties only support strings"); 051 052 // Copy every key/value pair from original - can't use putAll() since it calls put() which is now disabled 053 for (String key : keys) { 054 super.put(key, mutable.getProperty(key)); 055 } 056 } 057 } 058 059 public static Properties of(String name, String value) { 060 Properties props = new Properties(); 061 props.setProperty(name, value); 062 return copyOf(props); 063 } 064 065 public static Properties of() { 066 return EMPTY; 067 } 068 069 /** 070 * Create and return a new immutable properties object identical to the one passed in. If <code>properties</code> is already immutable, no new object is created, the 071 * <code>properties</code> object passed in as a method argument is what is returned. 072 * 073 * @throws NullPointerException 074 * if {@code properties} is null 075 * 076 * @deprecated use copyOf(Properties) instead 077 */ 078 @Deprecated 079 public static Properties of(Properties properties) { 080 return copyOf(properties); 081 } 082 083 /** 084 * Create and return a new immutable properties object identical to the one passed in. If <code>properties</code> is already immutable, no new object is created, the 085 * <code>properties</code> object passed in as a method argument is what is returned. 086 * 087 * @throws NullPointerException 088 * if {@code properties} is null 089 */ 090 public static ImmutableProperties copyOf(Properties properties) { 091 checkNotNull(properties, "properties"); 092 if (properties instanceof ImmutableProperties) { 093 return (ImmutableProperties) properties; 094 } else { 095 return new ImmutableProperties(properties); 096 } 097 } 098 099 public static ImmutableProperties copyOf(Map<String, String> map) { 100 checkNotNull(map, "map"); 101 Properties properties = new Properties(); 102 for (String key : map.keySet()) { 103 properties.setProperty(key, map.get(key)); 104 } 105 return copyOf(properties); 106 } 107 108 /** 109 * @deprecated Not supported for immutable properties 110 */ 111 @Deprecated 112 @Override 113 public Object setProperty(String key, String value) { 114 throw new UnsupportedOperationException(UOE_MSG); 115 } 116 117 /** 118 * @deprecated Not supported for immutable properties 119 */ 120 @Deprecated 121 @Override 122 public void load(Reader reader) { 123 throw new UnsupportedOperationException(UOE_MSG); 124 } 125 126 /** 127 * @deprecated Not supported for immutable properties 128 */ 129 @Deprecated 130 @Override 131 public void load(InputStream inStream) { 132 throw new UnsupportedOperationException(UOE_MSG); 133 } 134 135 /** 136 * @deprecated Not supported for immutable properties 137 */ 138 @Deprecated 139 @Override 140 public void loadFromXML(InputStream in) { 141 throw new UnsupportedOperationException(UOE_MSG); 142 } 143 144 /** 145 * @deprecated Not supported for immutable properties 146 */ 147 @Deprecated 148 @Override 149 public Object put(Object key, Object value) { 150 throw new UnsupportedOperationException(UOE_MSG); 151 } 152 153 /** 154 * @deprecated Not supported for immutable properties 155 */ 156 @Deprecated 157 @Override 158 public Object remove(Object key) { 159 throw new UnsupportedOperationException(UOE_MSG); 160 } 161 162 /** 163 * @deprecated Not supported for immutable properties 164 */ 165 @Deprecated 166 @Override 167 public void putAll(Map<? extends Object, ? extends Object> t) { 168 throw new UnsupportedOperationException(UOE_MSG); 169 } 170 171 /** 172 * @deprecated Not supported for immutable properties 173 */ 174 @Deprecated 175 @Override 176 public void clear() { 177 throw new UnsupportedOperationException(UOE_MSG); 178 } 179 180 @Override 181 public Set<Object> keySet() { 182 return ImmutableSet.copyOf(super.keySet()); 183 } 184 185 @Override 186 public Set<java.util.Map.Entry<Object, Object>> entrySet() { 187 return ImmutableSet.copyOf(super.entrySet()); 188 } 189 190 @Override 191 public Collection<Object> values() { 192 return ImmutableList.copyOf(super.values()); 193 } 194 195}