1 /*******************************************************************************
2  * Copyright (c) 1997, 2008 by ProSyst Software GmbH
3  * http://www.prosyst.com
4  *
5  * This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License 2.0
7  * which accompanies this distribution, and is available at
8  * https://www.eclipse.org/legal/epl-2.0/
9  *
10  * SPDX-License-Identifier: EPL-2.0
11  *
12  * Contributors:
13  *    ProSyst Software GmbH - initial API and implementation
14  *******************************************************************************/
15 package org.eclipse.equinox.internal.ip.storage.file;
16 
17 import java.io.*;
18 import java.util.*;
19 import java.util.zip.*;
20 import org.eclipse.equinox.internal.ip.ProvisioningStorage;
21 import org.eclipse.equinox.internal.ip.impl.Log;
22 import org.eclipse.equinox.internal.ip.impl.ProvisioningAgent;
23 import org.osgi.framework.BundleActivator;
24 import org.osgi.framework.BundleContext;
25 import org.osgi.service.provisioning.ProvisioningService;
26 
27 /**
28  * File Storage.
29  *
30  * @author Avgustin Marinov,
31  * @author Pavlin Dobrev
32  * @version 1.0
33  */
34 
35 public class FileStorage implements ProvisioningStorage, BundleActivator {
36 
37 	/** Name of data file used for storing configuration. */
38 	public static final String FILE_NAME = "_storage.zip";
39 
40 	/** Bundle context. */
41 	private BundleContext bc;
42 
43 	/**
44 	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
45 	 */
start(BundleContext bc)46 	public void start(BundleContext bc) throws Exception {
47 		Log.debug = ProvisioningAgent.getBoolean("equinox.provisioning.debug");
48 		this.bc = bc;
49 	}
50 
51 	/**
52 	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
53 	 */
stop(BundleContext bc)54 	public void stop(BundleContext bc) throws Exception {
55 	}
56 
57 	/**
58 	 * @see org.eclipse.equinox.internal.ip.ProvisioningStorage#getStoredInfo()
59 	 */
getStoredInfo()60 	public Dictionary getStoredInfo() {
61 		FileInputStream fis = null;
62 		try {
63 			fis = new FileInputStream(bc.getDataFile(FILE_NAME));
64 		} catch (Exception e) {
65 			return null;
66 		}
67 		try {
68 			Dictionary toAdd = new Hashtable();
69 			getInfo(fis, toAdd);
70 			fis.close();
71 			return toAdd;
72 		} catch (Exception e) {
73 			Log.debug(e);
74 			return null;
75 		}
76 	}
77 
78 	/**
79 	 * @see org.eclipse.equinox.internal.ip.ProvisioningStorage#store(java.util.Dictionary)
80 	 */
store(Dictionary dictionary)81 	public void store(Dictionary dictionary) {
82 		try {
83 			FileOutputStream fos = new FileOutputStream(bc.getDataFile(FILE_NAME));
84 			saveInfo(fos, dictionary);
85 			fos.close();
86 		} catch (Exception e) {
87 			Log.debug(e);
88 		}
89 	}
90 
91 	/**
92 	 * Returns string name of storage.
93 	 *
94 	 * @see java.lang.Object#toString()
95 	 */
toString()96 	public String toString() {
97 		return "File Storage";
98 	}
99 
100 	/**
101 	 * Decodes data from input stream and loads it in passed dictionary.
102 	 *
103 	 * @param is
104 	 *            input stream in specific format.
105 	 * @param info
106 	 *            dictionary.
107 	 */
getInfo(InputStream is, Dictionary info)108 	private void getInfo(InputStream is, Dictionary info) {
109 		if (is != null) {
110 			try {
111 				ZipInputStream zis = new ZipInputStream(is);
112 				ZipEntry ze;
113 				ByteArrayOutputStream baos = new ByteArrayOutputStream();
114 				int read;
115 				byte[] buff = new byte[256];
116 				while ((ze = zis.getNextEntry()) != null) {
117 					if ("props.txt".equals(ze.getName())) {
118 						BufferedReader reader = new BufferedReader(new InputStreamReader(zis));
119 						String line;
120 						int index;
121 						while ((line = reader.readLine()) != null) {
122 							if (!(line = line.trim()).startsWith("#")) {
123 								if ((index = line.indexOf("=")) != -1) {
124 									String key = line.substring(0, index);
125 									if (ProvisioningService.PROVISIONING_UPDATE_COUNT.equals(key)) {
126 										int uc = 0;
127 										try {
128 											uc = Integer.parseInt(line.substring(index + 1).trim());
129 										} catch (Exception _) {
130 										}
131 										info.put(key, new Integer(uc));
132 									} else {
133 										info.put(key, line.substring(index + 1));
134 									}
135 								}
136 							}
137 						}
138 					} else {
139 						while ((read = zis.read(buff)) != -1) {
140 							baos.write(buff, 0, read);
141 						}
142 						info.put(ze.getName(), baos.toByteArray());
143 						baos.reset();
144 					}
145 					zis.closeEntry();
146 				}
147 			} catch (Exception e) {
148 				Log.debug(e);
149 				// What is loaded is loaded.
150 			}
151 		}
152 	}
153 
154 	/**
155 	 * Encodes "info" and saves it into an output stream.
156 	 *
157 	 * @param os
158 	 *            output stream where to be saved data.
159 	 */
saveInfo(OutputStream os, Dictionary info)160 	private void saveInfo(OutputStream os, Dictionary info) {
161 		try {
162 			ZipOutputStream zos = new ZipOutputStream(os);
163 			ByteArrayOutputStream strings = new ByteArrayOutputStream();
164 			Object key;
165 			Object value;
166 			for (Enumeration e = info.keys(); e.hasMoreElements();) {
167 				key = e.nextElement();
168 				value = info.get(key);
169 				if (value instanceof String || ProvisioningService.PROVISIONING_UPDATE_COUNT.equals(key)) {
170 					strings.write((key + "=" + value + "\r\n").getBytes());
171 				} else if (value instanceof byte[]) {
172 					ZipEntry ze = new ZipEntry((String) key);
173 					zos.putNextEntry(ze);
174 					zos.write((byte[]) value);
175 					zos.closeEntry();
176 				}
177 			}
178 			ZipEntry ze = new ZipEntry("props.txt");
179 			zos.putNextEntry(ze);
180 			zos.write(strings.toByteArray());
181 			zos.closeEntry();
182 			zos.close();
183 		} catch (Exception e) {
184 			Log.debug(e);
185 			// What is load is load.
186 		}
187 	}
188 }
189