1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.gui.plugin;
21
22 import java.awt.Component;
23 import java.io.File;
24 import java.io.IOException;
25
26 import javax.swing.JOptionPane;
27
28 import org.apache.log4j.Logger;
29 import org.xnap.XNap;
30 import org.xnap.gui.Dialogs;
31 import org.xnap.gui.pkg.PackageInstallerDialog;
32 import org.xnap.loader.XNapLoader;
33 import org.xnap.pkg.PackageCommit;
34 import org.xnap.pkg.PackageInfo;
35 import org.xnap.pkg.ParseException;
36 import org.xnap.pkg.UnsatisfiedDependenciesException;
37 import org.xnap.pkg.XNapPackageManager;
38 import org.xnap.plugin.PluginInfo;
39 import org.xnap.plugin.PluginManager;
40 import org.xnap.plugin.PluginVerifier;
41 import org.xnap.util.FileHelper;
42 import org.xnap.util.Preferences;
43 import org.xnap.util.StringHelper;
44
45 public class PluginInstallerDialog extends PackageInstallerDialog {
46
47
48
49
50 private static Logger logger = Logger.getLogger(PluginInstallerDialog.class);
51
52
53
54 private PluginInstallerDialog(PackageInfo[] packages)/package-summary.html">ong> PluginInstallerDialog(PackageInfo[] packages)
55 {
56 super(packages);
57 }
58
59
60
61 public void close()
62 {
63 if (!isRunning()) {
64 dispose();
65
66 PackageInfo pendingCore = null;
67
68 boolean showRestart = false;
69 boolean rewriteLoader = false;
70 PackageInfo[] infos = getInstaller().getPackageInfos();
71 for (int i = 0; i < infos.length; i++) {
72 if (infos[i].isInstalled()) {
73 if (infos[i].isPlugin()) {
74 showRestart |= addPlugin(infos[i]);
75 }
76 else if (infos[i].isPatch()) {
77 rewriteLoader |= addPatch(infos[i]);
78 }
79 else if (infos[i].isCore()) {
80 pendingCore = infos[i];
81 }
82 }
83 }
84
85 if (pendingCore != null) {
86 addBase(pendingCore);
87 }
88 else if (rewriteLoader) {
89
90 }
91
92 if (showRestart) {
93 Dialogs.info(this,
94 XNap.tr("One or more plugins could not be enabled, yet. You need to restart XNap."),
95 XNap.tr("New Plugin Installed"));
96 Preferences.getInstance().setUpdatePluginsOnStartup(true);
97 }
98 }
99
100
101 XNapPackageManager.getInstance().write();
102 PluginManager.getInstance().write();
103 }
104
105
106 private void addBase(PackageInfo p)
107 {
108 PluginInfo info = new PluginInfo(p.getProperties());
109 if (resolve(info)) {
110 PluginManager.getInstance().add(info);
111 String[] classPath = info.getClassPath();
112 try {
113 String loaderPathText
114 = "# XNap startup classpath\n"
115 + "Loader-Version: " + XNapLoader.VERSION + "\n"
116 + StringHelper.toString(classPath, "\n");
117 FileHelper.writeText
118 (new File(XNapLoader.LOADER_FILENAME), loaderPathText);
119 }
120 catch (IOException e) {
121 Dialogs.error
122 (this, XNap.tr("Could not write loader information: {0}.",
123 e.getLocalizedMessage()));
124 return;
125 }
126 Dialogs.info
127 (this,
128 XNap.tr("You need to restart XNap."),
129 XNap.tr("New Base Package Installed"));
130 }
131 }
132
133 private boolean addPatch(PackageInfo p)
134 {
135
136
137
138
139
140 return true;
141 }
142
143 private boolean addPlugin(PackageInfo p)
144 {
145 PluginInfo info = new PluginInfo(p.getProperties());
146 if (resolve(info)) {
147 if (PluginManager.getInstance().add(info)) {
148 int response = JOptionPane.showConfirmDialog
149 (this,
150 XNap.tr("Would you like to enable the {0} plugin?",
151 info.getName()),
152 XNap.tr("New Plugin Installed"),
153 JOptionPane.YES_NO_OPTION);
154 if (response == JOptionPane.YES_OPTION) {
155 PluginHelper.enablePlugin(this, info);
156 }
157 }
158 else {
159
160 return true;
161 }
162 }
163 return false;
164 }
165
166 public static boolean commit(Component c)
167 {
168 try {
169 PackageCommit commit
170 = new PackageCommit(XNapPackageManager.getInstance());
171
172 if (!commit.isEmpty()) {
173 PluginInstallerDialog
174 dialog = new PluginInstallerDialog(commit.getInstall());
175 dialog.show(c);
176 }
177
178 return true;
179 }
180 catch (ParseException e) {
181 Dialogs.error(c, e.getLocalizedMessage());
182 }
183 catch (UnsatisfiedDependenciesException e) {
184 String message
185 = XNap.tr("Unsatisfied dependency: Missing {0}.",
186 e.getLocalizedMessage());
187 Dialogs.error(c, message);
188 }
189
190 return false;
191 }
192
193 public boolean resolve(PluginInfo info)
194 {
195 try {
196 info.setClassPath(PluginManager.resolveClassPath(info));
197 }
198 catch (Exception e) {
199 Dialogs.error
200 (this, XNap.tr("Error while resolving class path for {0}: {1}.",
201 info.getName(),
202 e.getLocalizedMessage()));
203 return false;
204 }
205
206
207
208
209
210
211 return true;
212 }
213
214 public boolean validate(PluginInfo info)
215 {
216 try {
217 PluginVerifier pv = new PluginVerifier(info);
218 if (!pv.isValid()) {
219
220 logger.error(info.getName()+" contains invalid jars!");
221 Dialogs.error(this, XNap.tr("Security Error: {0} will be disabled because it has a broken signature", info.getName()));
222 return false;
223 }
224
225 logger.info(info.getName()+(pv.isSigned()?" is signed by "+pv.getSigners():"is not signed"));
226 if (!pv.isTrustedByXNap()) {
227 logger.warn(info.getName()+" contains untrusted code!");
228
229 }
230 }
231 catch (IOException e) {
232 logger.error("Plugin validation failed", e);
233 return false;
234 }
235
236 return true;
237 }
238
239
240 }