/* * $Id$ * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved. * * http://izpack.org/ * http://izpack.codehaus.org/ * * Copyright 2002 Jan Blok * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.izforge.izpack.installer; import com.izforge.izpack.CustomData; import com.izforge.izpack.ExecutableFile; import com.izforge.izpack.LocaleDatabase; import com.izforge.izpack.Panel; import com.izforge.izpack.adaptator.IXMLElement; import com.izforge.izpack.adaptator.IXMLParser; import com.izforge.izpack.adaptator.IXMLWriter; import com.izforge.izpack.adaptator.impl.XMLElementImpl; import com.izforge.izpack.adaptator.impl.XMLParser; import com.izforge.izpack.adaptator.impl.XMLWriter; import com.izforge.izpack.gui.ButtonFactory; import com.izforge.izpack.gui.EtchedLineBorder; import com.izforge.izpack.gui.IconsDatabase; import com.izforge.izpack.rules.RulesEngine; import com.izforge.izpack.util.*; import com.sun.pkg.client.Image.FmriState; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; import java.io.*; import java.lang.reflect.Constructor; import java.net.URL; import java.util.*; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipOutputStream; /** * The IzPack installer frame. * * @author Julien Ponge created October 27, 2002 * @author Fabrice Mirabile added fix for alert window on cross button, July 06 2005 * @author Dennis Reil, added RulesEngine November 10 2006, several changes in January 2007 */ public class InstallerFrame extends JFrame { private static final long serialVersionUID = 3257852069162727473L; /** * VM version to use version dependent methods calls */ private static final float JAVA_SPECIFICATION_VERSION = Float.parseFloat(System .getProperty("java.specification.version")); private static final String ICON_RESOURCE = "Installer.image"; /** * Name of the variable where to find an extension to the resource name of the icon resource */ private static final String ICON_RESOURCE_EXT_VARIABLE_NAME = "installerimage.ext"; /** * Heading icon resource name. */ private static final String HEADING_ICON_RESOURCE = "Heading.image"; /** * The language pack. */ public LocaleDatabase langpack; /** * The installation data. */ protected InstallData installdata; /** * The icons database. */ public IconsDatabase icons; /** * The panels container. */ protected JPanel panelsContainer; /** * The frame content pane. */ protected JPanel contentPane; /** * The help button. */ protected JButton helpButton = null; /** * The previous button. */ protected JButton prevButton; /** * The next button. */ protected JButton nextButton; /** * The quit button. */ protected JButton quitButton; /** * Mapping from "raw" panel number to visible panel number. */ protected ArrayList<Integer> visiblePanelMapping; /** * Registered GUICreationListener. */ protected ArrayList<GUIListener> guiListener; /** * Heading major text. */ protected JLabel[] headingLabels; /** * Panel which contains the heading text and/or icon */ protected JPanel headingPanel; /** * The heading counter component. */ protected JComponent headingCounterComponent; /** * Image */ private JLabel iconLabel; /** * Count for discarded interrupt trials. */ private int interruptCount = 1; /** * Maximum of discarded interrupt trials. */ private static final int MAX_INTERRUPT = 3; /** * conditions */ protected RulesEngine rules; /** * Resource name for custom icons */ private static final String CUSTOM_ICONS_RESOURCEFILE = "customicons.xml"; private VariableSubstitutor substitutor; private Debugger debugger; // If a heading image is defined should it be displayed on the left private boolean imageLeft = false; private InstallerBase parentInstaller; /** * The constructor (normal mode). * * @param title The window title. * @param installdata The installation data. * * @throws Exception Description of the Exception */ public InstallerFrame(String title, InstallData installdata, InstallerBase parentInstaller) throws Exception { super(title); this.parentInstaller = parentInstaller; this.rules = this.parentInstaller.getRules(); substitutor = new VariableSubstitutor(installdata.variables); guiListener = new ArrayList<GUIListener>(); visiblePanelMapping = new ArrayList<Integer>(); this.installdata = installdata; this.langpack = installdata.langpack; // Sets the window events handler addWindowListener(new WindowHandler()); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); // Builds the GUI loadIcons(); loadCustomIcons(); loadPanels(); buildGUI(); // We show the frame showFrame(); switchPanel(0); } public Debugger getDebugger() { return this.debugger; } /** * Loads the panels. * * @throws Exception Description of the Exception */ private void loadPanels() throws Exception { // Initialisation java.util.List panelsOrder = installdata.panelsOrder; int i; int size = panelsOrder.size(); String className; Class objectClass; Constructor constructor; Object object; IzPanel panel; Class[] paramsClasses = new Class[2]; paramsClasses[0] = Class.forName("com.izforge.izpack.installer.InstallerFrame"); paramsClasses[1] = Class.forName("com.izforge.izpack.installer.InstallData"); Object[] params = {this, installdata}; // We load each of them int curVisPanelNumber = 0; int lastVis = 0; int count = 0; for (i = 0; i < size; i++) { // We add the panel Panel p = (Panel) panelsOrder.get(i); if (!OsConstraint.oneMatchesCurrentSystem(p.osConstraints)) { continue; } className = p.className; String praefix = "com.izforge.izpack.panels."; if (className.indexOf('.') > -1) // Full qualified class name { praefix = ""; } objectClass = Class.forName(praefix + className); constructor = objectClass.getDeclaredConstructor(paramsClasses); installdata.currentPanel = p; // A hack to use meta data in IzPanel constructor // Do not call constructor of IzPanel or it's derived at an other place else // metadata will be not set. List<String> preConstgructionActions = p.getPreConstructionActions(); if (preConstgructionActions != null) { for (int actionIndex = 0; actionIndex < preConstgructionActions.size(); actionIndex++) { PanelAction action = PanelActionFactory.createPanelAction(preConstgructionActions.get(actionIndex)); action.initialize(p.getPanelActionConfiguration(preConstgructionActions.get(actionIndex))); action.executeAction(AutomatedInstallData.getInstance(), null); } } object = constructor.newInstance(params); panel = (IzPanel) object; String dataValidator = p.getValidator(); if (dataValidator != null) { panel.setValidationService(DataValidatorFactory.createDataValidator(dataValidator)); } panel.setHelps(p.getHelpsMap()); List<String> preActivateActions = p.getPreActivationActions(); if (preActivateActions != null) { for (int actionIndex = 0; actionIndex < preActivateActions.size(); actionIndex++) { String panelActionClass = preActivateActions.get(actionIndex); PanelAction action = PanelActionFactory.createPanelAction(panelActionClass); action.initialize(p.getPanelActionConfiguration(panelActionClass)); panel.addPreActivationAction(action); } } List<String> preValidateActions = p.getPreValidationActions(); if (preValidateActions != null) { for (int actionIndex = 0; actionIndex < preValidateActions.size(); actionIndex++) { String panelActionClass = preValidateActions.get(actionIndex); PanelAction action = PanelActionFactory.createPanelAction(panelActionClass); action.initialize(p.getPanelActionConfiguration(panelActionClass)); panel.addPreValidationAction(action); } } List<String> postValidateActions = p.getPostValidationActions(); if (postValidateActions != null) { for (int actionIndex = 0; actionIndex < postValidateActions.size(); actionIndex++) { String panelActionClass = postValidateActions.get(actionIndex); PanelAction action = PanelActionFactory.createPanelAction(panelActionClass); action.initialize(p.getPanelActionConfiguration(panelActionClass)); panel.addPostValidationAction(action); } } installdata.panels.add(panel); if (panel.isHidden()) { visiblePanelMapping.add(count, -1); } else { visiblePanelMapping.add(count, curVisPanelNumber); curVisPanelNumber++; lastVis = count; } count++; // We add the XML data panel root IXMLElement panelRoot = new XMLElementImpl(className, installdata.xmlData); // if set, we add the id as an attribute to the panelRoot String panelId = p.getPanelid(); if (panelId != null) { panelRoot.setAttribute("id", panelId); } installdata.xmlData.addChild(panelRoot); } visiblePanelMapping.add(count, lastVis); } /** * Loads the icons. * * @throws Exception Description of the Exception */ private void loadIcons() throws Exception { // Initialisations icons = new IconsDatabase(); URL url; ImageIcon img; IXMLElement icon; InputStream inXML = InstallerFrame.class .getResourceAsStream("/com/izforge/izpack/installer/icons.xml"); // Initialises the parser IXMLParser parser = new XMLParser(); // We get the data IXMLElement data = parser.parse(inXML); // We load the icons Vector<IXMLElement> children = data.getChildrenNamed("icon"); int size = children.size(); for (int i = 0; i < size; i++) { icon = children.get(i); url = InstallerFrame.class.getResource(icon.getAttribute("res")); img = new ImageIcon(url); icons.put(icon.getAttribute("id"), img); } // We load the Swing-specific icons children = data.getChildrenNamed("sysicon"); size = children.size(); for (int i = 0; i < size; i++) { icon = children.get(i); url = InstallerFrame.class.getResource(icon.getAttribute("res")); img = new ImageIcon(url); UIManager.put(icon.getAttribute("id"), img); } } /** * Loads custom icons into the installer. * * @throws Exception */ protected void loadCustomIcons() throws Exception { // We try to load and add a custom langpack. InputStream inXML = null; try { inXML = ResourceManager.getInstance().getInputStream(CUSTOM_ICONS_RESOURCEFILE); } catch (Throwable exception) { Debug.trace("Resource " + CUSTOM_ICONS_RESOURCEFILE + " not defined. No custom icons available."); return; } Debug.trace("Custom icons available."); URL url; ImageIcon img; IXMLElement icon; // Initialises the parser IXMLParser parser = new XMLParser(); // We get the data IXMLElement data = parser.parse(inXML); // We load the icons Vector<IXMLElement> children = data.getChildrenNamed("icon"); int size = children.size(); for (int i = 0; i < size; i++) { icon = children.get(i); url = InstallerFrame.class.getResource(icon.getAttribute("res")); img = new ImageIcon(url); Debug.trace("Icon with id found: " + icon.getAttribute("id")); icons.put(icon.getAttribute("id"), img); } // We load the Swing-specific icons children = data.getChildrenNamed("sysicon"); size = children.size(); for (int i = 0; i < size; i++) { icon = children.get(i); url = InstallerFrame.class.getResource(icon.getAttribute("res")); img = new ImageIcon(url); UIManager.put(icon.getAttribute("id"), img); } } /** * Builds the GUI. */ private void buildGUI() { this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // patch 06/07/2005, // Fabrice Mirabile // Sets the frame icon setIconImage(icons.getImageIcon("JFrameIcon").getImage()); // Prepares the glass pane to block the gui interaction when needed JPanel glassPane = (JPanel) getGlassPane(); glassPane.addMouseListener(new MouseAdapter() {/* Nothing todo */ }); glassPane.addMouseMotionListener(new MouseMotionAdapter() {/* Nothing todo */ }); glassPane.addKeyListener(new KeyAdapter() {/* Nothing todo */ }); glassPane.addFocusListener(new FocusAdapter() {/* Nothing todo */ }); // We set the layout & prepare the constraint object contentPane = (JPanel) getContentPane(); contentPane.setLayout(new BorderLayout()); // layout); // We add the panels container panelsContainer = new JPanel(); panelsContainer.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); panelsContainer.setLayout(new GridLayout(1, 1)); contentPane.add(panelsContainer, BorderLayout.CENTER); // We put the first panel installdata.curPanelNumber = 0; IzPanel panel_0 = installdata.panels.get(0); panelsContainer.add(panel_0); // We add the navigation buttons & labels NavigationHandler navHandler = new NavigationHandler(); JPanel navPanel = new JPanel(); navPanel.setLayout(new BoxLayout(navPanel, BoxLayout.X_AXIS)); navPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8), BorderFactory.createTitledBorder(new EtchedLineBorder(), langpack .getString("installer.madewith") + " ", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font( "Dialog", Font.PLAIN, 10)))); // Add help Button to the navigation panel this.helpButton = ButtonFactory.createButton(langpack.getString("installer.help"), icons .getImageIcon("help"), installdata.buttonsHColor); navPanel.add(this.helpButton); this.helpButton.setName("HelpButton"); this.helpButton.addActionListener(new HelpHandler()); navPanel.add(Box.createHorizontalGlue()); prevButton = ButtonFactory.createButton(langpack.getString("installer.prev"), icons .getImageIcon("stepback"), installdata.buttonsHColor); navPanel.add(prevButton); prevButton.addActionListener(navHandler); navPanel.add(Box.createRigidArea(new Dimension(5, 0))); nextButton = ButtonFactory.createButton(langpack.getString("installer.next"), icons .getImageIcon("stepforward"), installdata.buttonsHColor); navPanel.add(nextButton); nextButton.addActionListener(navHandler); navPanel.add(Box.createRigidArea(new Dimension(5, 0))); quitButton = ButtonFactory.createButton(langpack.getString("installer.quit"), icons .getImageIcon("stop"), installdata.buttonsHColor); navPanel.add(quitButton); quitButton.addActionListener(navHandler); contentPane.add(navPanel, BorderLayout.SOUTH); // create a debug panel if TRACE is enabled if (Debug.isTRACE()) { debugger = new Debugger(installdata, icons, rules); JPanel debugpanel = debugger.getDebugPanel(); if (installdata.guiPrefs.modifier.containsKey("showDebugWindow") && Boolean.valueOf(installdata.guiPrefs.modifier.get("showDebugWindow"))) { JFrame debugframe = new JFrame("Debug information"); debugframe.setContentPane(debugpanel); debugframe.setSize(new Dimension(400, 400)); debugframe.setVisible(true); } else { debugpanel.setPreferredSize(new Dimension(200, 400)); contentPane.add(debugpanel, BorderLayout.EAST); } } try { ImageIcon icon = loadIcon(ICON_RESOURCE, 0, true); if (icon != null) { JPanel imgPanel = new JPanel(); imgPanel.setLayout(new BorderLayout()); imgPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 0)); iconLabel = new JLabel(icon); iconLabel.setBorder(BorderFactory.createLoweredBevelBorder()); imgPanel.add(iconLabel, BorderLayout.NORTH); contentPane.add(imgPanel, BorderLayout.WEST); } } catch (Exception e) { // ignore } loadAndShowImage(0); getRootPane().setDefaultButton(nextButton); callGUIListener(GUIListener.GUI_BUILDED, navPanel); createHeading(navPanel); } private void callGUIListener(int what) { callGUIListener(what, null); } private void callGUIListener(int what, Object param) { Iterator<GUIListener> iter = guiListener.iterator(); while (iter.hasNext()) { (iter.next()).guiActionPerformed(what, param); } } /** * Loads icon for given panel. * * @param resPrefix resources prefix. * @param PanelNo panel id. * @param tryBaseIcon should try to fallback to base icon? * * @return icon image * * @throws ResourceNotFoundException * @throws IOException */ private ImageIcon loadIcon(String resPrefix, int PanelNo, boolean tryBaseIcon) throws ResourceNotFoundException, IOException { ResourceManager rm = ResourceManager.getInstance(); ImageIcon icon = null; String iconext = this.getIconResourceNameExtension(); if (tryBaseIcon) { try { icon = rm.getImageIconResource(resPrefix); } catch (Exception e) // This is not that clean ... { icon = rm.getImageIconResource(resPrefix + "." + PanelNo + iconext); } } else { icon = rm.getImageIconResource(resPrefix + "." + PanelNo + iconext); } return (icon); } /** * Loads icon for given panel id. * * @param resPrefix resource prefix. * @param panelid panel id. * @param tryBaseIcon should try to load base icon? * * @return image icon * * @throws ResourceNotFoundException * @throws IOException */ private ImageIcon loadIcon(String resPrefix, String panelid, boolean tryBaseIcon) throws ResourceNotFoundException, IOException { ResourceManager rm = ResourceManager.getInstance(); ImageIcon icon = null; String iconext = this.getIconResourceNameExtension(); if (tryBaseIcon) { try { icon = rm.getImageIconResource(resPrefix); } catch (Exception e) // This is not that clean ... { icon = rm.getImageIconResource(resPrefix + "." + panelid + iconext); } } else { icon = rm.getImageIconResource(resPrefix + "." + panelid + iconext); } return (icon); } /** * Returns the current set extension to icon resource names. Can be used to change the static * installer image based on user input * * @return a resource extension or an empty string if the variable was not set. */ private String getIconResourceNameExtension() { try { String iconext = this.installdata.getVariable(ICON_RESOURCE_EXT_VARIABLE_NAME); if (iconext == null) { iconext = ""; } else { if ((iconext.length() > 0) && (iconext.charAt(0) != '.')) { iconext = "." + iconext; } } iconext = iconext.trim(); return iconext; } catch (Exception e) { // in case of error, return an empty string return ""; } } private void loadAndShowImage(int panelNo) { loadAndShowImage(iconLabel, ICON_RESOURCE, panelNo); } private void loadAndShowImage(int panelNo, String panelid) { loadAndShowImage(iconLabel, ICON_RESOURCE, panelNo, panelid); } private void loadAndShowImage(JLabel iLabel, String resPrefix, int panelno, String panelid) { ImageIcon icon = null; try { icon = loadIcon(resPrefix, panelid, false); } catch (Exception e) { try { icon = loadIcon(resPrefix, panelno, false); } catch (Exception ex) { try { icon = loadIcon(resPrefix, panelid, true); } catch (Exception e1) { // ignore } } } if (icon != null) { iLabel.setVisible(false); iLabel.setIcon(icon); iLabel.setVisible(true); } } private void loadAndShowImage(JLabel iLabel, String resPrefix, int panelNo) { ImageIcon icon = null; try { icon = loadIcon(resPrefix, panelNo, false); } catch (Exception e) { try { icon = loadIcon(resPrefix, panelNo, true); } catch (Exception e1) { // ignore } } if (icon != null) { iLabel.setVisible(false); iLabel.setIcon(icon); iLabel.setVisible(true); } } /** * Shows the frame. */ private void showFrame() { pack(); setSize(installdata.guiPrefs.width, installdata.guiPrefs.height); setResizable(installdata.guiPrefs.resizable); centerFrame(this); setVisible(true); } /** * Here is persisted the direction of panel traversing. */ private boolean isBack = false; /** * Switches the current panel. * * @param last Description of the Parameter */ protected void switchPanel(int last) { // refresh dynamic variables every time, a panel switch is done this.parentInstaller.refreshDynamicVariables(substitutor, installdata); try { if (installdata.curPanelNumber < last) { isBack = true; } panelsContainer.setVisible(false); IzPanel panel = installdata.panels.get(installdata.curPanelNumber); IzPanel l_panel = installdata.panels.get(last); showHelpButton(panel.canShowHelp()); if (Debug.isTRACE()) { debugger.switchPanel(panel.getMetadata(), l_panel.getMetadata()); } Log.getInstance().addDebugMessage( "InstallerFrame.switchPanel: try switching panel from {0} to {1} ({2} to {3})", new String[]{l_panel.getClass().getName(), panel.getClass().getName(), Integer.toString(last), Integer.toString(installdata.curPanelNumber)}, DebugConstants.PANEL_TRACE, null); // instead of writing data here which leads to duplicated entries in // auto-installation script (bug # 4551), let's make data only immediately before // writing out that script. // l_panel.makeXMLData(installdata.xmlData.getChildAtIndex(last)); // No previos button in the first visible panel if (visiblePanelMapping.get(installdata.curPanelNumber) == 0) { prevButton.setVisible(false); lockPrevButton(); unlockNextButton(); // if we push the button back at the license // panel } // Only the exit button in the last panel. else if (visiblePanelMapping.get(installdata.panels.size()) == installdata.curPanelNumber) { prevButton.setVisible(false); nextButton.setVisible(false); lockNextButton(); } else { if (hasNavigatePrevious(installdata.curPanelNumber, true) != -1) { prevButton.setVisible(true); unlockPrevButton(); } else { lockPrevButton(); prevButton.setVisible(false); } if (hasNavigateNext(installdata.curPanelNumber, true) != -1) { nextButton.setVisible(true); unlockNextButton(); } else { lockNextButton(); nextButton.setVisible(false); } } // With VM version >= 1.5 setting default button one time will not work. // Therefore we set it every panel switch and that also later. But in // the moment it seems so that the quit button will not used as default button. // No idea why... (Klaus Bartz, 06.09.25) SwingUtilities.invokeLater(new Runnable() { public void run() { JButton cdb = null; String buttonName = "next"; if (nextButton.isEnabled()) { cdb = nextButton; quitButton.setDefaultCapable(false); prevButton.setDefaultCapable(false); nextButton.setDefaultCapable(true); } else if (quitButton.isEnabled()) { cdb = quitButton; buttonName = "quit"; quitButton.setDefaultCapable(true); prevButton.setDefaultCapable(false); nextButton.setDefaultCapable(false); } getRootPane().setDefaultButton(cdb); Log.getInstance().addDebugMessage( "InstallerFrame.switchPanel: setting {0} as default button", new String[]{buttonName}, DebugConstants.PANEL_TRACE, null); } }); // Change panels container to the current one. panelsContainer.remove(l_panel); l_panel.panelDeactivate(); panelsContainer.add(panel); if (panel.getInitialFocus() != null) { // Initial focus hint should be performed after current panel // was added to the panels container, else the focus hint will // be ignored. // Give a hint for the initial focus to the system. final Component inFoc = panel.getInitialFocus(); if (JAVA_SPECIFICATION_VERSION < 1.35) { inFoc.requestFocus(); } else { // On java VM version >= 1.5 it works only if // invoke later will be used. SwingUtilities.invokeLater(new Runnable() { public void run() { inFoc.requestFocusInWindow(); } }); } /* * On editable text components position the caret to the end of the cust existent * text. */ if (inFoc instanceof JTextComponent) { JTextComponent inText = (JTextComponent) inFoc; if (inText.isEditable() && inText.getDocument() != null) { inText.setCaretPosition(inText.getDocument().getLength()); } } } performHeading(panel); performHeadingCounter(panel); panel.executePreActivationActions(); panel.panelActivate(); panelsContainer.setVisible(true); Panel metadata = panel.getMetadata(); if ((metadata != null) && (!"UNKNOWN".equals(metadata.getPanelid()))) { loadAndShowImage(visiblePanelMapping.get(installdata.curPanelNumber), metadata .getPanelid()); } else { loadAndShowImage(visiblePanelMapping.get(installdata.curPanelNumber)); } isBack = false; callGUIListener(GUIListener.PANEL_SWITCHED); Log.getInstance().addDebugMessage("InstallerFrame.switchPanel: switched", null, DebugConstants.PANEL_TRACE, null); } catch (Exception err) { err.printStackTrace(); } } /** * Writes the uninstalldata. */ private void writeUninstallData() { // Show whether a separated logfile should be also written or not. String logfile = installdata.getVariable("InstallerFrame.logfilePath"); BufferedWriter extLogWriter = null; if (logfile != null) { if (logfile.toLowerCase().startsWith("default")) { logfile = installdata.info.getUninstallerPath() + "/install.log"; } logfile = IoHelper.translatePath(logfile, new VariableSubstitutor(installdata .getVariables())); File outFile = new File(logfile); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } FileOutputStream out = null; try { out = new FileOutputStream(outFile); } catch (FileNotFoundException e) { Debug.trace("Cannot create logfile!"); Debug.error(e); } if (out != null) { extLogWriter = new BufferedWriter(new OutputStreamWriter(out)); } } try { String condition = installdata.getVariable("UNINSTALLER_CONDITION"); if (condition != null) { if (!RulesEngine.getCondition(condition).isTrue()) { // condition for creating the uninstaller is not fulfilled. return; } } // We get the data UninstallData udata = UninstallData.getInstance(); List files = udata.getUninstalableFilesList(); ZipOutputStream outJar = installdata.uninstallOutJar; if (outJar == null) { return; } // We write the files log outJar.putNextEntry(new ZipEntry("install.log")); BufferedWriter logWriter = new BufferedWriter(new OutputStreamWriter(outJar)); logWriter.write(installdata.getInstallPath()); logWriter.newLine(); Iterator iter = files.iterator(); if (extLogWriter != null) { // Write intern (in uninstaller.jar) and extern log file. while (iter.hasNext()) { String txt = (String) iter.next(); logWriter.write(txt); extLogWriter.write(txt); if (iter.hasNext()) { logWriter.newLine(); extLogWriter.newLine(); } } logWriter.flush(); extLogWriter.flush(); extLogWriter.close(); } else { while (iter.hasNext()) { logWriter.write((String) iter.next()); if (iter.hasNext()) { logWriter.newLine(); } } logWriter.flush(); } outJar.closeEntry(); /* * We write the IPS packages log. */ outJar.putNextEntry(new ZipEntry("ips-install.log")); logWriter = new BufferedWriter(new OutputStreamWriter(outJar)); logWriter.newLine(); for (FmriState fmristate: installdata.installedIPSPackages) { logWriter.write(fmristate.fmri.getName()); logWriter.newLine(); } logWriter.flush(); outJar.closeEntry(); // We write the uninstaller jar file log outJar.putNextEntry(new ZipEntry("jarlocation.log")); logWriter = new BufferedWriter(new OutputStreamWriter(outJar)); logWriter.write(udata.getUninstallerJarFilename()); logWriter.newLine(); logWriter.write(udata.getUninstallerPath()); logWriter.flush(); outJar.closeEntry(); // Write out executables to execute on uninstall outJar.putNextEntry(new ZipEntry("executables")); ObjectOutputStream execStream = new ObjectOutputStream(outJar); iter = udata.getExecutablesList().iterator(); execStream.writeInt(udata.getExecutablesList().size()); while (iter.hasNext()) { ExecutableFile file = (ExecutableFile) iter.next(); execStream.writeObject(file); } execStream.flush(); outJar.closeEntry(); // Write out additional uninstall data // Do not "kill" the installation if there is a problem // with custom uninstall data. Therefore log it to Debug, // but do not throw. Map<String, Object> additionalData = udata.getAdditionalData(); if (additionalData != null && !additionalData.isEmpty()) { Iterator<String> keys = additionalData.keySet().iterator(); HashSet<String> exist = new HashSet<String>(); while (keys != null && keys.hasNext()) { String key = keys.next(); Object contents = additionalData.get(key); if ("__uninstallLibs__".equals(key)) { Iterator nativeLibIter = ((List) contents).iterator(); while (nativeLibIter != null && nativeLibIter.hasNext()) { String nativeLibName = (String) ((List) nativeLibIter.next()).get(0); byte[] buffer = new byte[5120]; long bytesCopied = 0; int bytesInBuffer; outJar.putNextEntry(new ZipEntry("native/" + nativeLibName)); InputStream in = getClass().getResourceAsStream( "/native/" + nativeLibName); while ((bytesInBuffer = in.read(buffer)) != -1) { outJar.write(buffer, 0, bytesInBuffer); bytesCopied += bytesInBuffer; } outJar.closeEntry(); } } else if ("uninstallerListeners".equals(key) || "uninstallerJars".equals(key)) { // It is a ArrayList of ArrayLists which contains the // full // package paths of all needed class files. // First we create a new ArrayList which contains only // the full paths for the uninstall listener self; thats // the first entry of each sub ArrayList. ArrayList<String> subContents = new ArrayList<String>(); // Secound put the class into uninstaller.jar Iterator listenerIter = ((List) contents).iterator(); while (listenerIter.hasNext()) { byte[] buffer = new byte[5120]; long bytesCopied = 0; int bytesInBuffer; CustomData customData = (CustomData) listenerIter.next(); // First element of the list contains the listener // class path; // remind it for later. if (customData.listenerName != null) { subContents.add(customData.listenerName); } Iterator<String> liClaIter = customData.contents.iterator(); while (liClaIter.hasNext()) { String contentPath = liClaIter.next(); if (exist.contains(contentPath)) { continue; } exist.add(contentPath); try { outJar.putNextEntry(new ZipEntry(contentPath)); } catch (ZipException ze) { // Ignore, or ignore not ?? May be it is a // exception because // a doubled entry was tried, then we should // ignore ... Debug.trace("ZipException in writing custom data: " + ze.getMessage()); continue; } InputStream in = getClass().getResourceAsStream("/" + contentPath); if (in != null) { while ((bytesInBuffer = in.read(buffer)) != -1) { outJar.write(buffer, 0, bytesInBuffer); bytesCopied += bytesInBuffer; } } else { Debug.trace("custom data not found: " + contentPath); } outJar.closeEntry(); } } // Third we write the list into the // uninstaller.jar outJar.putNextEntry(new ZipEntry(key)); ObjectOutputStream objOut = new ObjectOutputStream(outJar); objOut.writeObject(subContents); objOut.flush(); outJar.closeEntry(); } else { outJar.putNextEntry(new ZipEntry(key)); if (contents instanceof ByteArrayOutputStream) { ((ByteArrayOutputStream) contents).writeTo(outJar); } else { ObjectOutputStream objOut = new ObjectOutputStream(outJar); objOut.writeObject(contents); objOut.flush(); } outJar.closeEntry(); } } } // write the script files, which will // perform several complement and unindependend uninstall actions ArrayList<String> unInstallScripts = udata.getUninstallScripts(); Iterator<String> unInstallIter = unInstallScripts.iterator(); ObjectOutputStream rootStream; int idx = 0; while (unInstallIter.hasNext()) { outJar.putNextEntry(new ZipEntry(UninstallData.ROOTSCRIPT + Integer.toString(idx))); rootStream = new ObjectOutputStream(outJar); String unInstallScript = (String) unInstallIter.next(); rootStream.writeUTF(unInstallScript); rootStream.flush(); outJar.closeEntry(); idx++; } // Cleanup outJar.flush(); outJar.close(); } catch (Exception err) { err.printStackTrace(); } } /** * Gets the stream to a resource. * * @param res The resource id. * * @return The resource value, null if not found * * @throws Exception */ public InputStream getResource(String res) throws Exception { InputStream result; String basePath = ""; ResourceManager rm = null; try { rm = ResourceManager.getInstance(); basePath = rm.resourceBasePath; } catch (Exception e) { e.printStackTrace(); } result = this.getClass().getResourceAsStream(basePath + res); if (result == null) { throw new ResourceNotFoundException("Warning: Resource not found: " + res); } return result; } /** * Centers a window on screen. * * @param frame The window tp center. */ public void centerFrame(Window frame) { Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint(); Dimension frameSize = frame.getSize(); frame.setLocation(center.x - frameSize.width / 2, center.y - frameSize.height / 2 - 10); } /** * Returns the panels container size. * * @return The panels container size. */ public Dimension getPanelsContainerSize() { return panelsContainer.getSize(); } /** * Sets the parameters of a GridBagConstraints object. * * @param gbc The constraints object. * @param gx The x coordinates. * @param gy The y coordinates. * @param gw The width. * @param wx The x wheight. * @param wy The y wheight. * @param gh Description of the Parameter */ public void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, double wx, double wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } /** * Makes a clean closing. */ public void exit() { if (installdata.canClose || ((!nextButton.isVisible() || !nextButton.isEnabled()) && (!prevButton .isVisible() || !prevButton.isEnabled()))) { // this does nothing if the uninstaller was not included writeUninstallData(); Housekeeper.getInstance().shutDown(0); } else { // The installation is not over if (Unpacker.isDiscardInterrupt() && interruptCount < MAX_INTERRUPT) { // But we should not interrupt. interruptCount++; return; } // Use a alternate message and title if defined. final String mkey = "installer.quit.reversemessage"; final String tkey = "installer.quit.reversetitle"; String message = langpack.getString(mkey); String title = langpack.getString(tkey); // message equal to key -> no alternate message defined. if (message.indexOf(mkey) > -1) { message = langpack.getString("installer.quit.message"); } // title equal to key -> no alternate title defined. if (title.indexOf(tkey) > -1) { title = langpack.getString("installer.quit.title"); } // Now replace variables in message or title. VariableSubstitutor vs = new VariableSubstitutor(installdata.getVariables()); message = vs.substitute(message, null); title = vs.substitute(title, null); int res = JOptionPane .showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION); if (res == JOptionPane.YES_OPTION) { wipeAborted(); Housekeeper.getInstance().shutDown(0); } } } /** * Wipes the written files when you abort the installation. */ protected void wipeAborted() { // We set interrupt to all running Unpacker and wait 40 sec for maximum. // If interrupt is discarded (return value false), return immediately: if (!Unpacker.interruptAll(40000)) { return; } // Wipe the files that had been installed UninstallData u = UninstallData.getInstance(); for (String p : u.getInstalledFilesList()) { File f = new File(p); f.delete(); } } /** * Launches the installation. * * @param listener The installation listener. */ public void install(AbstractUIProgressHandler listener) { IUnpacker unpacker = UnpackerFactory.getUnpacker(this.installdata.info .getUnpackerClassName(), installdata, listener); unpacker.setRules(this.rules); Thread unpackerthread = new Thread(unpacker, "IzPack - Unpacker thread"); unpackerthread.start(); } /** * Writes an XML tree. * * @param root The XML tree to write out. * @param out The stream to write on. * * @throws Exception Description of the Exception */ public void writeXMLTree(IXMLElement root, OutputStream out) throws Exception { IXMLWriter writer = new XMLWriter(out); // fix bug# 4551 // write.write(root); for (int i = 0; i < installdata.panels.size(); i++) { IzPanel panel = installdata.panels.get(i); panel.makeXMLData(installdata.xmlData.getChildAtIndex(i)); } writer.write(root); } /** * Changes the quit button text. If <tt>text</tt> is null, the default quit text is used. * * @param text text to be used for changes */ public void setQuitButtonText(String text) { String text1 = text; if (text1 == null) { text1 = langpack.getString("installer.quit"); } quitButton.setText(text1); } /** * Sets a new icon into the quit button if icons should be used, else nothing will be done. * * @param iconName name of the icon to be used */ public void setQuitButtonIcon(String iconName) { String useButtonIcons = installdata.guiPrefs.modifier.get("useButtonIcons"); if (useButtonIcons == null || "yes".equalsIgnoreCase(useButtonIcons)) { quitButton.setIcon(icons.getImageIcon(iconName)); } } /** * FocusTraversalPolicy objects to handle keybord blocking; the declaration os Object allows to * use a pre version 1.4 VM. */ private Object usualFTP = null; private Object blockFTP = null; /** * Blocks GUI interaction. */ public void blockGUI() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); getGlassPane().setVisible(true); getGlassPane().setEnabled(true); // No traversal handling before VM version 1.4 if (JAVA_SPECIFICATION_VERSION < 1.35) { return; } if (usualFTP == null) { usualFTP = getFocusTraversalPolicy(); } if (blockFTP == null) { blockFTP = new BlockFocusTraversalPolicy(); } setFocusTraversalPolicy((java.awt.FocusTraversalPolicy) blockFTP); getGlassPane().requestFocus(); callGUIListener(GUIListener.GUI_BLOCKED); } /** * Releases GUI interaction. */ public void releaseGUI() { getGlassPane().setEnabled(false); getGlassPane().setVisible(false); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); // No traversal handling before VM version 1.4 if (JAVA_SPECIFICATION_VERSION < 1.35) { return; } setFocusTraversalPolicy((java.awt.FocusTraversalPolicy) usualFTP); callGUIListener(GUIListener.GUI_RELEASED); } /** * Locks the 'previous' button. */ public void lockPrevButton() { prevButton.setEnabled(false); } /** * Locks the 'next' button. */ public void lockNextButton() { nextButton.setEnabled(false); } /** * Unlocks the 'previous' button. */ public void unlockPrevButton() { prevButton.setEnabled(true); } /** * Unlocks the 'next' button. */ public void unlockNextButton() { unlockNextButton(true); } /** * Unlocks the 'next' button. * * @param requestFocus if <code>true</code> focus goes to <code>nextButton</code> */ public void unlockNextButton(boolean requestFocus) { nextButton.setEnabled(true); if (requestFocus) { nextButton.requestFocusInWindow(); getRootPane().setDefaultButton(nextButton); if (this.getFocusOwner() != null) { Debug.trace("Current focus owner: " + this.getFocusOwner().getName()); } if (!(getRootPane().getDefaultButton() == nextButton)) { Debug.trace("Next button not default button, setting..."); quitButton.setDefaultCapable(false); prevButton.setDefaultCapable(false); nextButton.setDefaultCapable(true); getRootPane().setDefaultButton(nextButton); } } } /** * Allows a panel to ask to be skipped. */ public void skipPanel() { if (installdata.curPanelNumber < installdata.panels.size() - 1) { if (isBack) { navigatePrevious(installdata.curPanelNumber); } else { navigateNext(installdata.curPanelNumber, false); } } } /** * Method checks whether conditions are met to show the given panel. * * @param panelnumber the panel number to check * * @return true or false */ public boolean canShow(int panelnumber) { IzPanel panel = installdata.panels.get(panelnumber); Panel panelmetadata = panel.getMetadata(); String panelid = panelmetadata.getPanelid(); Debug.trace("Current Panel: " + panelid); if (panelmetadata.hasCondition()) { Debug.log("Checking panelcondition"); return rules.isConditionTrue(panelmetadata.getCondition()); } else { if (!rules.canShowPanel(panelid, this.installdata.variables)) { // skip panel, if conditions for panel aren't met Debug.log("Skip panel with panelid=" + panelid); // panel should be skipped, so we have to decrement panelnumber for skipping return false; } else { return true; } } } /** * This function moves to the next panel */ public void navigateNext() { // If the button is inactive this indicates that we cannot move // so we don't do the move if (!nextButton.isEnabled()) { return; } this.navigateNext(installdata.curPanelNumber, true); } /** * This function searches for the next available panel, the search begins from given panel+1 * * @param startPanel the starting panel number * @param doValidation whether to do panel validation */ public void navigateNext(int startPanel, boolean doValidation) { if ((installdata.curPanelNumber < installdata.panels.size() - 1)) { // We must trasfer all fields into the variables before // panelconditions try to resolve the rules based on unassigned vars. final IzPanel panel = installdata.panels.get(startPanel); panel.executePreValidationActions(); boolean isValid = doValidation ? panel.panelValidated() : true; panel.executePostValidationActions(); // if this is not here, validation will // occur mutilple times while skipping panels through the recursion if (!isValid) { return; } // We try to show the next panel that we can. int nextPanel = hasNavigateNext(startPanel, false); if (-1 != nextPanel) { installdata.curPanelNumber = nextPanel; switchPanel(startPanel); } } } /** * Check to see if there is another panel that can be navigated to next. This checks the * successive panels to see if at least one can be shown based on the conditions associated with * the panels. * * @param startPanel The panel to check from * @param visibleOnly Only check the visible panels * * @return The panel that we can navigate to next or -1 if there is no panel that we can * navigate next to */ public int hasNavigateNext(int startPanel, boolean visibleOnly) { // Assume that we cannot navigate to another panel int res = -1; // Start from the panel given and check each one until we find one // that we can navigate to or until there are no more panels for (int panel = startPanel + 1; res == -1 && panel < installdata.panels.size(); panel++) { // See if we can show this panel if (!visibleOnly || ((Integer) visiblePanelMapping.get(panel)).intValue() != -1) { if (canShow(panel)) { res = panel; } } } // Return the result return res; } /** * Check to see if there is another panel that can be navigated to previous. This checks the * previous panels to see if at least one can be shown based on the conditions associated with * the panels. * * @param endingPanel The panel to check from * * @return The panel that we can navigate to previous or -1 if there is no panel that we can * navigate previous to */ public int hasNavigatePrevious(int endingPanel, boolean visibleOnly) { // Assume that we cannot navigate to another panel int res = -1; // Start from the panel given and check each one until we find one // that we can navigate to or until there are no more panels for (int panel = endingPanel - 1; res == -1 && panel >= 0; panel--) { // See if we can show this panel if (!visibleOnly || ((Integer) visiblePanelMapping.get(panel)).intValue() != -1) { if (canShow(panel)) { res = panel; } } } // Return the result return res; } /** * This function moves to the previous panel */ public void navigatePrevious() { // If the button is inactive this indicates that we cannot move // so we don't do the move if (!prevButton.isEnabled()) { return; } this.navigatePrevious(installdata.curPanelNumber); } /** * This function switches to the available panel that is just before the given one. * * @param endingPanel the panel to search backwards, beginning from this. */ public void navigatePrevious(int endingPanel) { // We try to show the previous panel that we can. int prevPanel = hasNavigatePrevious(endingPanel, false); if (-1 != prevPanel) { installdata.curPanelNumber = prevPanel; switchPanel(endingPanel); } } /** * Show help Window */ public void showHelp() { installdata.panels.get(installdata.curPanelNumber).showHelp(); } /** * Handles the events from the navigation bar elements. * * @author Julien Ponge */ class NavigationHandler implements ActionListener { /** * Actions handler. * * @param e The event. */ public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == prevButton) { navigatePrevious(); } else if (source == nextButton) { navigateNext(); } else if (source == quitButton) { exit(); } } } class HelpHandler implements ActionListener { /** * Actions handler. * * @param e The event. */ public void actionPerformed(ActionEvent e) { showHelp(); } } /** * The window events handler. * * @author julien created October 27, 2002 */ class WindowHandler extends WindowAdapter { /** * Window close is pressed, * * @param e The event. */ public void windowClosing(WindowEvent e) { // We ask for confirmation exit(); } /** * OLD VERSION We can't avoid the exit here, so don't call exit anywhere else. * * @param e The event. * * public void windowClosing(WindowEvent e) { if (Unpacker.isDiscardInterrupt() && * interruptCount < MAX_INTERRUPT) { // But we should not interrupt. interruptCount++; * return; } // We show an alert anyway if (!installdata.canClose) * JOptionPane.showMessageDialog(null, langpack.getString("installer.quit.message"), * langpack.getString("installer.warning"), JOptionPane.ERROR_MESSAGE); wipeAborted(); * Housekeeper.getInstance().shutDown(0); } */ } /** * A FocusTraversalPolicy that only allows the block panel to have the focus */ private class BlockFocusTraversalPolicy extends java.awt.DefaultFocusTraversalPolicy { private static final long serialVersionUID = 3258413928261169209L; /** * Only accepts the block panel * * @param aComp the component to check * * @return true if aComp is the block panel */ protected boolean accept(Component aComp) { return aComp == getGlassPane(); } } /** * Returns the gui creation listener list. * * @return the gui creation listener list */ public List<GUIListener> getGuiListener() { return guiListener; } /** * Add a listener to the listener list. * * @param listener to be added as gui creation listener */ public void addGuiListener(GUIListener listener) { guiListener.add(listener); } /** * Creates heading labels. * * @param headingLines the number of lines of heading labels * @param back background color (currently not used) */ private void createHeadingLabels(int headingLines, Color back) { // headingLabels are an array which contains the labels for header (0), // description lines and the icon (last). headingLabels = new JLabel[headingLines + 1]; headingLabels[0] = new JLabel(""); // First line ist the "main heading" which should be bold. headingLabels[0].setFont(headingLabels[0].getFont().deriveFont(Font.BOLD)); // Updated by Daniel Azarov, Exadel Inc. // start Color foreground = null; if (installdata.guiPrefs.modifier.containsKey("headingForegroundColor")) { foreground = Color.decode(installdata.guiPrefs.modifier.get("headingForegroundColor")); headingLabels[0].setForeground(foreground); } // end if (installdata.guiPrefs.modifier.containsKey("headingFontSize")) { float fontSize = Float.parseFloat(installdata.guiPrefs.modifier.get("headingFontSize")); if (fontSize > 0.0 && fontSize <= 5.0) { float currentSize = headingLabels[0].getFont().getSize2D(); headingLabels[0].setFont(headingLabels[0].getFont().deriveFont( currentSize * fontSize)); } } if (imageLeft) { headingLabels[0].setAlignmentX(Component.RIGHT_ALIGNMENT); } for (int i = 1; i < headingLines; ++i) { headingLabels[i] = new JLabel(); // Minor headings should be a little bit more to the right. if (imageLeft) { headingLabels[i].setAlignmentX(Component.RIGHT_ALIGNMENT); } else { headingLabels[i].setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 8)); } } } /** * Creates heading panel counter. * * @param back background color * @param navPanel navi JPanel * @param leftHeadingPanel left heading JPanel */ private void createHeadingCounter(Color back, JPanel navPanel, JPanel leftHeadingPanel) { int i; String counterPos = "inHeading"; if (installdata.guiPrefs.modifier.containsKey("headingPanelCounterPos")) { counterPos = installdata.guiPrefs.modifier.get("headingPanelCounterPos"); } // Do not create counter if it should be in the heading, but no heading should be used. if (leftHeadingPanel == null && "inHeading".equalsIgnoreCase(counterPos)) { return; } if (installdata.guiPrefs.modifier.containsKey("headingPanelCounter")) { headingCounterComponent = null; if ("progressbar".equalsIgnoreCase(installdata.guiPrefs.modifier .get("headingPanelCounter"))) { JProgressBar headingProgressBar = new JProgressBar(); headingProgressBar.setStringPainted(true); headingProgressBar.setString(""); headingProgressBar.setValue(0); headingCounterComponent = headingProgressBar; if (imageLeft) { headingCounterComponent.setAlignmentX(Component.RIGHT_ALIGNMENT); } } else if ("text".equalsIgnoreCase(installdata.guiPrefs.modifier .get("headingPanelCounter"))) { JLabel headingCountPanels = new JLabel(" "); headingCounterComponent = headingCountPanels; if (imageLeft) { headingCounterComponent.setAlignmentX(Component.RIGHT_ALIGNMENT); } else { headingCounterComponent.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); } // Updated by Daniel Azarov, Exadel Inc. // start Color foreground = null; if (installdata.guiPrefs.modifier.containsKey("headingForegroundColor")) { foreground = Color.decode(installdata.guiPrefs.modifier .get("headingForegroundColor")); headingCountPanels.setForeground(foreground); } // end } if ("inHeading".equals(counterPos)) { leftHeadingPanel.add(headingCounterComponent); } else if ("inNavigationPanel".equals(counterPos)) { Component[] comps = navPanel.getComponents(); for (i = 0; i < comps.length; ++i) { if (comps[i].equals(prevButton)) { break; } } if (i <= comps.length) { navPanel.add(Box.createHorizontalGlue(), i); navPanel.add(headingCounterComponent, i); } } } } /** * Creates heading icon. * * @param back the color of background around image. * * @return a panel with heading image. */ private JPanel createHeadingIcon(Color back) { // the icon ImageIcon icon = null; try { icon = loadIcon(HEADING_ICON_RESOURCE, 0, true); } catch (Exception e) { // ignore } JPanel imgPanel = new JPanel(); imgPanel.setLayout(new BoxLayout(imgPanel, BoxLayout.Y_AXIS)); // Updated by Daniel Azarov, Exadel Inc. // start int borderSize = 8; if (installdata.guiPrefs.modifier.containsKey("headingImageBorderSize")) { borderSize = Integer.parseInt(installdata.guiPrefs.modifier .get("headingImageBorderSize")); } imgPanel.setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize)); // end if (back != null) { imgPanel.setBackground(back); } JLabel iconLab = new JLabel(icon); if (imageLeft) { imgPanel.add(iconLab, BorderLayout.WEST); } else { imgPanel.add(iconLab, BorderLayout.EAST); } headingLabels[headingLabels.length - 1] = iconLab; return (imgPanel); } /** * Creates a Heading in given Panel. * * @param navPanel a panel */ private void createHeading(JPanel navPanel) { headingPanel = null; int headingLines = 1; // The number of lines can be determined in the config xml file. // The first is the header, additonals are descriptions for the header. if (installdata.guiPrefs.modifier.containsKey("headingLineCount")) { headingLines = Integer.parseInt(installdata.guiPrefs.modifier.get("headingLineCount")); } Color back = null; int i = 0; // It is possible to determine the used background color of the heading panel. if (installdata.guiPrefs.modifier.containsKey("headingBackgroundColor")) { back = Color.decode(installdata.guiPrefs.modifier.get("headingBackgroundColor")); } // Try to create counter if no heading should be used. if (!isHeading(null)) { createHeadingCounter(back, navPanel, null); return; } // See if we should switch the header image to the left side if (installdata.guiPrefs.modifier.containsKey("headingImageOnLeft") && (installdata.guiPrefs.modifier.get("headingImageOnLeft").equalsIgnoreCase("yes") || installdata.guiPrefs.modifier .get("headingImageOnLeft").equalsIgnoreCase("true"))) { imageLeft = true; } // We create the text labels and the needed panels. From inner to outer. // Labels createHeadingLabels(headingLines, back); // Panel which contains the labels JPanel leftHeadingPanel = new JPanel(); if (back != null) { leftHeadingPanel.setBackground(back); } leftHeadingPanel.setLayout(new BoxLayout(leftHeadingPanel, BoxLayout.Y_AXIS)); if (imageLeft) { leftHeadingPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8)); } for (i = 0; i < headingLines; ++i) { leftHeadingPanel.add(headingLabels[i]); } // HeadingPanel counter: this is a label or a progress bar which can be placed // in the leftHeadingPanel or in the navigation bar. It is facultative. If // exist, it shows the current panel number and the amount of panels. createHeadingCounter(back, navPanel, leftHeadingPanel); // It is possible to place an icon on the right side of the heading panel. JPanel imgPanel = createHeadingIcon(back); // The panel for text and icon. JPanel northPanel = new JPanel(); if (back != null) { northPanel.setBackground(back); } northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.X_AXIS)); northPanel.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 0)); if (imageLeft) { northPanel.add(imgPanel); northPanel.add(Box.createHorizontalGlue()); northPanel.add(leftHeadingPanel); } else { northPanel.add(leftHeadingPanel); northPanel.add(Box.createHorizontalGlue()); northPanel.add(imgPanel); } headingPanel = new JPanel(new BorderLayout()); headingPanel.add(northPanel); headingPanel.add(new JSeparator(), BorderLayout.SOUTH); // contentPane.add(northPanel, BorderLayout.NORTH); contentPane.add(headingPanel, BorderLayout.NORTH); } /** * Returns whether this installer frame uses with the given panel a separated heading panel or * not. Be aware, this is an other heading as given by the IzPanel which will be placed in the * IzPanel. This heading will be placed if the gui preferences contains an modifier with the key * "useHeadingPanel" and the value "yes" and there is a message with the key "<class * name>.headline". * * @param caller the IzPanel for which heading should be resolved * * @return whether an heading panel will be used or not */ public boolean isHeading(IzPanel caller) { if (!installdata.guiPrefs.modifier.containsKey("useHeadingPanel") || !(installdata.guiPrefs.modifier.get("useHeadingPanel")).equalsIgnoreCase("yes")) { return (false); } if (caller == null) { return (true); } return (caller.getI18nStringForClass("headline", null) != null); } private void performHeading(IzPanel panel) { int i; int headingLines = 1; if (installdata.guiPrefs.modifier.containsKey("headingLineCount")) { headingLines = Integer.parseInt(installdata.guiPrefs.modifier.get("headingLineCount")); } if (headingLabels == null) { return; } String headline = panel.getI18nStringForClass("headline"); if (headline == null) { headingPanel.setVisible(false); return; } for (i = 0; i <= headingLines; ++i) { if (headingLabels[i] != null) { headingLabels[i].setVisible(false); } } String info; for (i = 0; i < headingLines - 1; ++i) { info = panel.getI18nStringForClass("headinfo" + Integer.toString(i)); if (info == null) { info = " "; } if (info.endsWith(":")) { info = info.substring(0, info.length() - 1) + "."; } headingLabels[i + 1].setText(info); headingLabels[i + 1].setVisible(true); } // Do not forgett the first headline. headingLabels[0].setText(headline); headingLabels[0].setVisible(true); int curPanelNo = visiblePanelMapping.get(installdata.curPanelNumber); if (headingLabels[headingLines] != null) { loadAndShowImage(headingLabels[headingLines], HEADING_ICON_RESOURCE, curPanelNo); headingLabels[headingLines].setVisible(true); } headingPanel.setVisible(true); } private void performHeadingCounter(IzPanel panel) { if (headingCounterComponent != null) { int curPanelNo = visiblePanelMapping.get(installdata.curPanelNumber); int visPanelsCount = visiblePanelMapping.get((visiblePanelMapping .get(installdata.panels.size())).intValue()); StringBuffer buf = new StringBuffer(); buf.append(langpack.getString("installer.step")).append(" ").append(curPanelNo + 1) .append(" ").append(langpack.getString("installer.of")).append(" ").append( visPanelsCount + 1); if (headingCounterComponent instanceof JProgressBar) { JProgressBar headingProgressBar = (JProgressBar) headingCounterComponent; headingProgressBar.setMaximum(visPanelsCount + 1); headingProgressBar.setValue(curPanelNo + 1); headingProgressBar.setString(buf.toString()); } else { ((JLabel) headingCounterComponent).setText(buf.toString()); } } } /** * @return the rules */ public RulesEngine getRules() { return this.rules; } /** * @param rules the rules to set */ public void setRules(RulesEngine rules) { this.rules = rules; } /** * Shows or hides Help button depending on <code>show</code> parameter * * @param show - flag to show or hide Help button */ private void showHelpButton(boolean show) { if (this.helpButton == null) return; this.helpButton.setVisible(show); } }