package org.openslx.dozmod.gui.window; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.TreeSet; import org.apache.log4j.Logger; import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.helper.MessageType; import org.openslx.dozmod.gui.helper.TextChangeListener; import org.openslx.dozmod.gui.helper.UiFeedback; import org.openslx.dozmod.gui.window.layout.VirtConfigEditorWindowLayout; import org.openslx.dozmod.thrift.ImageDetailsActions; import org.openslx.dozmod.thrift.ImageDetailsActions.VirtConfCallback; import org.openslx.dozmod.thrift.cache.MetaDataCache; import org.openslx.util.XmlHelper; import org.openslx.util.vm.VboxMetaData; import org.openslx.util.vm.VmMetaData; import org.openslx.util.vm.VmwareConfig; @SuppressWarnings("serial") public class VirtConfigEditorWindow extends VirtConfigEditorWindowLayout implements UiFeedback { private final static Logger LOGGER = Logger.getLogger(VirtConfigEditorWindow.class); public interface VirtConfigChanged { public void virtConfigChanged(String newVmx); } private final String imageVersionId; private final String originalMachineDescription; private final VirtConfigEditorWindow me = this; private final ImageDetailsActions actionHandler; private boolean configWasSaved = false; protected VirtConfigEditorWindow(Window modalParent, final ImageDetailsActions actionHandler, final String imageVersionId, final String currentMachineDescription, final String originalmachineDescription) { super(modalParent); this.actionHandler = actionHandler; this.imageVersionId = imageVersionId; // listener for the text fields pnlEditor.getDocument().addDocumentListener(new TextChangeListener() { @Override public void changed() { btnSave.setEnabled(!originalMachineDescription.equals(pnlEditor.getText())); } }); btnSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { saveClicked(); } }); btnCancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { safeClose(); } }); // for vbox, originalMachineDescription is unformatted, the new one will be though // save original description for later use this.originalMachineDescription = XmlHelper.getFormattedXml( new ByteArrayInputStream(originalmachineDescription.getBytes(StandardCharsets.UTF_8))); pnlEditor.setText(currentMachineDescription); pnlEditor.setCaretPosition(0); } private void saveClicked() { // we make use of the fact that we saved the BB here! final String userInput = pnlEditor.getText(); byte[] uiBytes = userInput.getBytes(StandardCharsets.ISO_8859_1); Charset cs = VmwareConfig.getCharset(uiBytes, uiBytes.length); // cs is now either the detected encoding, or latin1 as a default uiBytes = userInput.getBytes(cs); // now we should have the correct bytes... VmMetaData metaCandidate = null; try { metaCandidate = VmMetaData.getInstance(MetaDataCache.getOperatingSystems(), uiBytes, uiBytes.length); } catch (IOException e) { LOGGER.error("Could not get VmMetaData instance from given machine description: ", e); } if (metaCandidate == null) { dispose(); return; } byte[] uiBytesFiltered = metaCandidate.getDefinitionArray(); final String userInputFiltered; if (metaCandidate instanceof VboxMetaData) { userInputFiltered = XmlHelper.getFormattedXml(new ByteArrayInputStream(uiBytesFiltered)); } else { userInputFiltered = new String(uiBytesFiltered, cs); } // So here we have: // - uiBytes is the unfiltered user input // - uiBytesFiltered is the user input filtered by VmwareMetaData TreeSet unfilteredSet = stringToTreeSet(userInput); TreeSet filteredSet = stringToTreeSet(userInputFiltered); if (!filteredSet.equals(unfilteredSet)) { unfilteredSet.removeAll(filteredSet); // not equals, means there was some invalid input String errorText = "Invalide Eingaben:\n"; for (String s : unfilteredSet) { errorText += s + "\n"; } errorText += System.lineSeparator() + "Wollen Sie trotzdem speichern? (Die invaliden Zeilen werden dabei automatisch gelöscht.)"; if (!Gui.showMessageBox(errorText, MessageType.ERROR_RETRY, LOGGER, null)) return; } ByteBuffer toSave; if (metaCandidate instanceof VboxMetaData) { String unformattedInput = XmlHelper.getUnformattedXml(new ByteArrayInputStream(uiBytesFiltered)); toSave = ByteBuffer.wrap(unformattedInput.getBytes(cs)); } else { toSave = ByteBuffer.wrap(uiBytesFiltered); } // we have a valid vmx or the user accepted to push the filtered input actionHandler.setVirtualizerConfig(imageVersionId, toSave, new VirtConfCallback() { @Override public void virtConfCallback(boolean success) { if (success) { configWasSaved = true; dispose(); } } }); } private TreeSet stringToTreeSet(final String s) { String[] split = s.split("[\\r\\n]+"); List splitList = new ArrayList(Arrays.asList(split)); splitList.removeAll(Arrays.asList("", null)); TreeSet set = new TreeSet(splitList); return set; } public static boolean open(Window modalParent, final ImageDetailsActions handler, final String imageVersionId, final String currentmachineDescription, final String originalMachineDescription) { VirtConfigEditorWindow win = new VirtConfigEditorWindow(modalParent, handler, imageVersionId, currentmachineDescription, originalMachineDescription); win.setVisible(true); return win.configWasSaved; } private void safeClose() { if (originalMachineDescription.equals(pnlEditor.getText()) || Gui.showMessageBox(me, "Ihre Änderungen, in diesem Fenster, werden verloren gehen, wollen Sie trotzdem abbrechen?", MessageType.QUESTION_YESNO, null, null)) dispose(); } @Override public boolean wantConfirmQuit() { return !originalMachineDescription.equals(pnlEditor.getText()); } @Override public void escapePressed() { safeClose(); } }