1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.pkg;
21
22 import java.io.BufferedReader;
23 import java.io.BufferedWriter;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileWriter;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.net.URL;
31 import java.util.Hashtable;
32 import java.util.Iterator;
33 import java.util.LinkedList;
34 import java.util.Properties;
35 import java.util.*;
36 import java.util.StringTokenizer;
37 import java.util.TreeSet;
38 import java.util.zip.GZIPInputStream;
39
40 /***
41 *
42 */
43 public class PackageManager
44 {
45
46
47
48
49
50 /***
51 * A sorted list of PackageInfo objects.
52 */
53 private TreeSet packages = new TreeSet()/package-summary.html">ong> TreeSet packages = new TreeSet();
54 private Hashtable packageListByProvides = new Hashtable()/package-summary.html">> Hashtable packageListByProvides = new Hashtable();
55
56
57
58 public PackageManager()
59 {
60 }
61
62
63
64 /***
65 * Adds a package. If info is not valid or a package with the same
66 * name and version already exists the package is not added.
67 */
68 public void add(PackageInfo info)
69 {
70 if (info.isValid()) {
71 if (packages/contains(info)) {/package-summary.html">ng> (packages.contains(info)) {
72 SortedSet tailSet = packages.tailSet(info);
73 PackageInfo old = (PackageInfo)tailSet.first();
74 if (old.isInstalled()) {
75 old.setAvailable(true);
76
77 return;
78 }
79 else {
80 remove(old);
81 info.setNew(old.isNew());
82 }
83 }
84 packages.add(info);
85 info.setAvailable(true);
86
87 if (info.getProvides() != null) {
88 StringTokenizer t
89 = new StringTokenizer(info.getProvides(), ",");
90 while (t.hasMoreTokens()) {
91 String name = t.nextToken().trim();
92 LinkedList list
93 = (LinkedList)packageListByProvides.get(name);
94 if (list == null) {
95 list = new LinkedList();
96 packageListByProvides.put(name, list);
97 }
98 list.add(info);
99 }
100 }
101 }
102 }
103
104 public PackageInfo[] getConflicts(PackageInfo info)
105 throws ParseException
106 {
107 LinkedList packageTokens = new LinkedList();
108 DefaultDependencyParser parser = new DefaultDependencyParser();
109 AbstractToken token = parser.parseConflicts(info);
110 if (token instanceof CommaToken) {
111 AbstractToken[] depends = ((CommaToken)token).depends;
112 for (int i = 0; i < depends.length; i++) {
113 if (depends[i] instanceof PackageToken) {
114 packageTokens.add(depends[i]);
115 }
116 }
117 }
118 else if (token instanceof PackageToken) {
119 packageTokens.add(token);
120 }
121
122 LinkedList infos = new LinkedList();
123 for (Iterator it = packageTokens.iterator(); it.hasNext();) {
124 addConflicts(infos, (PackageToken)it.next());
125 }
126 return (PackageInfo[])infos.toArray(new PackageInfo[0]);
127 }
128
129 private void addConflicts(List list, PackageToken token)
130 {
131
132 for (Iterator it = tailSet(token.name).iterator(); it.hasNext();) {
133 PackageInfo info = (PackageInfo)it.next();
134 if (info.getPackage().equals(token.name)) {
135 if (token.compareMode == null
136 || token.equalsVersion(info.compareToVersion
137 (token.version))) {
138
139 list.add(info);
140 }
141 }
142 else {
143 break;
144 }
145 }
146 }
147
148 /***
149 * Returns a list of urls.
150 *
151 * @return the empty string
152 */
153 public String getDefaultSources()
154 {
155 return "";
156 }
157
158 /***
159 *
160 * @exception ParseException thrown, if package file is invalid
161 * @exception UnsatisfiedDependenciesException thrown, if
162 * dependencies are not satisfied
163 */
164 public PackageInfo[] getDependencies(PackageInfo info)
165 throws ParseException, UnsatisfiedDependenciesException
166 {
167 DependencyGraph graph = new DependencyGraph(this);
168 graph.add(info);
169 graph.buildDependencies(new DefaultDependencyParser());
170
171 DefaultResolver r = new DefaultResolver(graph, true);
172 r.resolve();
173 return r.getRequired();
174 }
175
176 /***
177 * Marks all packages that are not installed as unavailable. Marks
178 * all packages as not new.
179 */
180 public void markAllUnavailable()
181 {
182 for (Iterator i = packages(); i.hasNext();) {
183 PackageInfo info = (PackageInfo)i.next();
184 info.setAvailable(info.isInstalled());
185 info.setNew(false);
186 }
187 }
188
189 /***
190 * Reads package information from a control file.
191 *
192 * @param file the control file
193 */
194 public void read(File file, Properties table) throws IOException
195 {
196 FileInputStream in = new FileInputStream(file);
197 try {
198 read(in, table);
199 }
200 finally {
201 in.close();
202 }
203 }
204
205 public void read(File file) throws IOException
206 {
207 read(file, null);
208 }
209
210 /***
211 * Reads package information from a url.
212 *
213 * @param location the package file url
214 * @param downloadUrl the base location of the package files
215 */
216 public void read(String location, Properties table) throws IOException
217 {
218 URL url = new URL(location);
219 InputStream in = url.openStream();
220 try {
221 if (location.endsWith(".gz")) {
222 in = new GZIPInputStream(url.openStream());
223 }
224 read(in, table);
225 }
226 finally {
227 in.close();
228 }
229 }
230
231 /***
232 * Reads package information from a stream.
233 *
234 * @param inStream the stream
235 * @param flags additional flags that are added to the {@link
236 * PackageInfo} record; if null, flags are ignored
237 */
238 public void read(InputStream inStream, Properties flags)
239 throws IOException
240 {
241 BufferedReader in
242 = new BufferedReader(new InputStreamReader(inStream));
243
244 Properties p;
245 while ((p = PackageInfoReader.readNext(in)) != null) {
246 PackageInfo info = new PackageInfo(p);
247 if (flags != null) {
248 info.putAll(flags);
249 }
250 add(info);
251 }
252 }
253
254 public void remove(PackageInfo info)
255 {
256 packages.remove(info);
257 if (info.getProvides() != null) {
258 StringTokenizer t
259 = new StringTokenizer(info.getProvides(), ",");
260 while (t.hasMoreTokens()) {
261 String name = t.nextToken().trim();
262 LinkedList list
263 = (LinkedList)packageListByProvides.get(name);
264 if (list != null) {
265 list.remove(info);
266 }
267 }
268 }
269 }
270
271 /***
272 * Removes all packages that are marked as unavailable.
273 */
274 public void removeUnavailable()
275 {
276 LinkedList toRemove = new LinkedList();
277 for (Iterator i = packages(); i.hasNext();) {
278 PackageInfo info = (PackageInfo)i.next();
279 if (!(info.isInstalled() || info.isAvailable())) {
280 toRemove.add(info);
281 }
282 }
283
284 for (Iterator i = toRemove.iterator(); i.hasNext();) {
285 remove((PackageInfo)i.next());
286 }
287 }
288
289 /***
290 * Returns an iterator over all {@link PackageInfo} objects.
291 */
292 public Iterator packages()/package-summary.html">> Iterator packages()
293 {
294 return packages/iterator()/package-summary.html">g> packages.iterator();
295 }
296
297 /***
298 * Returns the number of packages.
299 */
300 public int getPackageCount()
301 {
302 return packages/size()/package-summary.html">g> packages.size();
303 }
304
305 /***
306 * Returns a package by name.
307 */
308 public PackageInfo getPackage(String packageName)/package-summary.html">> PackageInfo getPackage(String packageName)
309 {
310 SortedSet set = tailSet(packageName);
311 if (!set.isEmpty()) {
312 PackageInfo info = (PackageInfo)set.first();
313 if (info/getPackage()/equals(packageName)) {/package-summary.html">rong> (info.getPackage().equals(packageName)) {
314 return info;
315 }
316 }
317 return null;
318 }
319
320 public SortedSet tailSet(String packageName)/package-summary.html">> SortedSet tailSet(String packageName)
321 {
322 return packages/tailSet(new PackageInfo(packageName))/package-summary.html">g> packages.tailSet(new PackageInfo(packageName));
323 }
324
325 /***
326 * Returns an array of packages that provide packageName.
327 */
328 public PackageInfo[] getProviders(String packageName)/package-summary.html">> PackageInfo[] getProviders(String packageName)
329 {
330 LinkedList list = (LinkedList)packageListByProvides.get(packageName);
331 return (list != null)
332 ? (PackageInfo[])list.toArray(new PackageInfo[0])
333 : null;
334 }
335
336 public void write(File file, Properties flags) throws IOException
337 {
338 BufferedWriter out = new BufferedWriter(new FileWriter(file));
339 try {
340 for (Iterator i = packages.iterator(); i.hasNext();) {
341 PackageInfo info = (PackageInfo)i.next();
342 if (flags == null || info.containsProperties(flags)) {
343 PackageInfoWriter.write(out, info.getProperties());
344 }
345 }
346 }
347 finally {
348 try {
349 out.close();
350 }
351 catch (IOException e) {
352 }
353 }
354 }
355
356 }
357