18 |
ilm |
1 |
/*
|
|
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
|
3 |
*
|
182 |
ilm |
4 |
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
|
18 |
ilm |
5 |
*
|
|
|
6 |
* The contents of this file are subject to the terms of the GNU General Public License Version 3
|
|
|
7 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
|
|
|
8 |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
|
|
|
9 |
* language governing permissions and limitations under the License.
|
|
|
10 |
*
|
|
|
11 |
* When distributing the software, include this License Header Notice in each file.
|
|
|
12 |
*/
|
|
|
13 |
|
|
|
14 |
package org.openconcerto.erp.modules;
|
|
|
15 |
|
80 |
ilm |
16 |
import org.openconcerto.erp.config.Gestion;
|
|
|
17 |
import org.openconcerto.erp.modules.ModuleManager.ModuleAction;
|
|
|
18 |
import org.openconcerto.erp.modules.ModuleManager.ModuleState;
|
|
|
19 |
import org.openconcerto.erp.modules.ModuleTableModel.ModuleRow;
|
|
|
20 |
import org.openconcerto.erp.panel.UserExitConf;
|
25 |
ilm |
21 |
import org.openconcerto.sql.view.AbstractFileTransfertHandler;
|
61 |
ilm |
22 |
import org.openconcerto.ui.component.WaitIndeterminatePanel;
|
156 |
ilm |
23 |
import org.openconcerto.utils.CompareUtils;
|
19 |
ilm |
24 |
import org.openconcerto.utils.ExceptionHandler;
|
25 |
ilm |
25 |
import org.openconcerto.utils.FileUtils;
|
18 |
ilm |
26 |
|
61 |
ilm |
27 |
import java.awt.Dialog.ModalityType;
|
19 |
ilm |
28 |
import java.awt.event.ActionEvent;
|
25 |
ilm |
29 |
import java.io.File;
|
|
|
30 |
import java.io.IOException;
|
61 |
ilm |
31 |
import java.text.ChoiceFormat;
|
|
|
32 |
import java.text.MessageFormat;
|
80 |
ilm |
33 |
import java.util.Collection;
|
|
|
34 |
import java.util.HashSet;
|
182 |
ilm |
35 |
import java.util.List;
|
67 |
ilm |
36 |
import java.util.Set;
|
18 |
ilm |
37 |
|
19 |
ilm |
38 |
import javax.swing.AbstractAction;
|
80 |
ilm |
39 |
import javax.swing.Action;
|
61 |
ilm |
40 |
import javax.swing.JComponent;
|
|
|
41 |
import javax.swing.JDialog;
|
25 |
ilm |
42 |
import javax.swing.JOptionPane;
|
|
|
43 |
import javax.swing.SwingUtilities;
|
61 |
ilm |
44 |
import javax.swing.SwingWorker;
|
80 |
ilm |
45 |
import javax.swing.TransferHandler;
|
18 |
ilm |
46 |
|
80 |
ilm |
47 |
public class AvailableModulesPanel {
|
61 |
ilm |
48 |
|
|
|
49 |
static final MessageFormat MODULE_FMT;
|
|
|
50 |
|
|
|
51 |
static {
|
|
|
52 |
final ChoiceFormat choiceForm = new ChoiceFormat(new double[] { 1, 2 }, new String[] { "d'un module", "de {0} modules" });
|
|
|
53 |
MODULE_FMT = new MessageFormat("{0}");
|
|
|
54 |
MODULE_FMT.setFormatByArgumentIndex(0, choiceForm);
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
// prevent the user from interacting when un/installing modules
|
|
|
58 |
static JDialog displayDialog(JComponent parent, final String text) {
|
|
|
59 |
final WaitIndeterminatePanel panel = new WaitIndeterminatePanel(text);
|
|
|
60 |
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(parent), ModalityType.APPLICATION_MODAL);
|
|
|
61 |
dialog.add(panel);
|
|
|
62 |
dialog.pack();
|
|
|
63 |
dialog.setLocationRelativeTo(parent);
|
|
|
64 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
65 |
@Override
|
|
|
66 |
public void run() {
|
|
|
67 |
dialog.setVisible(true);
|
|
|
68 |
}
|
|
|
69 |
});
|
|
|
70 |
return dialog;
|
|
|
71 |
}
|
|
|
72 |
|
80 |
ilm |
73 |
// return true if the user cancels
|
|
|
74 |
static boolean displayDenied(final JComponent panel, final String dialogTitle, final String deniedMsg, final boolean noneAllowed) {
|
|
|
75 |
final boolean done;
|
|
|
76 |
if (noneAllowed) {
|
|
|
77 |
JOptionPane.showMessageDialog(panel, deniedMsg, dialogTitle, JOptionPane.WARNING_MESSAGE);
|
|
|
78 |
done = true;
|
|
|
79 |
} else {
|
|
|
80 |
final int answer = JOptionPane.showConfirmDialog(panel, deniedMsg, dialogTitle, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
|
|
|
81 |
done = answer == JOptionPane.CANCEL_OPTION;
|
73 |
ilm |
82 |
}
|
80 |
ilm |
83 |
return done;
|
67 |
ilm |
84 |
}
|
61 |
ilm |
85 |
|
156 |
ilm |
86 |
static void applySolution(final ModuleManager mngr, final ModulePanel panel, final ModulesStateChange chosen, final ModuleState targetState) {
|
80 |
ilm |
87 |
final String dialogTitle = "Gestion des modules";
|
|
|
88 |
final int installSize = chosen.getReferencesToInstall().size();
|
|
|
89 |
final int uninstallSize = chosen.getReferencesToRemove().size();
|
|
|
90 |
if (installSize == 0 && uninstallSize == 0) {
|
|
|
91 |
JOptionPane.showMessageDialog(panel, "Aucun changement à apporter", dialogTitle, JOptionPane.INFORMATION_MESSAGE);
|
67 |
ilm |
92 |
return;
|
|
|
93 |
}
|
80 |
ilm |
94 |
|
|
|
95 |
final StringBuilder sb = new StringBuilder(128);
|
|
|
96 |
if (uninstallSize > 0) {
|
|
|
97 |
sb.append("Désinstallation ");
|
|
|
98 |
sb.append(MODULE_FMT.format(new Object[] { uninstallSize }));
|
67 |
ilm |
99 |
}
|
80 |
ilm |
100 |
if (installSize > 0) {
|
|
|
101 |
if (sb.length() > 0)
|
|
|
102 |
sb.append(". ");
|
|
|
103 |
sb.append("Installation ");
|
|
|
104 |
sb.append(MODULE_FMT.format(new Object[] { installSize }));
|
67 |
ilm |
105 |
}
|
80 |
ilm |
106 |
sb.append(".");
|
|
|
107 |
final String msg = sb.toString();
|
|
|
108 |
if (mngr.needExit(chosen)) {
|
|
|
109 |
Gestion.askForExit(new UserExitConf(msg, true) {
|
67 |
ilm |
110 |
@Override
|
80 |
ilm |
111 |
protected void afterWindowsClosed() throws Exception {
|
|
|
112 |
// since windows are closed this should minimise uninstall
|
|
|
113 |
// problems. As the other branch of the if, start modules
|
|
|
114 |
mngr.applyChange(chosen, targetState, true);
|
|
|
115 |
};
|
|
|
116 |
});
|
|
|
117 |
} else {
|
|
|
118 |
final JDialog dialog = displayDialog(panel, msg);
|
|
|
119 |
new SwingWorker<ModulesStateChangeResult, Object>() {
|
|
|
120 |
@Override
|
|
|
121 |
protected ModulesStateChangeResult doInBackground() throws Exception {
|
156 |
ilm |
122 |
// don't start the module in background (see below)
|
|
|
123 |
// don't go farther than requested
|
|
|
124 |
final ModuleState backgroundState = CompareUtils.min(targetState, ModuleState.REGISTERED);
|
|
|
125 |
return mngr.applyChange(chosen, backgroundState);
|
25 |
ilm |
126 |
}
|
67 |
ilm |
127 |
|
|
|
128 |
@Override
|
|
|
129 |
protected void done() {
|
25 |
ilm |
130 |
try {
|
80 |
ilm |
131 |
final ModulesStateChangeResult res = this.get();
|
|
|
132 |
if (res.getNotCreated().size() > 0)
|
|
|
133 |
JOptionPane.showMessageDialog(panel, "Certains modules n'ont pu être créés : " + res.getNotCreated(), dialogTitle, JOptionPane.WARNING_MESSAGE);
|
|
|
134 |
|
|
|
135 |
// start inside the EDT, that way when we return, the
|
|
|
136 |
// modules are completely started. Further if any exception
|
|
|
137 |
// is thrown we can catch it here.
|
|
|
138 |
if (targetState.compareTo(ModuleState.STARTED) >= 0) {
|
|
|
139 |
try {
|
|
|
140 |
// pass all modules to start() since start/stop status might have
|
|
|
141 |
// changed since doInBackground()
|
|
|
142 |
mngr.startFactories(res.getGraph().flatten());
|
|
|
143 |
mngr.setPersistentModules(chosen.getUserReferencesToInstall());
|
|
|
144 |
} catch (Exception e) {
|
|
|
145 |
ExceptionHandler.handle(panel, "Impossible de démarrer les modules", e);
|
|
|
146 |
}
|
67 |
ilm |
147 |
}
|
|
|
148 |
} catch (Exception e) {
|
80 |
ilm |
149 |
ExceptionHandler.handle(panel, "Impossible d'appliquer les changements", e);
|
25 |
ilm |
150 |
}
|
80 |
ilm |
151 |
panel.reload();
|
67 |
ilm |
152 |
dialog.dispose();
|
25 |
ilm |
153 |
}
|
67 |
ilm |
154 |
}.execute();
|
|
|
155 |
}
|
|
|
156 |
}
|
25 |
ilm |
157 |
|
81 |
ilm |
158 |
static final Action createInstallAction(final ModulePanel panel, final boolean onlyInstall) {
|
80 |
ilm |
159 |
return new AbstractAction("Installer") {
|
|
|
160 |
@Override
|
|
|
161 |
public void actionPerformed(ActionEvent evt) {
|
|
|
162 |
final String dialogTitle = "Installation de modules";
|
81 |
ilm |
163 |
final Collection<ModuleRow> checkedRows = panel.getSelection();
|
80 |
ilm |
164 |
if (checkedRows.isEmpty()) {
|
|
|
165 |
JOptionPane.showMessageDialog(panel, "Aucune ligne cochée", dialogTitle, JOptionPane.INFORMATION_MESSAGE);
|
|
|
166 |
return;
|
|
|
167 |
}
|
156 |
ilm |
168 |
final ModuleManager mngr = panel.getModuleManager();
|
80 |
ilm |
169 |
final Set<ModuleReference> refs = new HashSet<ModuleReference>();
|
|
|
170 |
final Set<ModuleReference> deniedRefs = new HashSet<ModuleReference>();
|
|
|
171 |
for (final ModuleRow f : checkedRows) {
|
|
|
172 |
if (!mngr.canCurrentUser(ModuleAction.INSTALL, f))
|
|
|
173 |
deniedRefs.add(f.getRef());
|
|
|
174 |
else
|
|
|
175 |
refs.add(f.getRef());
|
|
|
176 |
}
|
|
|
177 |
if (deniedRefs.size() > 0) {
|
|
|
178 |
if (displayDenied(panel, dialogTitle, "Ces modules ne peuvent être installés : " + deniedRefs, refs.size() == 0))
|
|
|
179 |
return;
|
|
|
180 |
}
|
|
|
181 |
assert refs.size() > 0;
|
|
|
182 |
final JDialog depDialog = displayDialog(panel, "Calcul des dépendences");
|
|
|
183 |
new SwingWorker<Solutions, Object>() {
|
|
|
184 |
@Override
|
|
|
185 |
protected Solutions doInBackground() throws Exception {
|
|
|
186 |
// MAYBE present the user with the reason references couldn't be installed
|
|
|
187 |
return mngr.getSolutions(refs, 5);
|
|
|
188 |
}
|
25 |
ilm |
189 |
|
80 |
ilm |
190 |
@Override
|
|
|
191 |
protected void done() {
|
|
|
192 |
depDialog.dispose();
|
|
|
193 |
try {
|
|
|
194 |
final Solutions res = this.get();
|
|
|
195 |
if (res.getSolutions().size() == 0) {
|
|
|
196 |
JOptionPane.showMessageDialog(panel, "Aucune solution trouvée", "Installation de modules", JOptionPane.WARNING_MESSAGE);
|
|
|
197 |
} else {
|
|
|
198 |
final DepSolverResultChooserPanel cPanel = new DepSolverResultChooserPanel(res.getSolutions());
|
|
|
199 |
cPanel.setRunnable(new Runnable() {
|
|
|
200 |
@Override
|
|
|
201 |
public void run() {
|
156 |
ilm |
202 |
applySolution(mngr, panel, cPanel.getSolutionToApply(), onlyInstall ? ModuleState.INSTALLED : ModuleState.STARTED);
|
80 |
ilm |
203 |
}
|
|
|
204 |
});
|
|
|
205 |
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(panel), ModalityType.APPLICATION_MODAL);
|
|
|
206 |
dialog.add(cPanel);
|
|
|
207 |
dialog.pack();
|
|
|
208 |
dialog.setLocationRelativeTo(panel);
|
|
|
209 |
dialog.setVisible(true);
|
67 |
ilm |
210 |
|
80 |
ilm |
211 |
}
|
|
|
212 |
} catch (Exception e) {
|
|
|
213 |
ExceptionHandler.handle(panel, "Erreur lors de la recherche de solutions", e);
|
|
|
214 |
}
|
|
|
215 |
}
|
|
|
216 |
|
|
|
217 |
}.execute();
|
25 |
ilm |
218 |
}
|
80 |
ilm |
219 |
};
|
|
|
220 |
}
|
67 |
ilm |
221 |
|
80 |
ilm |
222 |
static final TransferHandler createTransferHandler(final ModulePanel panel) {
|
|
|
223 |
return new AbstractFileTransfertHandler() {
|
|
|
224 |
|
|
|
225 |
@Override
|
|
|
226 |
public void handleFile(File f) {
|
|
|
227 |
if (!f.getName().endsWith(".jar")) {
|
|
|
228 |
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module. Le fichier n'est pas un module.");
|
|
|
229 |
return;
|
|
|
230 |
}
|
182 |
ilm |
231 |
final List<File> dirs = panel.getModuleManager().getFolders();
|
|
|
232 |
final File dir = ModuleManager.getFolderToWrite(dirs);
|
|
|
233 |
if (dir == null) {
|
|
|
234 |
if (dirs.isEmpty()) {
|
|
|
235 |
JOptionPane.showMessageDialog(panel, "Aucun dossier configuré");
|
142 |
ilm |
236 |
} else {
|
182 |
ilm |
237 |
JOptionPane.showMessageDialog(panel, "Impossible de créer le dossier des modules : " + dirs);
|
142 |
ilm |
238 |
}
|
182 |
ilm |
239 |
return;
|
142 |
ilm |
240 |
}
|
80 |
ilm |
241 |
File out = null;
|
|
|
242 |
if (dir.canWrite()) {
|
|
|
243 |
try {
|
|
|
244 |
out = new File(dir, f.getName());
|
|
|
245 |
FileUtils.copyFile(f, out);
|
|
|
246 |
} catch (IOException e) {
|
|
|
247 |
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module.\n" + f.getAbsolutePath() + " vers " + dir.getAbsolutePath());
|
|
|
248 |
return;
|
|
|
249 |
}
|
|
|
250 |
} else {
|
|
|
251 |
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module.\nVous devez disposer des droits en écriture sur le dossier:\n" + dir.getAbsolutePath());
|
|
|
252 |
return;
|
|
|
253 |
}
|
|
|
254 |
try {
|
156 |
ilm |
255 |
panel.getModuleManager().addFactory(new JarModuleFactory(out));
|
80 |
ilm |
256 |
} catch (IOException e) {
|
|
|
257 |
JOptionPane.showMessageDialog(panel, "Impossible d'intégrer le module.\n" + e.getMessage());
|
|
|
258 |
return;
|
|
|
259 |
}
|
|
|
260 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
261 |
|
|
|
262 |
@Override
|
|
|
263 |
public void run() {
|
|
|
264 |
panel.reload();
|
|
|
265 |
}
|
|
|
266 |
});
|
|
|
267 |
|
|
|
268 |
}
|
|
|
269 |
};
|
18 |
ilm |
270 |
}
|
|
|
271 |
}
|