001/* 002 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved. 003 * 004 * http://www.izforge.com/izpack/ 005 * http://developer.berlios.de/projects/izpack/ 006 * 007 * Copyright 2004 Klaus Bartz 008 * 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 */ 021 022package com.izforge.izpack.panels; 023 024import java.awt.GridBagConstraints; 025import java.awt.Insets; 026import java.awt.event.ActionEvent; 027import java.awt.event.ActionListener; 028import java.io.BufferedReader; 029import java.io.File; 030import java.io.IOException; 031import java.io.InputStream; 032import java.io.InputStreamReader; 033 034import javax.swing.JLabel; 035 036import com.izforge.izpack.installer.InstallData; 037import com.izforge.izpack.installer.InstallerFrame; 038import com.izforge.izpack.installer.IzPanel; 039import com.izforge.izpack.installer.ResourceNotFoundException; 040import com.izforge.izpack.util.AbstractUIHandler; 041import com.izforge.izpack.util.Debug; 042import com.izforge.izpack.util.IoHelper; 043import com.izforge.izpack.util.MultiLineLabel; 044import com.izforge.izpack.util.OsVersion; 045import com.izforge.izpack.util.VariableSubstitutor; 046 047/** 048 * Base class for panels which asks for paths. 049 * 050 * @author Klaus Bartz 051 * 052 */ 053public class PathInputPanel extends IzPanel implements ActionListener 054{ 055 056 /** 057 * 058 */ 059 private static final long serialVersionUID = 3257566217698292531L; 060 061 /** Flag whether the choosen path must exist or not */ 062 protected boolean mustExist = false; 063 064 /** Files which should be exist */ 065 protected String[] existFiles = null; 066 067 /** The path which was chosen */ 068 // protected String chosenPath; 069 /** The path selection sub panel */ 070 protected PathSelectionPanel pathSelectionPanel; 071 072 protected String emptyTargetMsg; 073 074 protected String warnMsg; 075 076 protected static String defaultInstallDir = null; 077 078 /** 079 * The constructor. 080 * 081 * @param parent The parent window. 082 * @param idata The installation data. 083 */ 084 public PathInputPanel(InstallerFrame parent, InstallData idata) 085 { 086 super(parent, idata); 087 // Set default values 088 emptyTargetMsg = getI18nStringForClass("empty_target", "TargetPanel"); 089 warnMsg = getI18nStringForClass("warn", "TargetPanel"); 090 // if( this.class.) 091 092 // Customize the default GridBagConstraints. 093 GridBagConstraints gbConstraint = getDefaultGridBagConstraints(); 094 gbConstraint.gridwidth = GridBagConstraints.REMAINDER; 095 this.setDefaultGridBagConstraints(gbConstraint); 096 String introText = getI18nStringForClass("intro", "PathInputPanel"); 097 if (introText == null || introText.startsWith("PathInputPanel.intro")) introText = ""; 098 // Intro 099 // Create and customize constraint for it. 100 // row 0 column 0 101 gbConstraint = getNextYGridBagConstraints(); 102 // Create component and add it to this panel. 103 MultiLineLabel introLabel = createMultiLineLabel(introText); 104 add(introLabel, gbConstraint); 105 // Label for input 106 // Create and customize constraint for it. 107 // row 1 column 0; is the next Y 108 gbConstraint = getNextYGridBagConstraints(); 109 gbConstraint.gridwidth = GridBagConstraints.RELATIVE; 110 gbConstraint.insets = new Insets(0, 0, 10, 0); 111 // Create component and add it to this panel. 112 JLabel infoLabel = createLabel("info", "TargetPanel", "open", 113 JLabel.LEFT); 114 add(infoLabel, gbConstraint); 115 // Create path selection components and add they to this panel. 116 pathSelectionPanel = new PathSelectionPanel(this, idata); 117 gbConstraint = getNextYGridBagConstraints(); 118 gbConstraint.gridwidth = GridBagConstraints.REMAINDER; 119 gbConstraint.fill = GridBagConstraints.HORIZONTAL; 120 gbConstraint.insets = new Insets(0, 0, 0, 0); 121 add(pathSelectionPanel, gbConstraint); 122 createLayoutBottom(); 123 // Place a footer as last component, if 124 completeGridBagLayout(); 125 } 126 127 /** 128 * This method does nothing. It is called from ctor of PathInputPanel, to give in a derived 129 * class the possibility to add more components under the path input components. 130 */ 131 public void createLayoutBottom() 132 { 133 } 134 135 /** 136 * Actions-handling method. 137 * 138 * @param e The event. 139 */ 140 public void actionPerformed(ActionEvent e) 141 { 142 Object source = e.getSource(); 143 if (source == pathSelectionPanel.getPathInputField()) 144 { 145 parent.navigateNext(); 146 } 147 148 } 149 150 /** 151 * Indicates wether the panel has been validated or not. 152 * 153 * @return Wether the panel has been validated or not. 154 */ 155 public boolean isValidated() 156 { 157 String chosenPath = pathSelectionPanel.getPath(); 158 boolean ok = true; 159 160 // We put a warning if the specified target is nameless 161 if (chosenPath.length() == 0) 162 { 163 if (isMustExist()) 164 { 165 emitError(parent.langpack.getString("installer.error"), parent.langpack 166 .getString("PathInputPanel.required")); 167 return false; 168 } 169 else 170 { 171 ok = emitWarning(parent.langpack.getString("installer.warning"), emptyTargetMsg); 172 } 173 } 174 if (!ok) return ok; 175 176 // Normalize the path 177 File path = new File(chosenPath).getAbsoluteFile(); 178 chosenPath = path.toString(); 179 pathSelectionPanel.setPath(chosenPath); 180 if (isMustExist()) 181 { 182 if (!path.exists()) 183 { 184 emitError(parent.langpack.getString("installer.error"), parent.langpack 185 .getString(getI18nStringForClass("required", "PathInputPanel"))); 186 return false; 187 } 188 if (!pathIsValid()) 189 { 190 emitError(parent.langpack.getString("installer.error"), parent.langpack 191 .getString(getI18nStringForClass("notValid", "PathInputPanel"))); 192 return false; 193 } 194 } 195 else 196 { 197 // We assume, that we would install something into this dir 198 if (!isWriteable()) 199 { 200 emitError(parent.langpack.getString("installer.error"), getI18nStringForClass( 201 "notwritable", "TargetPanel")); 202 return false; 203 } 204 // We put a warning if the directory exists else we warn 205 // that it will be created 206 if (path.exists()) 207 { 208 int res = askQuestion(parent.langpack.getString("installer.warning"), warnMsg, 209 AbstractUIHandler.CHOICES_YES_NO, AbstractUIHandler.ANSWER_YES); 210 ok = res == AbstractUIHandler.ANSWER_YES; 211 } 212 else 213 this.emitNotification(getI18nStringForClass("createdir", "TargetPanel") + "\n" 214 + chosenPath); 215 } 216 return ok; 217 } 218 219 /** 220 * Returns whether the chosen path is true or not. If existFiles are not null, the existence of 221 * it under the choosen path are detected. This method can be also implemented in derived 222 * classes to handle special verification of the path. 223 * 224 * @return true if existFiles are exist or not defined, else false 225 */ 226 protected boolean pathIsValid() 227 { 228 if (existFiles == null) return true; 229 for (int i = 0; i < existFiles.length; ++i) 230 { 231 File path = new File(pathSelectionPanel.getPath(), existFiles[i]).getAbsoluteFile(); 232 if (!path.exists()) return false; 233 } 234 return true; 235 } 236 237 /** 238 * Returns the must exist state. 239 * 240 * @return the must exist state 241 */ 242 public boolean isMustExist() 243 { 244 return mustExist; 245 } 246 247 /** 248 * Sets the must exist state. If it is true, the path must exist. 249 * 250 * @param b must exist state 251 */ 252 public void setMustExist(boolean b) 253 { 254 mustExist = b; 255 } 256 257 /** 258 * Returns the array of strings which are described the files which must exist. 259 * 260 * @return paths of files which must exist 261 */ 262 public String[] getExistFiles() 263 { 264 return existFiles; 265 } 266 267 /** 268 * Sets the paths of files which must exist under the chosen path. 269 * 270 * @param strings paths of files which must exist under the chosen path 271 */ 272 public void setExistFiles(String[] strings) 273 { 274 existFiles = strings; 275 } 276 277 /** 278 * Loads up the "dir" resource associated with TargetPanel. Acceptable dir resource names: 279 * <code> 280 * TargetPanel.dir.macosx 281 * TargetPanel.dir.mac 282 * TargetPanel.dir.windows 283 * TargetPanel.dir.unix 284 * TargetPanel.dir.xxx, 285 * where xxx is the lower case version of System.getProperty("os.name"), 286 * with any spaces replace with underscores 287 * TargetPanel.dir (generic that will be applied if none of above is found) 288 * </code> 289 * As with all IzPack resources, each the above ids should be associated with a separate 290 * filename, which is set in the install.xml file at compile time. 291 */ 292 public static void loadDefaultInstallDir(InstallerFrame parentFrame, 293 InstallData idata) 294 { 295 // Load only once ... 296 if (getDefaultInstallDir() != null) return; 297 BufferedReader br = null; 298 try 299 { 300 InputStream in = null; 301 302 if (OsVersion.IS_WINDOWS) 303 in = parentFrame.getResource("TargetPanel.dir.windows"); 304 305 else if (OsVersion.IS_OSX) 306 in = parentFrame.getResource("TargetPanel.dir.macosx"); 307 else 308 { 309 String os = System.getProperty("os.name"); 310 // first try to look up by specific os name 311 os = os.replace(' ', '_'); // avoid spaces in file names 312 os = os.toLowerCase(); // for consistency among TargetPanel res 313 // files 314 try 315 { 316 in = parentFrame.getResource("TargetPanel.dir.".concat(os)); 317 } 318 catch (ResourceNotFoundException rnfe) 319 {} 320 // if not specific os, try getting generic 'unix' resource file 321 if (in == null) in = parentFrame.getResource("TargetPanel.dir.unix"); 322 323 // if all those failed, try to look up a generic dir file 324 if (in == null) 325 { 326 try 327 { 328 in = parentFrame.getResource("TargetPanel.dir.unix"); 329 } 330 catch (ResourceNotFoundException eee) 331 {} 332 } 333 334 } 335 336 // if all above tests failed, there is no resource file, 337 // so use system default 338 if (in == null) 339 { 340 try 341 { 342 in = parentFrame.getResource("TargetPanel.dir"); 343 } 344 catch (ResourceNotFoundException eee) 345 {} 346 } 347 348 // now read the file, once we've identified which one to read 349 InputStreamReader isr = new InputStreamReader(in); 350 br = new BufferedReader(isr); 351 String line; 352 while ((line = br.readLine()) != null) 353 { 354 line = line.trim(); 355 // use the first non-blank line 356 if (!line.equals("")) break; 357 } 358 defaultInstallDir = line; 359 VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); 360 defaultInstallDir = vs.substitute(defaultInstallDir, null); 361 } 362 catch (Exception e) 363 { 364 defaultInstallDir = null; 365 // leave unset to take the system default set by Installer class 366 } 367 finally 368 { 369 try 370 { 371 if (br != null) br.close(); 372 } 373 catch (IOException ignored) 374 {} 375 } 376 } 377 378 /** 379 * This method determines whether the chosen dir is writeable or not. 380 * 381 * @return whether the chosen dir is writeable or not 382 */ 383 public boolean isWriteable() 384 { 385 File existParent = IoHelper.existingParent(new File(pathSelectionPanel.getPath())); 386 if (existParent == null) return false; 387 // On windows we cannot use canWrite because 388 // it looks to the dos flags which are not valid 389 // on NT or 2k XP or ... 390 if (OsVersion.IS_WINDOWS) 391 { 392 File tmpFile; 393 try 394 { 395 tmpFile = File.createTempFile("izWrTe", ".tmp", existParent); 396 tmpFile.deleteOnExit(); 397 } 398 catch (IOException e) 399 { 400 Debug.trace(e.toString()); 401 return false; 402 } 403 return true; 404 } 405 else 406 return existParent.canWrite(); 407 } 408 409 /** 410 * Returns the default for the installation directory. 411 * 412 * @return the default for the installation directory 413 */ 414 public static String getDefaultInstallDir() 415 { 416 return defaultInstallDir; 417 } 418 419 /** 420 * Sets the default for the installation directory to the given string. 421 * 422 * @param string path for default for the installation directory 423 */ 424 public static void setDefaultInstallDir(String string) 425 { 426 defaultInstallDir = string; 427 } 428 429}