Dépôt officiel du code source de l'ERP OpenConcerto
Rev 156 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.modules;
import org.openconcerto.erp.config.Gestion;
import org.openconcerto.erp.modules.ModuleManager.ModuleAction;
import org.openconcerto.erp.modules.ModuleManager.ModuleState;
import org.openconcerto.erp.modules.ModuleTableModel.ModuleRow;
import org.openconcerto.erp.panel.UserExitConf;
import org.openconcerto.sql.view.AbstractFileTransfertHandler;
import org.openconcerto.ui.component.WaitIndeterminatePanel;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.FileUtils;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.text.ChoiceFormat;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.TransferHandler;
public class AvailableModulesPanel {
static final MessageFormat MODULE_FMT;
static {
final ChoiceFormat choiceForm = new ChoiceFormat(new double[] { 1, 2 }, new String[] { "d'un module", "de {0} modules" });
MODULE_FMT = new MessageFormat("{0}");
MODULE_FMT.setFormatByArgumentIndex(0, choiceForm);
}
// prevent the user from interacting when un/installing modules
static JDialog displayDialog(JComponent parent, final String text) {
final WaitIndeterminatePanel panel = new WaitIndeterminatePanel(text);
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(parent), ModalityType.APPLICATION_MODAL);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(parent);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
dialog.setVisible(true);
}
});
return dialog;
}
// return true if the user cancels
static boolean displayDenied(final JComponent panel, final String dialogTitle, final String deniedMsg, final boolean noneAllowed) {
final boolean done;
if (noneAllowed) {
JOptionPane.showMessageDialog(panel, deniedMsg, dialogTitle, JOptionPane.WARNING_MESSAGE);
done = true;
} else {
final int answer = JOptionPane.showConfirmDialog(panel, deniedMsg, dialogTitle, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
done = answer == JOptionPane.CANCEL_OPTION;
}
return done;
}
static void applySolution(final ModuleManager mngr, final ModulePanel panel, final ModulesStateChange chosen, final ModuleState targetState) {
final String dialogTitle = "Gestion des modules";
final int installSize = chosen.getReferencesToInstall().size();
final int uninstallSize = chosen.getReferencesToRemove().size();
if (installSize == 0 && uninstallSize == 0) {
JOptionPane.showMessageDialog(panel, "Aucun changement à apporter", dialogTitle, JOptionPane.INFORMATION_MESSAGE);
return;
}
final StringBuilder sb = new StringBuilder(128);
if (uninstallSize > 0) {
sb.append("Désinstallation ");
sb.append(MODULE_FMT.format(new Object[] { uninstallSize }));
}
if (installSize > 0) {
if (sb.length() > 0)
sb.append(". ");
sb.append("Installation ");
sb.append(MODULE_FMT.format(new Object[] { installSize }));
}
sb.append(".");
final String msg = sb.toString();
if (mngr.needExit(chosen)) {
Gestion.askForExit(new UserExitConf(msg, true) {
@Override
protected void afterWindowsClosed() throws Exception {
// since windows are closed this should minimise uninstall
// problems. As the other branch of the if, start modules
mngr.applyChange(chosen, targetState, true);
};
});
} else {
final JDialog dialog = displayDialog(panel, msg);
new SwingWorker<ModulesStateChangeResult, Object>() {
@Override
protected ModulesStateChangeResult doInBackground() throws Exception {
// don't start the module in background (see below)
// don't go farther than requested
final ModuleState backgroundState = CompareUtils.min(targetState, ModuleState.REGISTERED);
return mngr.applyChange(chosen, backgroundState);
}
@Override
protected void done() {
try {
final ModulesStateChangeResult res = this.get();
if (res.getNotCreated().size() > 0)
JOptionPane.showMessageDialog(panel, "Certains modules n'ont pu être créés : " + res.getNotCreated(), dialogTitle, JOptionPane.WARNING_MESSAGE);
// start inside the EDT, that way when we return, the
// modules are completely started. Further if any exception
// is thrown we can catch it here.
if (targetState.compareTo(ModuleState.STARTED) >= 0) {
try {
// pass all modules to start() since start/stop status might have
// changed since doInBackground()
mngr.startFactories(res.getGraph().flatten());
mngr.setPersistentModules(chosen.getUserReferencesToInstall());
} catch (Exception e) {
ExceptionHandler.handle(panel, "Impossible de démarrer les modules", e);
}
}
} catch (Exception e) {
ExceptionHandler.handle(panel, "Impossible d'appliquer les changements", e);
}
panel.reload();
dialog.dispose();
}
}.execute();
}
}
static final Action createInstallAction(final ModulePanel panel, final boolean onlyInstall) {
return new AbstractAction("Installer") {
@Override
public void actionPerformed(ActionEvent evt) {
final String dialogTitle = "Installation de modules";
final Collection<ModuleRow> checkedRows = panel.getSelection();
if (checkedRows.isEmpty()) {
JOptionPane.showMessageDialog(panel, "Aucune ligne cochée", dialogTitle, JOptionPane.INFORMATION_MESSAGE);
return;
}
final ModuleManager mngr = panel.getModuleManager();
final Set<ModuleReference> refs = new HashSet<ModuleReference>();
final Set<ModuleReference> deniedRefs = new HashSet<ModuleReference>();
for (final ModuleRow f : checkedRows) {
if (!mngr.canCurrentUser(ModuleAction.INSTALL, f))
deniedRefs.add(f.getRef());
else
refs.add(f.getRef());
}
if (deniedRefs.size() > 0) {
if (displayDenied(panel, dialogTitle, "Ces modules ne peuvent être installés : " + deniedRefs, refs.size() == 0))
return;
}
assert refs.size() > 0;
final JDialog depDialog = displayDialog(panel, "Calcul des dépendences");
new SwingWorker<Solutions, Object>() {
@Override
protected Solutions doInBackground() throws Exception {
// MAYBE present the user with the reason references couldn't be installed
return mngr.getSolutions(refs, 5);
}
@Override
protected void done() {
depDialog.dispose();
try {
final Solutions res = this.get();
if (res.getSolutions().size() == 0) {
JOptionPane.showMessageDialog(panel, "Aucune solution trouvée", "Installation de modules", JOptionPane.WARNING_MESSAGE);
} else {
final DepSolverResultChooserPanel cPanel = new DepSolverResultChooserPanel(res.getSolutions());
cPanel.setRunnable(new Runnable() {
@Override
public void run() {
applySolution(mngr, panel, cPanel.getSolutionToApply(), onlyInstall ? ModuleState.INSTALLED : ModuleState.STARTED);
}
});
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(panel), ModalityType.APPLICATION_MODAL);
dialog.add(cPanel);
dialog.pack();
dialog.setLocationRelativeTo(panel);
dialog.setVisible(true);
}
} catch (Exception e) {
ExceptionHandler.handle(panel, "Erreur lors de la recherche de solutions", e);
}
}
}.execute();
}
};
}
static final TransferHandler createTransferHandler(final ModulePanel panel) {
return new AbstractFileTransfertHandler() {
@Override
public void handleFile(File f) {
if (!f.getName().endsWith(".jar")) {
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module. Le fichier n'est pas un module.");
return;
}
final List<File> dirs = panel.getModuleManager().getFolders();
final File dir = ModuleManager.getFolderToWrite(dirs);
if (dir == null) {
if (dirs.isEmpty()) {
JOptionPane.showMessageDialog(panel, "Aucun dossier configuré");
} else {
JOptionPane.showMessageDialog(panel, "Impossible de créer le dossier des modules : " + dirs);
}
return;
}
File out = null;
if (dir.canWrite()) {
try {
out = new File(dir, f.getName());
FileUtils.copyFile(f, out);
} catch (IOException e) {
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module.\n" + f.getAbsolutePath() + " vers " + dir.getAbsolutePath());
return;
}
} else {
JOptionPane.showMessageDialog(panel, "Impossible d'installer le module.\nVous devez disposer des droits en écriture sur le dossier:\n" + dir.getAbsolutePath());
return;
}
try {
panel.getModuleManager().addFactory(new JarModuleFactory(out));
} catch (IOException e) {
JOptionPane.showMessageDialog(panel, "Impossible d'intégrer le module.\n" + e.getMessage());
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
panel.reload();
}
});
}
};
}
}