source: josm/trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java@ 6049

Last change on this file since 6049 was 5874, checked in by Don-vip, 11 years ago

see #8570, #7406 - I/O refactorization:

  • Move different file copy functions to Utils.copyFile (to be replaced later by Files.copy when switching to Java 7)
  • Replace all Utils.close(XXX) by Utils.close(Closeable) -> impacted plugins: commandline, mirrored_download, opendata, piclayer
  • Add new Utils.close(ZipFile)
  • Use of Utils.close almost everywhere
  • Javadoc fixes
  • Property svn:eol-style set to native
File size: 14.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.io.BufferedReader;
11import java.io.File;
12import java.io.FileReader;
13import java.io.IOException;
14import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.HashSet;
19import java.util.LinkedHashSet;
20import java.util.LinkedList;
21import java.util.List;
22import java.util.Set;
23import java.util.regex.Matcher;
24import java.util.regex.Pattern;
25
26import javax.swing.JFileChooser;
27import javax.swing.JOptionPane;
28import javax.swing.SwingUtilities;
29import javax.swing.filechooser.FileFilter;
30
31import org.openstreetmap.josm.Main;
32import org.openstreetmap.josm.gui.HelpAwareOptionPane;
33import org.openstreetmap.josm.gui.PleaseWaitRunnable;
34import org.openstreetmap.josm.gui.help.HelpUtil;
35import org.openstreetmap.josm.io.AllFormatsImporter;
36import org.openstreetmap.josm.io.FileImporter;
37import org.openstreetmap.josm.io.OsmTransferException;
38import org.openstreetmap.josm.tools.MultiMap;
39import org.openstreetmap.josm.tools.Shortcut;
40import org.openstreetmap.josm.tools.Utils;
41import org.xml.sax.SAXException;
42
43/**
44 * Open a file chooser dialog and select an file to import. Then call the gpx-import driver. Finally
45 * open an internal frame into the main window with the gpx data shown.
46 *
47 * @author imi
48 */
49public class OpenFileAction extends DiskAccessAction {
50
51 /**
52 * The {@link ExtensionFileFilter} matching .url files
53 */
54 public static final ExtensionFileFilter urlFileFilter = new ExtensionFileFilter("url", "url", tr("URL Files") + " (*.url)");
55
56 /**
57 * Create an open action. The name is "Open a file".
58 */
59 public OpenFileAction() {
60 super(tr("Open..."), "open", tr("Open a file."),
61 Shortcut.registerShortcut("system:open", tr("File: {0}", tr("Open...")), KeyEvent.VK_O, Shortcut.CTRL));
62 putValue("help", ht("/Action/Open"));
63 }
64
65 public void actionPerformed(ActionEvent e) {
66 JFileChooser fc = createAndOpenFileChooser(true, true, null);
67 if (fc == null)
68 return;
69 File[] files = fc.getSelectedFiles();
70 OpenFileTask task = new OpenFileTask(Arrays.asList(files), fc.getFileFilter());
71 task.setRecordHistory(true);
72 Main.worker.submit(task);
73 }
74
75 @Override
76 protected void updateEnabledState() {
77 setEnabled(! Main.applet);
78 }
79
80 /**
81 * Open a list of files. The complete list will be passed to batch importers.
82 * @param fileList A list of files
83 */
84 static public void openFiles(List<File> fileList) {
85 openFiles(fileList, false);
86 }
87
88 static public void openFiles(List<File> fileList, boolean recordHistory) {
89 OpenFileTask task = new OpenFileTask(fileList, null);
90 task.setRecordHistory(recordHistory);
91 Main.worker.submit(task);
92 }
93
94 static public class OpenFileTask extends PleaseWaitRunnable {
95 private List<File> files;
96 private List<File> successfullyOpenedFiles = new ArrayList<File>();
97 private FileFilter fileFilter;
98 private boolean canceled;
99 private boolean recordHistory = false;
100
101 public OpenFileTask(List<File> files, FileFilter fileFilter, String title) {
102 super(title, false /* don't ignore exception */);
103 this.files = new ArrayList<File>(files);
104 this.fileFilter = fileFilter;
105 }
106
107 public OpenFileTask(List<File> files, FileFilter fileFilter) {
108 this(files, fileFilter, tr("Opening files"));
109 }
110
111 /**
112 * save filename in history (for list of recently opened files)
113 * default: false
114 */
115 public void setRecordHistory(boolean recordHistory) {
116 this.recordHistory = recordHistory;
117 }
118
119 public boolean isRecordHistory() {
120 return recordHistory;
121 }
122
123 @Override
124 protected void cancel() {
125 this.canceled = true;
126 }
127
128 @Override
129 protected void finish() {
130 // do nothing
131 }
132
133 protected void alertFilesNotMatchingWithImporter(Collection<File> files, FileImporter importer) {
134 final StringBuffer msg = new StringBuffer();
135 msg.append("<html>");
136 msg.append(
137 trn(
138 "Cannot open {0} file with the file importer ''{1}''.",
139 "Cannot open {0} files with the file importer ''{1}''.",
140 files.size(),
141 files.size(),
142 importer.filter.getDescription()
143 )
144 ).append("<br>");
145 msg.append("<ul>");
146 for (File f: files) {
147 msg.append("<li>").append(f.getAbsolutePath()).append("</li>");
148 }
149 msg.append("</ul>");
150
151 HelpAwareOptionPane.showMessageDialogInEDT(
152 Main.parent,
153 msg.toString(),
154 tr("Warning"),
155 JOptionPane.WARNING_MESSAGE,
156 HelpUtil.ht("/Action/Open#ImporterCantImportFiles")
157 );
158 }
159
160 protected void alertFilesWithUnknownImporter(Collection<File> files) {
161 final StringBuffer msg = new StringBuffer();
162 msg.append("<html>");
163 msg.append(
164 trn(
165 "Cannot open {0} file because file does not exist or no suitable file importer is available.",
166 "Cannot open {0} files because files do not exist or no suitable file importer is available.",
167 files.size(),
168 files.size()
169 )
170 ).append("<br>");
171 msg.append("<ul>");
172 for (File f: files) {
173 msg.append("<li>");
174 msg.append(f.getAbsolutePath());
175 msg.append(" (<i>");
176 msg.append(f.exists() ? tr("no importer") : tr("does not exist"));
177 msg.append("</i>)</li>");
178 }
179 msg.append("</ul>");
180
181 HelpAwareOptionPane.showMessageDialogInEDT(
182 Main.parent,
183 msg.toString(),
184 tr("Warning"),
185 JOptionPane.WARNING_MESSAGE,
186 HelpUtil.ht("/Action/Open#MissingImporterForFiles")
187 );
188 }
189
190 @Override
191 protected void realRun() throws SAXException, IOException, OsmTransferException {
192 if (files == null || files.isEmpty()) return;
193
194 /**
195 * Find the importer with the chosen file filter
196 */
197 FileImporter chosenImporter = null;
198 for (FileImporter importer : ExtensionFileFilter.importers) {
199 if (fileFilter == importer.filter) {
200 chosenImporter = importer;
201 }
202 }
203 /**
204 * If the filter hasn't been changed in the dialog, chosenImporter is null now.
205 * When the filter has been set explicitly to AllFormatsImporter, treat this the same.
206 */
207 if (chosenImporter instanceof AllFormatsImporter) {
208 chosenImporter = null;
209 }
210 getProgressMonitor().setTicksCount(files.size());
211
212 if (chosenImporter != null) {
213 // The importer was explicitly chosen, so use it.
214 List<File> filesNotMatchingWithImporter = new LinkedList<File>();
215 List<File> filesMatchingWithImporter = new LinkedList<File>();
216 for (final File f : files) {
217 if (!chosenImporter.acceptFile(f)) {
218 if (f.isDirectory()) {
219 SwingUtilities.invokeLater(new Runnable() {
220 public void run() {
221 JOptionPane.showMessageDialog(Main.parent, tr(
222 "<html>Cannot open directory ''{0}''.<br>Please select a file.</html>",
223 f.getAbsolutePath()), tr("Open file"), JOptionPane.ERROR_MESSAGE);
224 }
225 });
226 // TODO when changing to Java 6: Don't cancel the
227 // task here but use different modality. (Currently 2 dialogs
228 // would block each other.)
229 return;
230 } else {
231 filesNotMatchingWithImporter.add(f);
232 }
233 } else {
234 filesMatchingWithImporter.add(f);
235 }
236 }
237
238 if (!filesNotMatchingWithImporter.isEmpty()) {
239 alertFilesNotMatchingWithImporter(filesNotMatchingWithImporter, chosenImporter);
240 }
241 if (!filesMatchingWithImporter.isEmpty()) {
242 importData(chosenImporter, filesMatchingWithImporter);
243 }
244 } else {
245 // find appropriate importer
246 MultiMap<FileImporter, File> importerMap = new MultiMap<FileImporter, File>();
247 List<File> filesWithUnknownImporter = new LinkedList<File>();
248 List<File> urlFiles = new LinkedList<File>();
249 FILES: for (File f : files) {
250 for (FileImporter importer : ExtensionFileFilter.importers) {
251 if (importer.acceptFile(f)) {
252 importerMap.put(importer, f);
253 continue FILES;
254 }
255 }
256 if (urlFileFilter.accept(f)) {
257 urlFiles.add(f);
258 } else {
259 filesWithUnknownImporter.add(f);
260 }
261 }
262 if (!filesWithUnknownImporter.isEmpty()) {
263 alertFilesWithUnknownImporter(filesWithUnknownImporter);
264 }
265 List<FileImporter> importers = new ArrayList<FileImporter>(importerMap.keySet());
266 Collections.sort(importers);
267 Collections.reverse(importers);
268
269 Set<String> fileHistory = new LinkedHashSet<String>();
270 Set<String> failedAll = new HashSet<String>();
271
272 for (FileImporter importer : importers) {
273 List<File> files = new ArrayList<File>(importerMap.get(importer));
274 importData(importer, files);
275 // suppose all files will fail to load
276 List<File> failedFiles = new ArrayList<File>(files);
277
278 if (recordHistory && !importer.isBatchImporter()) {
279 // remove the files which didn't fail to load from the failed list
280 failedFiles.removeAll(successfullyOpenedFiles);
281 for (File f : successfullyOpenedFiles) {
282 fileHistory.add(f.getCanonicalPath());
283 }
284 for (File f : failedFiles) {
285 failedAll.add(f.getCanonicalPath());
286 }
287 }
288 }
289
290 for (File urlFile: urlFiles) {
291 try {
292 BufferedReader reader = new BufferedReader(new FileReader(urlFile));
293 String line;
294 while ((line = reader.readLine()) != null) {
295 Matcher m = Pattern.compile(".*(http://.*)").matcher(line);
296 if (m.matches()) {
297 String url = m.group(1);
298 Main.main.menu.openLocation.openUrl(false, url);
299 }
300 }
301 Utils.close(reader);
302 } catch (Exception e) {
303 System.err.println(e.getMessage());
304 }
305 }
306
307 if (recordHistory) {
308 Collection<String> oldFileHistory = Main.pref.getCollection("file-open.history");
309 fileHistory.addAll(oldFileHistory);
310 // remove the files which failed to load from the list
311 fileHistory.removeAll(failedAll);
312 int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
313 Main.pref.putCollectionBounded("file-open.history", maxsize, fileHistory);
314 }
315 }
316 }
317
318 public void importData(FileImporter importer, List<File> files) {
319 if (importer.isBatchImporter()) {
320 if (canceled) return;
321 String msg = trn("Opening {0} file...", "Opening {0} files...", files.size(), files.size());
322 getProgressMonitor().setCustomText(msg);
323 getProgressMonitor().indeterminateSubTask(msg);
324 if (importer.importDataHandleExceptions(files, getProgressMonitor().createSubTaskMonitor(files.size(), false))) {
325 successfullyOpenedFiles.addAll(files);
326 }
327 } else {
328 for (File f : files) {
329 if (canceled) return;
330 getProgressMonitor().indeterminateSubTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath()));
331 if (importer.importDataHandleExceptions(f, getProgressMonitor().createSubTaskMonitor(1, false))) {
332 successfullyOpenedFiles.add(f);
333 }
334 }
335 }
336 }
337
338 /**
339 * Replies the list of files that have been successfully opened.
340 * @return The list of files that have been successfully opened.
341 */
342 public List<File> getSuccessfullyOpenedFiles() {
343 return successfullyOpenedFiles;
344 }
345 }
346}
Note: See TracBrowser for help on using the repository browser.