001 /*
002 * Copyright 2005,2009 Ivan SZKIBA
003 *
004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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 */
016 package org.ini4j;
017
018 import org.ini4j.spi.BeanAccess;
019 import org.ini4j.spi.BeanTool;
020
021 import java.util.regex.Matcher;
022 import java.util.regex.Pattern;
023
024 public class OptionMapImpl extends MultiMapImpl<String, String> implements OptionMap
025 {
026 private static final char SUBST_CHAR = '$';
027 private static final String SYSTEM_PROPERTY_PREFIX = "@prop/";
028 private static final String ENVIRONMENT_PREFIX = "@env/";
029 private static final int SYSTEM_PROPERTY_PREFIX_LEN = SYSTEM_PROPERTY_PREFIX.length();
030 private static final int ENVIRONMENT_PREFIX_LEN = ENVIRONMENT_PREFIX.length();
031 private static final Pattern EXPRESSION = Pattern.compile("(?<!\\\\)\\$\\{(([^\\[]+)(\\[([0-9]+)\\])?)\\}");
032 private static final int G_OPTION = 2;
033 private static final int G_INDEX = 4;
034 private BeanAccess _defaultBeanAccess;
035
036 @Override public <T> T as(Class<T> clazz)
037 {
038 return BeanTool.getInstance().proxy(clazz, getDefaultBeanAccess());
039 }
040
041 @Override public <T> T as(Class<T> clazz, String keyPrefix)
042 {
043 return BeanTool.getInstance().proxy(clazz, newBeanAccess(keyPrefix));
044 }
045
046 @Override public String fetch(Object key)
047 {
048 int len = length(key);
049
050 return (len == 0) ? null : fetch(key, len - 1);
051 }
052
053 @Override public String fetch(Object key, int index)
054 {
055 String value = get(key, index);
056
057 if ((value != null) && (value.indexOf(SUBST_CHAR) >= 0))
058 {
059 StringBuilder buffer = new StringBuilder(value);
060
061 resolve(buffer);
062 value = buffer.toString();
063 }
064
065 return value;
066 }
067
068 @Override public void from(Object bean)
069 {
070 BeanTool.getInstance().inject(getDefaultBeanAccess(), bean);
071 }
072
073 @Override public void from(Object bean, String keyPrefix)
074 {
075 BeanTool.getInstance().inject(newBeanAccess(keyPrefix), bean);
076 }
077
078 @Override public void to(Object bean)
079 {
080 BeanTool.getInstance().inject(bean, getDefaultBeanAccess());
081 }
082
083 @Override public void to(Object bean, String keyPrefix)
084 {
085 BeanTool.getInstance().inject(bean, newBeanAccess(keyPrefix));
086 }
087
088 protected synchronized BeanAccess getDefaultBeanAccess()
089 {
090 if (_defaultBeanAccess == null)
091 {
092 _defaultBeanAccess = newBeanAccess();
093 }
094
095 return _defaultBeanAccess;
096 }
097
098 protected BeanAccess newBeanAccess()
099 {
100 return new Access();
101 }
102
103 protected BeanAccess newBeanAccess(String propertyNamePrefix)
104 {
105 return new Access(propertyNamePrefix);
106 }
107
108 protected void resolve(StringBuilder buffer)
109 {
110 Matcher m = EXPRESSION.matcher(buffer);
111
112 while (m.find())
113 {
114 String name = m.group(G_OPTION);
115 int index = (m.group(G_INDEX) == null) ? -1 : Integer.parseInt(m.group(G_INDEX));
116 String value;
117
118 if (name.startsWith(ENVIRONMENT_PREFIX))
119 {
120 value = System.getenv(name.substring(ENVIRONMENT_PREFIX_LEN));
121 }
122 else if (name.startsWith(SYSTEM_PROPERTY_PREFIX))
123 {
124 value = System.getProperty(name.substring(SYSTEM_PROPERTY_PREFIX_LEN));
125 }
126 else
127 {
128 value = (index == -1) ? fetch(name) : fetch(name, index);
129 }
130
131 if (value != null)
132 {
133 buffer.replace(m.start(), m.end(), value);
134 m.reset(buffer);
135 }
136 }
137 }
138
139 protected class Access implements BeanAccess
140 {
141 private final String _prefix;
142
143 protected Access()
144 {
145 this(null);
146 }
147
148 protected Access(String prefix)
149 {
150 _prefix = prefix;
151 }
152
153 public void propAdd(String propertyName, String value)
154 {
155 add(transform(propertyName), value);
156 }
157
158 public String propDel(String propertyName)
159 {
160 return remove(transform(propertyName));
161 }
162
163 public String propGet(String propertyName)
164 {
165 return fetch(transform(propertyName));
166 }
167
168 public String propGet(String propertyName, int index)
169 {
170 return fetch(transform(propertyName), index);
171 }
172
173 public int propLength(String propertyName)
174 {
175 return length(transform(propertyName));
176 }
177
178 public String propSet(String propertyName, String value)
179 {
180 return put(transform(propertyName), value);
181 }
182
183 public String propSet(String propertyName, String value, int index)
184 {
185 return put(transform(propertyName), value, index);
186 }
187
188 private String transform(String orig)
189 {
190 return (orig == null) ? null : ((_prefix == null) ? orig : (_prefix + orig));
191 }
192 }
193 }