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.io.File; 025import java.util.StringTokenizer; 026 027import com.izforge.izpack.installer.InstallData; 028import com.izforge.izpack.installer.InstallerFrame; 029import com.izforge.izpack.util.AbstractUIHandler; 030import com.izforge.izpack.util.FileExecutor; 031import com.izforge.izpack.util.OsVersion; 032 033/** 034 * Panel which asks for the JDK path. 035 * 036 * @author Klaus Bartz 037 * 038 */ 039public class JDKPathPanel extends PathInputPanel 040{ 041 042 private static final long serialVersionUID = 3257006553327810104L; 043 044 private static final String[] testFiles = new String[] { "lib" + File.separator + "tools.jar"}; 045 046 private String detectedVersion; 047 048 private String minVersion = null; 049 050 private String maxVersion = null; 051 052 private String variableName; 053 054 /** 055 * The constructor. 056 * 057 * @param parent The parent window. 058 * @param idata The installation data. 059 */ 060 public JDKPathPanel(InstallerFrame parent, InstallData idata) 061 { 062 super(parent, idata); 063 setMustExist(true); 064 if(!OsVersion.IS_OSX) 065 setExistFiles(JDKPathPanel.testFiles); 066 setMinVersion(idata.getVariable("JDKPathPanel.minVersion")); 067 setMaxVersion(idata.getVariable("JDKPathPanel.maxVersion")); 068 setVariableName("JDKPath"); 069 } 070 071 /** 072 * Indicates wether the panel has been validated or not. 073 * 074 * @return Wether the panel has been validated or not. 075 */ 076 public boolean isValidated() 077 { 078 if (super.isValidated()) 079 { 080 if (verifyVersion()) 081 { 082 idata.setVariable(getVariableName(), pathSelectionPanel.getPath()); 083 return (true); 084 } 085 // Bad version detected. 086 String min = getMinVersion(); 087 String max = getMaxVersion(); 088 StringBuffer message = new StringBuffer(); 089 message.append(parent.langpack.getString("JDKPathPanel.badVersion1")).append( 090 getDetectedVersion()).append( 091 parent.langpack.getString("JDKPathPanel.badVersion2")); 092 if (min != null && max != null) 093 message.append(min).append(" - ").append(max); 094 else if (min != null) 095 message.append(" >= ").append(min); 096 else if (max != null) message.append(" <= ").append(max); 097 098 message.append(parent.langpack.getString("JDKPathPanel.badVersion3")); 099 if (askQuestion(parent.langpack.getString("installer.warning"), message.toString(), 100 AbstractUIHandler.CHOICES_YES_NO, AbstractUIHandler.ANSWER_NO) == AbstractUIHandler.ANSWER_YES) 101 { 102 idata.setVariable(getVariableName(), pathSelectionPanel.getPath()); 103 return (true); 104 } 105 } 106 return (false); 107 } 108 109 /** Called when the panel becomes active. */ 110 public void panelActivate() 111 { 112 // Resolve the default for chosenPath 113 super.panelActivate(); 114 String chosenPath; 115 // The variable will be exist if we enter this panel 116 // second time. We would maintain the previos 117 // selected path. 118 if (idata.getVariable(getVariableName()) != null) 119 chosenPath = idata.getVariable(getVariableName()); 120 else 121 // Try the JAVA_HOME as child dir of the jdk path 122 chosenPath = (new File(idata.getVariable("JAVA_HOME"))).getParent(); 123 // Set the path for method pathIsValid ... 124 pathSelectionPanel.setPath(chosenPath); 125 126 if (!pathIsValid() || !verifyVersion()) chosenPath = ""; 127 // Set the default to the path selection panel. 128 pathSelectionPanel.setPath(chosenPath); 129 String var = idata.getVariable("JDKPathPanel.skipIfValid"); 130 // Should we skip this panel? 131 if (chosenPath.length() > 0 && var != null && var.equalsIgnoreCase("yes")) 132 { 133 idata.setVariable(getVariableName(), chosenPath); 134 parent.skipPanel(); 135 } 136 137 } 138 139 private final boolean verifyVersion() 140 { 141 String min = getMinVersion(); 142 String max = getMaxVersion(); 143 // No min and max, version always ok. 144 if (min == null && max == null) return (true); 145 146 if (!pathIsValid()) return (false); 147 // No get the version ... 148 // We cannot look to the version of this vm because we should 149 // test the given JDK VM. 150 String[] params = { 151 pathSelectionPanel.getPath() + File.separator + "bin" + File.separator + "java", 152 "-version"}; 153 String[] output = new String[2]; 154 FileExecutor fe = new FileExecutor(); 155 fe.executeCommand(params, output); 156 // "My" VM writes the version on stderr :-( 157 String vs = (output[0].length() > 0) ? output[0] : output[1]; 158 if (min != null) 159 { 160 if (!compareVersions(vs, min, true, 4, 4, "__NO_NOT_IDENTIFIER_")) return (false); 161 } 162 if (max != null) 163 if (!compareVersions(vs, max, false, 4, 4, "__NO_NOT_IDENTIFIER_")) return (false); 164 return (true); 165 } 166 167 private final boolean compareVersions(String in, String template, boolean isMin, 168 int assumedPlace, int halfRange, String useNotIdentifier) 169 { 170 StringTokenizer st = new StringTokenizer(in, " \t\n\r\f\""); 171 int i; 172 int currentRange = 0; 173 String[] interestedEntries = new String[halfRange + halfRange]; 174 for (i = 0; i < assumedPlace - halfRange; ++i) 175 if (st.hasMoreTokens()) st.nextToken(); // Forget this entries. 176 177 for (i = 0; i < halfRange + halfRange; ++i) 178 { // Put the interesting Strings into an intermediaer array. 179 if (st.hasMoreTokens()) 180 { 181 interestedEntries[i] = st.nextToken(); 182 currentRange++; 183 } 184 } 185 186 for (i = 0; i < currentRange; ++i) 187 { 188 if (useNotIdentifier != null && interestedEntries[i].indexOf(useNotIdentifier) > -1) 189 continue; 190 if (Character.getType(interestedEntries[i].charAt(0)) != Character.DECIMAL_DIGIT_NUMBER) 191 continue; 192 break; 193 } 194 if (i == currentRange) 195 { 196 detectedVersion = "<not found>"; 197 return (false); 198 } 199 detectedVersion = interestedEntries[i]; 200 StringTokenizer current = new StringTokenizer(interestedEntries[i], "._-"); 201 StringTokenizer needed = new StringTokenizer(template, "._-"); 202 while (needed.hasMoreTokens()) 203 { 204 // Current can have no more tokens if needed has more 205 // and if a privious token was not accepted as good version. 206 // e.g. 1.4.2_02 needed, 1.4.2 current. The false return 207 // will be right here. Only if e.g. needed is 1.4.2_00 the 208 // return value will be false, but zero should not b e used 209 // at the last version part. 210 if (!current.hasMoreTokens()) return (false); 211 String cur = current.nextToken(); 212 String nee = needed.nextToken(); 213 int curVal = 0; 214 int neededVal = 0; 215 try 216 { 217 curVal = Integer.parseInt(cur); 218 neededVal = Integer.parseInt(nee); 219 } 220 catch (NumberFormatException nfe) 221 { // A number format exception will be raised if 222 // there is a non numeric part in the version, 223 // e.g. 1.5.0_beta. The verification runs only into 224 // this deep area of version number (fourth sub place) 225 // if all other are equal to the given limit. Then 226 // it is right to return false because e.g. 227 // the minimal needed version will be 1.5.0.2. 228 return (false); 229 } 230 if (curVal < neededVal) if (isMin) 231 return (false); 232 else 233 return (true); 234 if (Integer.parseInt(cur) > Integer.parseInt(nee)) if (isMin) 235 return (true); 236 else 237 return (false); 238 } 239 return (true); 240 } 241 242 /** 243 * Returns the current detected version. 244 * 245 * @return the current detected version 246 */ 247 public String getDetectedVersion() 248 { 249 return detectedVersion; 250 } 251 252 /** 253 * Returns the current used maximum version. 254 * 255 * @return the current used maximum version 256 */ 257 public String getMaxVersion() 258 { 259 return maxVersion; 260 } 261 262 /** 263 * Returns the current used minimum version. 264 * 265 * @return the current used minimum version 266 */ 267 public String getMinVersion() 268 { 269 return minVersion; 270 } 271 272 /** 273 * Sets the given value as current detected version. 274 * 275 * @param string version string to be used as detected version 276 */ 277 protected void setDetectedVersion(String string) 278 { 279 detectedVersion = string; 280 } 281 282 /** 283 * Sets the given value as maximum for version control. 284 * 285 * @param string version string to be used as maximum 286 */ 287 protected void setMaxVersion(String string) 288 { 289 maxVersion = string; 290 } 291 292 /** 293 * Sets the given value as minimum for version control. 294 * 295 * @param string version string to be used as minimum 296 */ 297 protected void setMinVersion(String string) 298 { 299 minVersion = string; 300 } 301 302 /** 303 * Returns the name of the variable which should be used for the path. 304 * 305 * @return the name of the variable which should be used for the path 306 */ 307 public String getVariableName() 308 { 309 return variableName; 310 } 311 312 /** 313 * Sets the name for the variable which should be set with the path. 314 * 315 * @param string variable name to be used 316 */ 317 public void setVariableName(String string) 318 { 319 variableName = string; 320 } 321 322 /* 323 * (non-Javadoc) 324 * 325 * @see com.izforge.izpack.installer.IzPanel#getSummaryBody() 326 */ 327 public String getSummaryBody() 328 { 329 return (idata.getVariable(getVariableName())); 330 } 331}