blob: 6c76d39c2e5692e73753c84e2d9995cc2d352b6e [file] [log] [blame]
Karl Pauls36407322008-03-07 00:37:30 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.framework.security.util;
20
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.File;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.OutputStream;
27import java.lang.reflect.Array;
28import java.lang.reflect.Constructor;
Karl Pauls36407322008-03-07 00:37:30 +000029import java.util.Iterator;
30import java.util.Map;
31import java.util.Properties;
Karl Pauls23287bd2010-01-10 22:11:27 +000032import java.util.TreeMap;
Karl Pauls36407322008-03-07 00:37:30 +000033import java.util.Map.Entry;
34
35import org.apache.felix.framework.util.SecureAction;
36
37public final class PropertiesCache
38{
39 private final File m_file;
40
41 private final File m_tmp;
42
43 private final SecureAction m_action;
44
45 public PropertiesCache(File store, File tmp, SecureAction action)
46 {
47 m_action = action;
48 m_file = store;
49 m_tmp = tmp;
50 }
51
52 public void write(Map data) throws IOException
53 {
54 OutputStream out = null;
55 File tmp = null;
56 File tmp2 = null;
57 try
58 {
59 tmp = m_action.createTempFile("tmp", null, m_tmp);
60 tmp2 = m_action.createTempFile("tmp", null, m_tmp);
61 m_action.deleteFile(tmp2);
62 Exception org = null;
63 try
64 {
65 out = m_action.getFileOutputStream(tmp);
66
67 Properties store = new Properties();
68
Karl Pauls23287bd2010-01-10 22:11:27 +000069 int count = 0;
70
Karl Pauls36407322008-03-07 00:37:30 +000071 for (Iterator iter = data.entrySet().iterator(); iter.hasNext();)
72 {
73 Entry entry = (Entry) iter.next();
Karl Pauls23287bd2010-01-10 22:11:27 +000074 store.setProperty(count++ + "-" + (String) entry.getKey(),
75 getEncoded(entry.getValue()));
Karl Pauls36407322008-03-07 00:37:30 +000076 }
77
78 store.store(out, null);
79 }
80 catch (IOException ex)
81 {
82 org = ex;
83 throw ex;
84 }
85 finally
86 {
87 if (out != null)
88 {
89 try
90 {
91 out.close();
92 }
93 catch (IOException ex)
94 {
95 if (org == null)
96 {
97 throw ex;
98 }
99 }
100 }
101 }
102 if ((m_action.fileExists(m_file) && !m_action.renameFile(m_file,
103 tmp2))
104 || !m_action.renameFile(tmp, m_file))
105 {
106 throw new IOException("Unable to write permissions");
107 }
108 }
109 catch (IOException ex)
110 {
111 if (!m_action.fileExists(m_file) && (tmp2 != null)
112 && m_action.fileExists(tmp2))
113 {
114 m_action.renameFile(tmp2, m_file);
115 }
116 throw ex;
117 }
118 finally
119 {
120 if (tmp != null)
121 {
122 m_action.deleteFile(tmp);
123 }
124 if (tmp2 != null)
125 {
126 m_action.deleteFile(tmp2);
127 }
128 }
129 }
130
Karl Pauls23287bd2010-01-10 22:11:27 +0000131 public void read(Class target, Map map) throws IOException
Karl Pauls36407322008-03-07 00:37:30 +0000132 {
133 if (!m_file.isFile())
134 {
Karl Pauls23287bd2010-01-10 22:11:27 +0000135 return;
Karl Pauls36407322008-03-07 00:37:30 +0000136 }
137 InputStream in = null;
138 Exception other = null;
Karl Pauls23287bd2010-01-10 22:11:27 +0000139 Map result = new TreeMap();
Karl Pauls36407322008-03-07 00:37:30 +0000140 try
141 {
142 in = m_action.getFileInputStream(m_file);
143
144 Properties store = new Properties();
145 store.load(in);
146
147 for (Iterator iter = store.entrySet().iterator(); iter.hasNext();)
148 {
149 Entry entry = (Entry) iter.next();
150 result.put(entry.getKey(), getUnencoded((String) entry
151 .getValue(), target));
152 }
153 }
154 catch (IOException ex)
155 {
156 other = ex;
157 throw ex;
158 }
159 finally
160 {
161 if (in != null)
162 {
163 try
164 {
165 in.close();
166 }
167 catch (IOException ex)
168 {
169 if (other == null)
170 {
171 throw ex;
172 }
173 }
174 }
175 }
Karl Pauls23287bd2010-01-10 22:11:27 +0000176 for (Iterator iter = result.entrySet().iterator(); iter.hasNext();)
177 {
178 Entry entry = (Entry) iter.next();
179 String key = (String) entry.getKey();
180 map.put(key.substring(key.indexOf("-")), entry.getValue());
181 }
Karl Pauls36407322008-03-07 00:37:30 +0000182 }
183
184 private String getEncoded(Object target) throws IOException
185 {
186 Properties props = new Properties();
187 if (target.getClass().isArray())
188 {
189
190 Object[] array = (Object[]) target;
191 for (int i = 0; i < array.length; i++)
192 {
193 props.setProperty(Integer.toString(i), array[i].toString());
194 }
195
196 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
197 props.store(tmp, null);
198 return new String(tmp.toByteArray());
199 }
200
201 return target.toString();
202 }
203
204 private Object getUnencoded(String encoded, Class target)
205 throws IOException
206 {
207 try
208 {
209 if (target.isArray())
210 {
211 Properties props = new Properties();
212 props.load(new ByteArrayInputStream(encoded.getBytes()));
213 Class componentType = target.getComponentType();
Karl Pauls23287bd2010-01-10 22:11:27 +0000214 Constructor constructor = m_action.getConstructor(
215 componentType, new Class[] { String.class });
Karl Pauls36407322008-03-07 00:37:30 +0000216 Object[] params = new Object[1];
Karl Pauls23287bd2010-01-10 22:11:27 +0000217 Object[] result = (Object[]) Array.newInstance(componentType,
218 props.size());
Karl Pauls36407322008-03-07 00:37:30 +0000219
220 for (Iterator iter = props.entrySet().iterator(); iter
221 .hasNext();)
222 {
223 Entry entry = (Entry) iter.next();
224 params[0] = entry.getValue();
Karl Pauls23287bd2010-01-10 22:11:27 +0000225 result[Integer.parseInt((String) entry.getKey())] = constructor
226 .newInstance(params);
Karl Pauls36407322008-03-07 00:37:30 +0000227 }
228
229 return result;
230 }
231
Karl Pauls23287bd2010-01-10 22:11:27 +0000232 return m_action.invoke(m_action.getConstructor(target,
Karl Pauls36407322008-03-07 00:37:30 +0000233 new Class[] { String.class }), new Object[] { encoded });
234 }
235 catch (Exception ex)
236 {
237 ex.printStackTrace();
238
239 throw new IOException(ex.getMessage());
240 }
241 }
242}