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.File;
23 import java.io.IOException;
24 import java.util.Properties;
25
26 import org.apache.log4j.Logger;
27 import org.xnap.XNap;
28 import org.xnap.gui.component.ProgressMonitor;
29 import org.xnap.loader.XNapClassLoader;
30 import org.xnap.util.FileHelper;
31 import org.xnap.util.Preferences;
32
33 /***
34 *
35 */
36 public class XNapPackageManager extends PackageManager {
37
38
39
40 public static final String AVAILABLE_FILENAME
41 = FileHelper.getHomeDir() + "available";
42
43 public static final String SOURCES_FILENAME
44 = FileHelper.getHomeDir() + "sources.list";
45
46 public static final String STATUS_FILENAME
47 = FileHelper.getHomeDir() + "status";
48
49
50
51 private static Logger logger = Logger.getLogger(XNapPackageManager.class);
52 private static XNapPackageManager singleton = new XNapPackageManager();
53 private boolean initialized;
54
55
56
57 private XNapPackageManager()
58 {
59 }
60
61
62
63 public static XNapPackageManager getInstance()
64 {
65 return singleton;
66 }
67
68 public PackageInfo createFakePackage(File file)
69 {
70 if (!file.getName().endsWith(".jar")) {
71 throw new IllegalArgumentException("Not a jar file.");
72 }
73 String filename
74 = file.getName().substring(0, file.getName().length() - 4);
75
76 PackageInfo info = new PackageInfo();
77
78 int i = filename.lastIndexOf("-");
79 if (i < 0 || i == filename.length() - 1) {
80 info.setPackage(filename);
81 info.setVersion("1.0");
82 }
83 else {
84 info.setPackage(filename.substring(0, i));
85 info.setVersion(filename.substring(i + 1, filename.length()));
86 }
87 info.setClassPath(new String[] { file.getName() });
88 info.setControlPath(file.getParentFile().getAbsolutePath());
89 info.setSection("local");
90 info.setDescription(XNap.tr("Locally installed jar file."));
91 info.setStatus(PackageInfo.STATUS_INSTALLED);
92
93 return info;
94 }
95
96 /***
97 * Adds installed packages and saves the list of packages to
98 * {@link #AVAILABLE_FILENAME}.
99 */
100 public void discover()
101 {
102 File pathes[] = XNapClassLoader.getSearchPath();
103 for (int i = 0; i < pathes.length; i++) {
104 discover(pathes[i]);
105 }
106
107 String pathnames[] = Preferences.getInstance().getJarIncludePath();
108 for (int i = 0; i < pathnames.length; i++) {
109 discover(new File(pathnames[i]));
110 }
111 }
112
113 /***
114 * Adds all packages found in path and recursively in all sub directories.
115 */
116 public void discover(File path)
117 {
118 File[] files = path.listFiles();
119 if (files != null) {
120 boolean isXNapPackage = false;
121 for (int i = 0; i < files.length; i++) {
122 if (files[i].isDirectory()) {
123 discover(files[i]);
124 }
125 else if (files[i].getName().equals("control")) {
126 try {
127 Properties table = new Properties();
128 table.put("Control-Path", path.getAbsolutePath());
129 table.put("Status", PackageInfo.STATUS_INSTALLED);
130 read(files[i], table);
131 isXNapPackage = true;
132 }
133 catch (IOException e) {
134
135 }
136 }
137 }
138
139 if (isXNapPackage) {
140
141 return;
142 }
143
144 for (int i = 0; i < files.length; i++) {
145 if (files[i].getName().endsWith(".jar")) {
146 PackageInfo info = createFakePackage(files[i]);
147 add(info);
148 }
149 }
150 }
151 }
152
153 public String getDefaultSources(boolean includeUnstable)
154 {
155 StringBuffer sb = new StringBuffer();
156 sb.append("http://xnap.sf.net/stable/packages.gz"
157 + " http://xnap.sf.net/stable/mirrors.list\n");
158 if (!includeUnstable) {
159 sb.append("#");
160 }
161 sb.append("http://xnap.sf.net/unstable/packages.gz"
162 + " http://xnap.sf.net/stable/mirrors.list\n");
163 return sb.toString();
164 }
165
166 public String getDefaultSources()
167 {
168 return getDefaultSources(false);
169 }
170
171 public void initialize()
172 {
173 if (!initialized) {
174 initialized = true;
175
176 logger.info("Initializing package manager");
177 if (XNap.isRunFromCvs()) {
178 try {
179 Properties table = new Properties();
180 table.put("Class-Path", "");
181 table.put("Depends", "");
182 table.put("Status", PackageInfo.STATUS_INSTALLED);
183 read(new File("metainfo/control"), table);
184 }
185 catch (IOException e) {
186 logger.debug("error reading control file", e);
187 }
188 return;
189 }
190
191 if (XNap.clearPackageInfos) {
192
193 discover();
194 }
195 else {
196 File f = new File(STATUS_FILENAME);
197 if (f.exists()) {
198 try {
199 read(new File(STATUS_FILENAME));
200 }
201 catch (IOException e) {
202 logger.debug("error reading status file", e);
203 }
204 }
205 else {
206 discover();
207 }
208
209 try {
210 read(new File(AVAILABLE_FILENAME));
211 }
212 catch (IOException e) {
213 logger.debug("error reading available file", e);
214 }
215 }
216
217 write();
218 }
219 }
220
221 /***
222 * Updates the list of packages from the urls specified in {@link
223 * #SOURCES_FILENAME}.
224 *
225 * <p>This method runs asynchronus. Make sure the package manager
226 * is not modified until monitor.done() is invoked.
227 */
228 public void update(ProgressMonitor monitor)
229 {
230 PackageUpdater updater = new PackageUpdater
231 (this, new File(SOURCES_FILENAME), monitor);
232 Thread t = new Thread(updater, "PackageUpdater");
233 if (monitor != null) {
234 monitor.setThread(t);
235 }
236 t.start();
237 }
238
239 /***
240 * Saves the list of packages.
241 */
242 public void write()
243 {
244 try {
245 write(new File(STATUS_FILENAME), new File(AVAILABLE_FILENAME));
246 }
247 catch (IOException e) {
248 logger.warn("Error writing list of packages", e);
249 }
250 }
251
252 private void write(File statusFile, File availableFile) throws IOException
253 {
254
255 Properties table = new Properties();
256 table.put("Status", PackageInfo.STATUS_INSTALLED);
257 write(statusFile, table);
258
259
260 table = new Properties();
261 table.put("Available", "True");
262 write(availableFile, table);
263 }
264
265 }
266