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

Last change on this file since 7053 was 7037, checked in by Don-vip, 10 years ago

see #8465 - last batch of try-with-resources

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