001: /*
002: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
003: *
004: * http://izpack.org/
005: * http://izpack.codehaus.org/
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: package com.izforge.izpack.panels;
022:
023: import java.awt.event.ActionEvent;
024: import java.awt.event.ActionListener;
025: import java.io.BufferedReader;
026: import java.io.File;
027: import java.io.IOException;
028: import java.io.InputStream;
029: import java.io.InputStreamReader;
030:
031: import com.izforge.izpack.gui.IzPanelLayout;
032: import com.izforge.izpack.installer.InstallData;
033: import com.izforge.izpack.installer.InstallerFrame;
034: import com.izforge.izpack.installer.IzPanel;
035: import com.izforge.izpack.installer.ResourceNotFoundException;
036: import com.izforge.izpack.util.AbstractUIHandler;
037: import com.izforge.izpack.util.Debug;
038: import com.izforge.izpack.util.IoHelper;
039: import com.izforge.izpack.util.OsVersion;
040: import com.izforge.izpack.util.VariableSubstitutor;
041:
042: /**
043: * Base class for panels which asks for paths.
044: *
045: * @author Klaus Bartz
046: * @author Jeff Gordon
047: *
048: */
049: public class UserPathInputPanel extends IzPanel implements
050: ActionListener {
051:
052: /**
053: *
054: */
055: private InstallerFrame _parent;
056: private InstallData _idata;
057: private static final long serialVersionUID = 3257566217698292531L;
058: /** Flag whether the choosen path must exist or not */
059: protected boolean _mustExist = false;
060: protected boolean _loadedDefaultDir = false;
061: /** Files which should be exist */
062: protected String[] _existFiles = null;
063: /** The path which was chosen */
064: // protected String chosenPath;
065: /** The path selection sub panel */
066: protected UserPathSelectionPanel _pathSelectionPanel;
067: protected String _error;
068: protected String _warn;
069: protected String _emptyTargetMsg;
070: protected String _warnMsg;
071: protected String _reqMsg;
072: protected String _notValidMsg;
073: protected String _notWritableMsg;
074: protected String _createDirMsg;
075: protected String _defaultDir = null;
076: protected String _this Panel = "UserPathInputPanel";
077: protected String _defaultPanelName = "TargetPanel";
078: protected String _targetPanel = "UserPathPanel";
079: protected String _variableName = "pathVariable";
080:
081: /**
082: * The constructor.
083: *
084: * @param parent The parent window.
085: * @param idata The installation data.
086: */
087: public UserPathInputPanel(InstallerFrame parent, InstallData idata,
088: String targetPanel, String variableName) {
089: super (parent, idata, new IzPanelLayout());
090: _parent = parent;
091: _idata = idata;
092: _targetPanel = targetPanel;
093: _variableName = variableName;
094: // Set default values
095: loadMessages();
096: String introText = getI18nStringForClass("extendedIntro",
097: _this Panel);
098: if (introText == null || introText.endsWith("extendedIntro")
099: || introText.indexOf('$') > -1) {
100: introText = getI18nStringForClass("intro", _this Panel);
101: if (introText == null || introText.endsWith("intro")) {
102: introText = "";
103: }
104: }
105: // Intro
106: // row 0 column 0
107: add(createMultiLineLabel(introText));
108: add(IzPanelLayout.createParagraphGap());
109: // Label for input
110: // row 1 column 0.
111: add(createLabel("info", _targetPanel, "open", LEFT, true),
112: NEXT_LINE);
113: // Create path selection components and add they to this panel.
114: _pathSelectionPanel = new UserPathSelectionPanel(this , idata,
115: _targetPanel, _variableName);
116: add(_pathSelectionPanel, NEXT_LINE);
117: createLayoutBottom();
118: getLayoutHelper().completeLayout();
119: }
120:
121: /**
122: * This method does nothing. It is called from ctor of UserPathInputPanel, to give in a derived
123: * class the possibility to add more components under the path input components.
124: */
125: public void createLayoutBottom() {
126: // Derived classes implements additional elements.
127: }
128:
129: /**
130: * Actions-handling method.
131: *
132: * @param e The event.
133: */
134: public void actionPerformed(ActionEvent e) {
135: Object source = e.getSource();
136: if (source == _pathSelectionPanel.getPathInputField()) {
137: parent.navigateNext();
138: }
139:
140: }
141:
142: private void loadMessages() {
143: _error = parent.langpack.getString("installer.error");
144: _warn = parent.langpack.getString("installer.warning");
145: _reqMsg = getMessage("required");
146: _emptyTargetMsg = getMessage("empty_target");
147: _warnMsg = getMessage("exists_warn");
148: _notValidMsg = getMessage("notValid");
149: _notWritableMsg = getMessage("notwritable");
150: _createDirMsg = getMessage("createdir");
151: }
152:
153: private String getMessage(String type) {
154: String msg = null;
155: msg = getI18nStringForClass(type, _targetPanel);
156: if (msg == null) {
157: msg = getI18nStringForClass(type, _defaultPanelName);
158: }
159: return msg;
160: }
161:
162: /**
163: * Indicates whether the panel has been validated or not.
164: *
165: * @return Whether the panel has been validated or not.
166: */
167: public boolean isValidated() {
168: String chosenPath = _pathSelectionPanel.getPath();
169: boolean ok = true;
170: // We put a warning if the specified target is nameless
171: if (chosenPath.length() == 0) {
172: if (isMustExist()) {
173: emitError(_error, _reqMsg);
174: return false;
175: }
176: ok = emitWarning(_warn, _emptyTargetMsg);
177: }
178: if (!ok) {
179: return ok;
180: }
181: // Normalize the path
182: File path = new File(chosenPath).getAbsoluteFile();
183: chosenPath = path.toString();
184: _pathSelectionPanel.setPath(chosenPath);
185: if (isMustExist()) {
186: if (!path.exists()) {
187: emitError(_error, _reqMsg);
188: return false;
189: }
190: if (!pathIsValid()) {
191: emitError(_error, _notValidMsg);
192: return false;
193: }
194: } else {
195: // We assume, that we would install something into this dir
196: if (!isWriteable()) {
197: emitError(_error, _notWritableMsg);
198: return false;
199: }
200: // We put a warning if the directory exists else we warn
201: // that it will be created
202: if (path.exists()) {
203: int res = askQuestion(_warn, _warnMsg,
204: AbstractUIHandler.CHOICES_YES_NO,
205: AbstractUIHandler.ANSWER_YES);
206: ok = res == AbstractUIHandler.ANSWER_YES;
207: } else {
208: ok = this .emitNotificationFeedback(_createDirMsg + "\n"
209: + chosenPath);
210: }
211: }
212: return ok;
213: }
214:
215: /**
216: * Returns whether the chosen path is true or not. If existFiles are not null, the existence of
217: * it under the choosen path are detected. This method can be also implemented in derived
218: * classes to handle special verification of the path.
219: *
220: * @return true if existFiles are exist or not defined, else false
221: */
222: protected boolean pathIsValid() {
223: if (_existFiles == null) {
224: return true;
225: }
226: for (String _existFile : _existFiles) {
227: File path = new File(_pathSelectionPanel.getPath(),
228: _existFile).getAbsoluteFile();
229: if (!path.exists()) {
230: return false;
231: }
232: }
233: return true;
234: }
235:
236: /**
237: * Returns the must exist state.
238: *
239: * @return the must exist state
240: */
241: public boolean isMustExist() {
242: return _mustExist;
243: }
244:
245: /**
246: * Sets the must exist state. If it is true, the path must exist.
247: *
248: * @param b must exist state
249: */
250: public void setMustExist(boolean b) {
251: _mustExist = b;
252: }
253:
254: /**
255: * Returns the array of strings which are described the files which must exist.
256: *
257: * @return paths of files which must exist
258: */
259: public String[] getExistFiles() {
260: return _existFiles;
261: }
262:
263: /**
264: * Sets the paths of files which must exist under the chosen path.
265: *
266: * @param strings paths of files which must exist under the chosen path
267: */
268: public void setExistFiles(String[] strings) {
269: _existFiles = strings;
270: }
271:
272: /**
273: * "targetPanel" is typically the class name of the implementing panel, such as
274: * "UserPathPanel" or "TargetPanel" set when the class is created, but can be set
275: * with setDefaultDir().
276: * Loads up the "dir" resource associated with targetPanel. Acceptable dir resource names:
277: * <code>
278: * targetPanel.dir.macosx
279: * targetPanel.dir.mac
280: * targetPanel.dir.windows
281: * targetPanel.dir.unix
282: * targetPanel.dir.xxx,
283: * where xxx is the lower case version of System.getProperty("os.name"),
284: * with any spaces replace with underscores
285: * targetPanel.dir (generic that will be applied if none of above is found)
286: * </code>
287: * As with all IzPack resources, each the above ids should be associated with a separate
288: * filename, which is set in the install.xml file at compile time.
289: */
290: private void loadDefaultDir() {
291: // Load only once ...
292: if (!(_loadedDefaultDir)) {
293: BufferedReader br = null;
294: try {
295: InputStream in = null;
296: if (OsVersion.IS_WINDOWS) {
297: try {
298: in = _parent.getResource(_targetPanel
299: + ".dir.windows");
300: } catch (ResourceNotFoundException rnfe) {
301: }//it's usual, that the resource does not exist
302: } else if (OsVersion.IS_OSX) {
303: try {
304: in = _parent.getResource(_targetPanel
305: + ".dir.macosx");
306: } catch (ResourceNotFoundException rnfe) {
307: }//it's usual, that the resource does not exist
308: } else {
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 files
313: try {
314: in = _parent.getResource(_targetPanel
315: + ".dir.".concat(os));
316: } catch (ResourceNotFoundException rnfe) {
317: }
318: // if not specific os, try getting generic 'unix' resource file
319: if (in == null) {
320: try {
321: in = _parent.getResource(_targetPanel
322: + ".dir.unix");
323: } catch (ResourceNotFoundException eee) {
324: }
325: }
326: }
327: // if all above tests failed, there is no resource file,
328: // so use system default
329: if (in == null) {
330: try {
331: in = _parent.getResource(_targetPanel + ".dir");
332: } catch (ResourceNotFoundException eee) {
333: }
334: }
335: if (in != null) {
336: // now read the file, once we've identified which one to read
337: InputStreamReader isr = new InputStreamReader(in);
338: br = new BufferedReader(isr);
339: String line;
340: while ((line = br.readLine()) != null) {
341: line = line.trim();
342: // use the first non-blank line
343: if (!"".equals(line)) {
344: break;
345: }
346: }
347: _defaultDir = line;
348: VariableSubstitutor vs = new VariableSubstitutor(
349: idata.getVariables());
350: _defaultDir = vs.substitute(_defaultDir, null);
351: }
352: } catch (Exception e) {
353: //mar: what's the common way to log an exception ?
354: e.printStackTrace();
355: _defaultDir = null;
356: // leave unset to take the system default set by Installer class
357: } finally {
358: try {
359: if (br != null) {
360: br.close();
361: }
362: } catch (IOException ignored) {
363: }
364: }
365: }
366: _loadedDefaultDir = true;
367: }
368:
369: /**
370: * This method determines whether the chosen dir is writeable or not.
371: *
372: * @return whether the chosen dir is writeable or not
373: */
374: public boolean isWriteable() {
375: File existParent = IoHelper.existingParent(new File(
376: _pathSelectionPanel.getPath()));
377: if (existParent == null) {
378: return false;
379: }
380: // On windows we cannot use canWrite because
381: // it looks to the dos flags which are not valid
382: // on NT or 2k XP or ...
383: if (OsVersion.IS_WINDOWS) {
384: File tmpFile;
385: try {
386: tmpFile = File.createTempFile("izWrTe", ".tmp",
387: existParent);
388: tmpFile.deleteOnExit();
389: } catch (IOException e) {
390: Debug.trace(e.toString());
391: return false;
392: }
393: return true;
394: }
395: return existParent.canWrite();
396: }
397:
398: /**
399: * Returns the default for the directory.
400: *
401: * @return the default for the directory
402: */
403: public String getDefaultDir() {
404: if (_defaultDir == null && (!(_loadedDefaultDir))) {
405: loadDefaultDir();
406: }
407: return _defaultDir;
408: }
409:
410: /**
411: * Sets the default for the directory to the given string.
412: *
413: * @param string path for default directory
414: */
415: public void setDefaultDir(String string) {
416: _defaultDir = string;
417: }
418:
419: /**
420: * Returns the panel name extending this class.
421: * Used for looking up localized text and resources.
422: *
423: * @return the default for the directory
424: */
425: public String getTargetPanel() {
426: return _targetPanel;
427: }
428:
429: /**
430: * Sets the panel name extending this class.
431: * Used for looking up localized text and resources.
432: *
433: * @param string path for default directory
434: */
435: public void setTargetPanel(String string) {
436: _targetPanel = string;
437: }
438: }
|