1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.loader;
21
22
23
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.lang.reflect.Method;
31 import java.net.URL;
32 import java.net.URLDecoder;
33 import java.util.*;
34
35 /***
36 * Checks if a version of XNap is available in the users preferences
37 * directory and launches the newest version found.
38 */
39 public class XNapLoader {
40
41
42
43 /***
44 * Current version of the core distribution. This version needs to
45 * be in sync with the version of the xnap-core package in the
46 * control file.
47 *
48 * <p><pre>
49 * Format: '$MAJOR.$MINOR[-$EXTRA(1-9)]'
50 * $EXTRA can be 'alpha', 'beta' or 'pre'
51 *
52 * Examples: 1.3-alpha1, 2.1-pre1, 2.4
53 * </pre>
54 *
55 * <p>Security fix related releases should append 'r(1-9)' to the version,
56 * like this 2.4r1 .
57 */
58 public static final String VERSION = "3.0-pre1";
59
60 public static final String LOADER_FILENAME
61 = XNapClassLoader.getHomeDir() + "loader";
62
63
64
65
66
67 /***
68 *
69 */
70 public static void main(String[] argv)
71 {
72 if (!invoke(LOADER_FILENAME, true, argv)) {
73
74 err("Using default class path");
75 if (!invoke("default_loader", false, argv)) {
76
77 err("Could not find suitable loader file, giving up");
78 System.exit(1);
79 }
80 }
81 }
82
83 /***
84 * Prints <code>o.toString()</code> to stderr.
85 */
86 public static void err(Object o)
87 {
88 System.err.println(o);
89 }
90
91 public static URL[] getStartupClassPath
92 (InputStream inStream, File parent, boolean requireVersion)
93 throws IOException
94 {
95 boolean versionFound = false;
96 LinkedList list = new LinkedList();
97
98 BufferedReader in
99 = new BufferedReader(new InputStreamReader(inStream));
100 try {
101 String s;
102 while ((s = in.readLine()) != null) {
103 if (s.startsWith("#")) {
104 continue;
105 }
106 else if (s.startsWith("Loader-Version: ")) {
107 StringTokenizer t = new StringTokenizer(s, ":");
108 t.nextToken();
109 if (t.hasMoreTokens()) {
110 versionFound = true;
111 String loaderVersion = t.nextToken().trim();
112 if (!VERSION.equals(loaderVersion)) {
113 throw new IOException
114 ("Mismatch of loader versions");
115 }
116 }
117 continue;
118 }
119
120 list.add(new File(parent, s).toURL());
121 }
122 }
123 finally {
124 try {
125 in.close();
126 }
127 catch (IOException e) {
128 }
129 }
130
131 if (requireVersion && !versionFound) {
132 throw new IOException("Loader version information is missing");
133 }
134
135 return (URL[])list.toArray(new URL[0]);
136 }
137
138 /***
139 * Returns the jar that contains the XNapLoader class.
140 *
141 * @return null, if path can not be determined; the jar, otherwise
142 */
143 public static File getJar()
144 {
145 URL url = ClassLoader.getSystemClassLoader().getResource
146 ("org/xnap/loader/XNapLoader.class");
147 if (url != null) {
148 String path = url.getFile();
149 if (path != null) {
150 int index = path.lastIndexOf("!/");
151 if (index > 0) {
152
153 path = "//" + URLDecoder.decode(path.substring(5, index));
154 return new File(path);
155 }
156 }
157 }
158
159 return null;
160 }
161
162 /***
163 * Returns path of the jar that contains the XNapLoader class.
164 *
165 * @return null, if path can not be determined; the path, otherwise
166 * @see #getJar()
167 */
168 public static File getJarPath()
169 {
170 File f = getJar();
171 return (f != null) ? f.getParentFile() : null;
172 }
173
174 public static boolean invoke
175 (String filename,
176 boolean requireVersion,
177 String[] argv)
178 {
179 URL[] urls;
180 try {
181 File parent = getJarPath();
182 InputStream in
183 = XNapClassLoader.getInstance().getResourceAsStream(filename);
184 if (in == null) {
185 in = new FileInputStream(filename);
186 parent = null;
187 }
188 urls = getStartupClassPath(in, parent, requireVersion);
189 }
190 catch (IOException e) {
191 err("Could not read startup classpath from " + filename
192 + " (" + e.getLocalizedMessage() + ")");
193 return false;
194 }
195
196 try {
197
198 for (int i = 0; i < urls.length; i++) {
199 XNapClassLoader.getInstance().add(urls[i]);
200 }
201
202
203 Class c = XNapClassLoader.getInstance().loadClass("org.xnap.XNap");
204 Object app = c.newInstance();
205 Method m = c.getMethod("main", new Class[] { String[].class });
206 m.invoke(app, new Object[] { argv });
207 return true;
208 }
209 catch (Throwable e) {
210 err("Could not load XNap");
211 e.printStackTrace(System.err);
212 return false;
213 }
214 }
215
216 }