1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.mrep; 28 29 import java.awt.Component; 30 import java.io.File; 31 32 import javax.swing.Icon; 33 import javax.swing.JFileChooser; 34 import javax.swing.filechooser.FileFilter; 35 import javax.swing.filechooser.FileView; 36 37 import com.sun.javatest.report.Report; 38 import com.sun.javatest.tool.IconFactory; 39 import com.sun.javatest.tool.UIFactory; 40 import com.sun.javatest.util.FileInfoCache; 41 42 /** 43 * A custom JFileChooser, for a user to choose a report directory. 44 */ 45 // 46 // see also com.sun.javatest.tool.WorkDirChooser 47 // 48 class ReportDirChooser extends JFileChooser 49 { 50 // the following is a workaround to force the Report class to 51 // be safely loaded, before the JFileChooser starts running its background 52 // thread, exposing a JVM bug in class loading. 53 static { 54 Class<?> reportClass = Report.class; 55 } 56 57 /** 58 * Create a ReportDirChooser, initially showing the user's current directory. 59 */ 60 public ReportDirChooser() { 61 this(new File(System.getProperty("user.dir"))); 62 } 63 64 /** 65 * Create a ReportDirChooser, initially showing a given directory. 66 * @param initialDir the initial directory to be shown 67 */ 68 public ReportDirChooser(File initialDir) { 69 super(initialDir); 70 uif = new UIFactory(this, null); // no helpBroker required 71 72 icon = IconFactory.getSelectableFolderIcon(); 73 74 // we want a filter that only selects directories 75 setAcceptAllFileFilterUsed(false); 76 setFileFilter(new RDC_FileFilter()); 77 78 // we want a file view that displays special icons for 79 // report directories and sets directories non-traversable, 80 // so that double clicking in the list view will select 81 // (ie choose) them 82 setFileView(new RDC_FileView()); 83 84 // we need FILES in the mode so that non-traversable 85 // items appear in the list 86 // -- see BasicDirectoryModel.LoadFilesThread 87 // we need DIRECTORIES in the mode so that directories 88 // (eg report directories) can be selected (ie chosen) 89 // -- see BasicFileChooserUI.ApproveSelectionAction 90 setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 91 92 // these parameters are still not ideal ... 93 // approveSelection(File) below gets called for all directories: 94 // we still have to redispatch according to whether it is a report 95 // directory or not. 96 } 97 98 /** 99 * A constant to indicate that a new report directory is to be created. 100 * @see #setMode 101 */ 102 public static final int NEW = 0; 103 104 /** 105 * A constant to indicate that an existing report directory is to be opened. 106 * @see #setMode 107 */ 108 public static final int OPEN = 1; 109 110 /** 111 * Set whether the chooser is to be used to create a new report directory 112 * or to open an existing report directory. 113 * @param mode a constant to indicate how the chooser is to operate 114 * @see #NEW 115 * @see #OPEN 116 */ 117 public void setMode(int mode) { 118 this.mode = mode; 119 switch (mode) { 120 case NEW: 121 setApproveButtonText(uif.getI18NString("rdc.new.btn")); 122 setApproveButtonToolTipText(uif.getI18NString("rdc.new.tip")); 123 setDialogTitle(uif.getI18NString("rdc.new.title")); 124 break; 125 case OPEN: 126 setApproveButtonText(uif.getI18NString("rdc.open.btn")); 127 setApproveButtonToolTipText(uif.getI18NString("rdc.open.tip")); 128 setDialogTitle(uif.getI18NString("rdc.open.title")); 129 break; 130 default: 131 throw new IllegalStateException(); 132 } 133 } 134 135 /** 136 * Get the report directory that was most recently selected by the user. 137 * @return the report directory that was most recently selected by the user 138 * @see #showDialog 139 */ 140 public File getSelectedReportDirectory() { 141 return reportDir; 142 } 143 144 /** 145 * Show a dialog to allow the user to select a report directory. 146 * If a report directory is selected, it can be accessed via getSelectedReportDirectory. 147 * @param parent the component to be used at the parent of this dialog 148 * @return an integer signifying how the dialog was dismissed 149 * (APPROVE_OPTION or CANCEL_OPTION). 150 * @see #APPROVE_OPTION 151 * @see #CANCEL_OPTION 152 * @see #getSelectedReportDirectory 153 */ 154 public int showDialog(Component parent) { 155 return showDialog(parent, getApproveButtonText()); 156 } 157 158 public void approveSelection() { 159 // the validity of the selection depends on whether the 160 // selected directory is to be created or opened. 161 File file = getSelectedFile(); 162 if (mode == NEW) 163 approveNewSelection(file); 164 else 165 approveOpenSelection(file); 166 } 167 168 //------------------------------------------------------------------------- 169 170 private void approveNewSelection(File file) { 171 if (file.exists()) { 172 if (isReportDirectory(file) || isEmptyDirectory(file)) { 173 // create new report in existing or empty report directory 174 reportDir = file; 175 super.approveSelection(); 176 } 177 else if (file.isDirectory()) { 178 // the directory exists, but is neither a report dir nor empty: open it 179 setCurrentDirectory(file); 180 setSelectedFile(null); 181 setSelectedFiles(null); 182 } 183 else { 184 uif.showError("rdc.notADir", file); 185 } 186 } 187 else { 188 // create new report in new report directory 189 reportDir = file; 190 super.approveSelection(); 191 } 192 } 193 194 //------------------------------------------------------------------------- 195 196 private void approveOpenSelection(File file) { 197 if (file.exists()) { 198 if (isReportDirectory(file)) { 199 reportDir = file; 200 super.approveSelection(); 201 } 202 else if (isDirectory(file)) { 203 // the directory exists, but is not a report dir: open it 204 setCurrentDirectory(file); 205 setSelectedFile(null); 206 setSelectedFiles(null); 207 } 208 else 209 uif.showError("rdc.notADir", file); 210 } 211 else 212 uif.showError("rdc.cantOpen", file); 213 } 214 215 //------------------------------------------------------------------------- 216 217 private boolean isDirectory(File f) { 218 return (f.isDirectory()); 219 } 220 221 private boolean isReportDirectory(File f) { 222 if (isIgnoreable(f)) 223 return false; 224 225 Boolean b = cache.get(f); 226 if (b == null) { 227 boolean v = Report.isReportDirectory(f); 228 String[] l = f.list(); 229 if (l != null) { 230 for (int i = 0; i < l.length; i++) { 231 if (l[i].endsWith(".html")) { 232 v = true; 233 } 234 } 235 } 236 cache.put(f, v); 237 return v; 238 } 239 else 240 return b; 241 } 242 243 private boolean isEmptyDirectory(File f) { 244 return (f.isDirectory() && f.list().length == 0); 245 } 246 247 private boolean isIgnoreable(File f) { 248 // Take care not touch the floppy disk drive on Windows 249 // because if there is no disk in it, the user will get a dialog. 250 // Root directories (such as A:) have an empty name, 251 // so use that to avoid touching the file itself. 252 // This means we can't put a work directory in the root of 253 // the file system, but that is a lesser inconvenience 254 // than those floppy dialogs! 255 return (f.getName().equals("")); 256 } 257 258 private FileInfoCache cache = new FileInfoCache(); 259 260 private int mode; 261 private File reportDir; 262 private UIFactory uif; 263 private Icon icon; 264 265 private class RDC_FileView extends FileView { 266 public String getDescription(File f) { 267 return null; 268 } 269 270 public Icon getIcon(File f) { 271 return (isReportDirectory(f) ? icon : null); 272 } 273 274 public String getName(File f) { 275 // Take care to get names of file system roots correct 276 String name = f.getName(); 277 return (name.length() == 0 ? f.getPath() : name); 278 } 279 280 public String getTypeDescription(File f) { 281 return null; 282 } 283 284 public Boolean isTraversable(File f) { 285 return (isDirectory(f) && !isReportDirectory(f) ? Boolean.TRUE : Boolean.FALSE); 286 } 287 } 288 289 private class RDC_FileFilter extends FileFilter { 290 public boolean accept(File f) { 291 return (isDirectory(f)); 292 } 293 294 public String getDescription() { 295 return uif.getI18NString("rdc.ft"); 296 } 297 } 298 }