Changeset 31927 in osm


Ignore:
Timestamp:
2016-01-03T16:18:19+01:00 (9 years ago)
Author:
donvip
Message:

[josm_commandline] improve file copy

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/CommandLine/src/CommandLine/CommandLine.java

    r31869 r31927  
    3030import java.awt.event.MouseEvent;
    3131import java.io.File;
    32 import java.io.FileOutputStream;
    3332import java.io.IOException;
    3433import java.io.InputStream;
     
    3837import java.net.URL;
    3938import java.nio.charset.StandardCharsets;
     39import java.nio.file.Files;
     40import java.nio.file.StandardCopyOption;
    4041import java.util.ArrayList;
    4142import java.util.Collection;
     
    7778
    7879public class CommandLine extends Plugin {
    79         protected JTextField textField;
    80         protected JTextField historyField;
    81         private String prefix;
    82         private Mode mode;
    83         private ArrayList<Command> commands;
    84         private JMenu commandMenu;
    85         protected Command currentCommand;
    86         protected String commandSymbol;
    87         protected History history;
    88         protected MapFrame currentMapFrame;
    89         protected MapMode previousMode;
    90 
    91         static final String pluginDir = Main.pref.getPluginsDirectory().getAbsolutePath() + "/CommandLine/";
    92 
    93         @SuppressWarnings("serial")
    94         public CommandLine(PluginInformation info) {
    95                 super(info);
    96                 commandSymbol = ": ";
    97                 history = new History(100);
    98                 historyField = new DisableShortcutsOnFocusGainedTextField();
    99                 textField = new DisableShortcutsOnFocusGainedTextField() {
    100                         @Override
    101                         protected void processKeyEvent(KeyEvent e) {
    102                                 if (e.getID() == KeyEvent.KEY_PRESSED) {
    103                                         int code = e.getKeyCode();
    104                                         if (code == KeyEvent.VK_ENTER) {
    105                                                 String commandText = textField.getText().substring(prefix.length());
    106                                                 switch (mode) {
    107                                                 case IDLE:
    108                                                         if (commandText.isEmpty()) {
    109                                                                 commandText = history.getLastItem();
    110                                                         } else {
    111                                                                 history.addItem(commandText);
    112                                                         }
    113                                                         Command command = findCommand(commandText, true);
    114                                                         if (command != null) {
    115                                                                 startCommand(command);
    116                                                         } else {
    117                                                                 setMode(Mode.IDLE);
    118                                                         }
    119                                                         break;
    120                                                 case SELECTION:
    121                                                         if (currentMapFrame.mapMode instanceof WayAction || currentMapFrame.mapMode instanceof NodeAction || currentMapFrame.mapMode instanceof RelationAction || currentMapFrame.mapMode instanceof AnyAction) {
    122                                                                 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
    123                                                                 if (selected.size() > 0)
    124                                                                         loadParameter(selected, true);
    125                                                         }
    126                                                         else {
    127                                                                 loadParameter(commandText, currentCommand.parameters.get(currentCommand.currentParameterNum).maxInstances == 1);
    128                                                         }
    129                                                         break;
    130                                                 case ADJUSTMENT:
    131                                                         break;
    132                                                 }
    133                                                 e.consume();
    134                                         }
    135                                         else if (code == KeyEvent.VK_UP) {
    136                                                 textField.setText(prefix + history.getPrevItem());
    137                                                 e.consume();
    138                                         }
    139                                         else if (code == KeyEvent.VK_DOWN) {
    140                                                 textField.setText(prefix + history.getNextItem());
    141                                                 e.consume();
    142                                         }
    143                                         else if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT) {
    144                                                 if (textField.getCaretPosition() <= prefix.length())
    145                                                         e.consume();
    146                                         }
    147                                         else if (code == KeyEvent.VK_HOME) {
    148                                                 setCaretPosition(prefix.length());
    149                                                 e.consume();
    150                                         }
    151                                         else if (code == KeyEvent.VK_ESCAPE) {
    152                                                 if (textField.getText().length() == prefix.length() && mode == Mode.IDLE)
    153                                                         deactivate();
    154                                                 else
    155                                                         endInput();
    156                                                 e.consume();
    157                                         }
    158                                         else if (code == KeyEvent.VK_DELETE || code == KeyEvent.VK_RIGHT || code == KeyEvent.VK_END) {
    159                                         }
    160                                         else {
    161                                                 e.consume();
    162                                         }
    163                                         if (textField.getCaretPosition() < prefix.length() || (textField.getSelectionStart() < prefix.length() && textField.getSelectionStart() > 0) )
    164                                                 e.consume();
    165                                 }
    166                                 if (e.getID() == KeyEvent.KEY_TYPED)
    167                                         if (textField.getCaretPosition() < prefix.length() || (textField.getSelectionStart() < prefix.length() && textField.getSelectionStart() > 0) )
    168                                                 e.consume();
    169                                 super.processKeyEvent(e);
    170                                 if (textField.getText().length() < prefix.length()) { // Safe
    171                                         setMode(mode);
    172                                 }
    173                                 if (e.getID() == KeyEvent.KEY_TYPED) {
    174                                         if (e.getKeyChar() > 'A' && e.getKeyChar() < 'z') {
    175                                                 Command command = findCommand(textField.getText().substring(prefix.length()), false);
    176                                                 if (command != null) {
    177                                                         int currentPos = textField.getSelectionStart() == 0 ? textField.getCaretPosition() : textField.getSelectionStart();
    178                                                         textField.setText(prefix + command.name);
    179                                                         textField.setCaretPosition(currentPos);
    180                                                         textField.select(currentPos, prefix.length() + command.name.length());
    181                                                 }
    182                                         }
    183                                 }
    184                         }
    185                         @Override
    186                         protected void processMouseEvent(MouseEvent e) {
    187                                 super.processMouseEvent(e);
    188                                 if (e.getButton() == MouseEvent.BUTTON1 && e.getID() == MouseEvent.MOUSE_RELEASED) {
    189                                         if (textField.getSelectionStart() > 0 && textField.getSelectionStart() < prefix.length())
    190                                                 textField.setSelectionStart(prefix.length());
    191                                         else if (textField.getCaretPosition() < prefix.length())
    192                                                 textField.setCaretPosition(prefix.length());
    193                                 }
    194                         }
    195                 };
    196 
    197                 if (Main.main.menu != null) {
    198                         commandMenu = Main.main.menu.addMenu("Commands", tr("Commands"), KeyEvent.VK_O, Main.main.menu.getDefaultMenuPos(), ht("/Plugin/CommandLine"));
    199                         MainMenu.add(commandMenu, new CommandLineAction(this));
    200                 }
    201                 loadCommands();
    202                 setMode(Mode.IDLE);
    203         }
    204 
    205         public void startCommand(String commandName) {
    206                 Command command = findCommand(commandName, true);
    207                 if (command != null) {
    208                         startCommand(command);
    209                 }
    210         }
    211 
    212         protected void startCommand(Command command) {
    213                 if (Main.map == null)
    214                         return;
    215                 DataSet ds = Main.main.getCurrentDataSet();
    216                 if (ds == null)
    217                         return;
    218                 currentCommand = command;
    219                 currentCommand.resetLoading();
    220                 parseSelection(ds.getSelected());
    221                 if (!(Main.map.mapMode instanceof AnyAction || Main.map.mapMode instanceof DummyAction || Main.map.mapMode instanceof LengthAction || Main.map.mapMode instanceof NodeAction || Main.map.mapMode instanceof PointAction || Main.map.mapMode instanceof RelationAction || Main.map.mapMode instanceof WayAction)) {
    222                         previousMode = Main.map.mapMode;
    223                 }
    224                 if (currentCommand.currentParameterNum < currentCommand.parameters.size())
    225                         setMode(Mode.SELECTION);
    226                 else
    227                         runTool();
    228         }
    229 
    230         @Override
    231         public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
    232                 currentMapFrame = newFrame;
    233                 if (oldFrame == null && newFrame != null) {
    234                         JToolBar tb = new JToolBar();
    235                         tb.setLayout(new BorderLayout());
    236                         tb.setFloatable(false);
    237                         tb.setOrientation(JToolBar.HORIZONTAL);
    238                         tb.add(historyField, BorderLayout.NORTH);
    239                         tb.add(textField, BorderLayout.SOUTH);
    240                         currentMapFrame.add(tb, BorderLayout.NORTH);
    241                         printHistory("Loaded CommandLine, version " + getPluginInformation().version);
    242                 }
    243         }
    244 
    245         protected void printHistory(final String text) {
    246                 SwingUtilities.invokeLater(new Runnable() {
    247                         @Override
    248                         public void run() {
    249                                 historyField.setText(text);
    250                         }
    251                 });
    252         }
    253 
    254         private void loadCommands() {
    255                 commands = (new Loader(getPluginDir())).load();
    256                 if (commands.isEmpty()) {
    257                         if (!GraphicsEnvironment.isHeadless() && JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Main.parent,
    258                                         tr("No command has been found. Would you like to download and install default commands now?"),
    259                                         tr("No command found"), JOptionPane.YES_NO_CANCEL_OPTION)) {
    260                                 try {
    261                                         downloadAndInstallDefaultCommands();
    262                                         commands = (new Loader(getPluginDir())).load();
    263                                         JOptionPane.showMessageDialog(Main.parent, tr("Default commands have been successfully installed"),
    264                                                         tr("Success"), JOptionPane.INFORMATION_MESSAGE);
    265                                 } catch (IOException e) {
    266                                         Main.warn(e);
    267                                         JOptionPane.showMessageDialog(Main.parent,
    268                                                         tr("Failed to download and install default commands.\n\nError: {0}", e.getMessage()),
    269                                                         tr("Warning"), JOptionPane.WARNING_MESSAGE);
    270                                 }
    271                         }
    272                 }
    273                 for (Command command : commands) {
    274                         commandMenu.add(new CommandAction(command, this));
    275                 }
    276         }
    277 
    278         private void downloadAndInstallDefaultCommands() throws IOException {
    279                 String url = Main.pref.get("commandline.default.commands.url",
    280                                 "https://github.com/Foxhind/JOSM-CommandLine-commands/archive/master.zip");
    281                 try (ZipInputStream zis = new ZipInputStream(HttpClient.create(new URL(url)).connect().getContent(), StandardCharsets.UTF_8)) {
    282                         File dir = new File(getPluginDir());
    283                         if (!dir.exists()) {
    284                                 dir.mkdirs();
    285                         }
    286                         ZipEntry entry = null;
    287                         while ( (entry = zis.getNextEntry()) != null ) {
    288                                 if (!entry.isDirectory()) {
    289                                         String name = entry.getName();
    290                                         if (name.contains("/")) {
    291                                                 name = name.substring(name.lastIndexOf("/"));
    292                                         }
    293                                         File file = new File(dir + File.separator + name);
    294                                         Main.info("Installing command file: "+file);
    295                                         if (!file.createNewFile()) {
    296                                                 throw new IOException("Could not create file: " + file.getAbsolutePath());
    297                                         }
    298                                         // Write file
    299                                         try (FileOutputStream fos = new FileOutputStream(file)) {
    300                                                 Utils.copyStream(zis, fos);
    301                                         }
    302                                         // Set last modification date
    303                                         long time = entry.getTime();
    304                                         if (time > -1) {
    305                                                 file.setLastModified(time);
    306                                         }
    307                                 }
    308                         }
    309                 }
    310         }
    311 
    312         private Command findCommand(String text, boolean strict) {
    313                 for (int i = 0; i < commands.size(); i++) {
    314                         if (strict) {
    315                                 if ( commands.get(i).name.equalsIgnoreCase(text) ) {
    316                                         return commands.get(i);
    317                                 }
    318                         } else if ( commands.get(i).name.toLowerCase().startsWith( text.toLowerCase() ) && text.length() > 1 ) {
    319                                 return commands.get(i);
    320                         }
    321                 }
    322                 return null;
    323         }
    324 
    325         protected void setMode(Mode targetMode) {
    326                 DataSet currentDataSet = Main.main.getCurrentDataSet();
    327                 if (currentDataSet != null) {
    328                         currentDataSet.clearSelection();
    329                         Main.map.mapView.repaint();
    330                 }
    331                 if (targetMode == Mode.IDLE) {
    332                         mode = Mode.IDLE;
    333                         currentCommand = null;
    334                         prefix = tr("Command") + commandSymbol;
    335                         textField.setText(prefix);
    336                 }
    337                 else if (targetMode == Mode.SELECTION) {
    338                         mode = Mode.SELECTION;
    339                         Parameter currentParameter = currentCommand.parameters.get(currentCommand.currentParameterNum);
    340                         prefix = tr(currentParameter.description == null ? currentParameter.name : currentParameter.description);
    341                         if (currentParameter.getRawValue() instanceof Relay)
    342                                 prefix = prefix + " (" + ((Relay)(currentParameter.getRawValue())).getOptionsString() + ")";
    343                         prefix += commandSymbol;
    344                         String value = currentParameter.getValue();
    345                         textField.setText(prefix + value);
    346                         Type currentType = currentParameter.type;
    347                         MapMode action = null;
    348                         switch (currentType) {
    349                         case POINT:
    350                                 action = new PointAction(currentMapFrame, this);
    351                                 break;
    352                         case WAY:
    353                                 action = new WayAction(currentMapFrame, this);
    354                                 break;
    355                         case NODE:
    356                                 action = new NodeAction(currentMapFrame, this);
    357                                 break;
    358                         case RELATION:
    359                                 action = new RelationAction(currentMapFrame, this);
    360                                 break;
    361                         case ANY:
    362                                 action = new AnyAction(currentMapFrame, this);
    363                                 break;
    364                         case LENGTH:
    365                                 action = new LengthAction(currentMapFrame, this);
    366                                 break;
    367                         case USERNAME:
    368                                 loadParameter(Main.pref.get("osm-server.username", null), true);
    369                                 action = new DummyAction(currentMapFrame, this);
    370                                 break;
    371                         case IMAGERYURL:
    372                                 Layer layer = Main.map.mapView.getActiveLayer();
    373                                 if (layer != null) {
    374                                         if (!(layer instanceof ImageryLayer)) {
    375                                                 List<ImageryLayer> imageryLayers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
    376                                                 if (imageryLayers.size() == 1) {
    377                                                         layer = imageryLayers.get(0);
    378                                                 }
    379                                                 else {
    380                                                         endInput();
    381                                                         return;
    382                                                 }
    383                                         }
    384                                 }
    385                                 ImageryInfo info = ((ImageryLayer)layer).getInfo();
    386                                 String url = info.getUrl();
    387                                 String itype = info.getImageryType().getTypeString();
    388                                 loadParameter((url.equals("") ? itype : url), true);
    389                                 action = new DummyAction(currentMapFrame, this);
    390                                 break;
    391                         case IMAGERYOFFSET:
    392                                 Layer olayer = Main.map.mapView.getActiveLayer();
    393                                 if (olayer != null) {
    394                                         if (!(olayer instanceof ImageryLayer)) {
    395                                                 List<ImageryLayer> imageryLayers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
    396                                                 if (imageryLayers.size() == 1) {
    397                                                         olayer = imageryLayers.get(0);
    398                                                 }
    399                                                 else {
    400                                                         endInput();
    401                                                         return;
    402                                                 }
    403                                         }
    404                                 }
    405                                 loadParameter((String.valueOf(((ImageryLayer)olayer).getDx()) + "," + String.valueOf(((ImageryLayer)olayer).getDy())), true);
    406                                 action = new DummyAction(currentMapFrame, this);
    407                                 break;
    408                         default:
    409                                 action = new DummyAction(currentMapFrame, this);
    410                                 break;
    411                         }
    412                         currentMapFrame.selectMapMode(action);
    413                         activate();
    414                         textField.select(prefix.length(), textField.getText().length());
    415                 }
    416                 else if (targetMode == Mode.PROCESSING) {
    417                         mode = Mode.PROCESSING;
    418                         prefix = tr("Processing...");
    419                         textField.setText(prefix);
    420                         Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    421                 }
    422         }
    423 
    424         public void activate() {
    425                 textField.requestFocus();
    426                 textField.setCaretPosition(textField.getText().length());
    427         }
    428 
    429         public void deactivate() {
    430                 Main.map.mapView.requestFocus();
    431         }
    432 
    433         public void abortInput() {
    434                 printHistory(tr("Aborted") + ".");
    435                 endInput();
    436         }
    437 
    438         public void endInput() {
    439                 setMode(Mode.IDLE);
    440                 Main.map.selectMapMode(previousMode);
    441                 Main.map.mapView.repaint();
    442         }
    443 
    444         public void loadParameter(Object obj, boolean next) {
    445                 if (currentCommand.loadObject(obj)) {
    446                         if (currentCommand.hasNextParameter()) {
    447                                 if (next) {
    448                                         Parameter currentParameter = currentCommand.parameters.get(currentCommand.currentParameterNum);
    449                                         String prefix = tr(currentParameter.description == null ? currentParameter.name : currentParameter.description);
    450                                         prefix += commandSymbol;
    451                                         String value = currentParameter.getValue();
    452                                         printHistory(prefix + value);
    453                                         currentCommand.nextParameter();
    454                                         setMode(Mode.SELECTION);
    455                                 }
    456                         } else {
    457                                 runTool();
    458                         }
    459                 } else {
    460                         Main.info("Invalid argument");
    461                         endInput();
    462                 }
    463         }
    464 
    465         private void parseSelection(Collection<OsmPrimitive> selection) {
    466                 boolean ok = false;
    467                 for (OsmPrimitive obj : selection) {
    468                         ok = currentCommand.loadObject(obj);
    469                         if (!ok)
    470                                 break;
    471                 }
    472                 if (ok) {
    473                         currentCommand.nextParameter();
    474                 } else {
    475                         currentCommand.resetLoading();
    476                 }
    477         }
    478 
    479         private class ToolProcess {
    480                 public Process process;
    481                 public volatile boolean running;
    482         }
    483 
    484         // Thanks to Upliner
    485         public void runTool() {
    486                 setMode(Mode.PROCESSING);
    487                 String commandToRun = currentCommand.run;
    488                 final boolean tracks = currentCommand.tracks;
    489                 final ArrayList<Parameter> parameters = currentCommand.parameters;
    490 
    491                 for (Parameter parameter : currentCommand.parameters) {
    492                         commandToRun = commandToRun.replace("{" + parameter.name + "}", parameter.getValue());
    493                 }
    494                 for (Parameter parameter : currentCommand.optParameters) {
    495                         commandToRun = commandToRun.replace("{" + parameter.name + "}", parameter.getValue());
    496                 }
    497                 String[] listToRun = commandToRun.split(" ");
    498 
    499                 // create the process
    500                 final Object syncObj = new Object();
    501 
    502                 ProcessBuilder builder;
    503                 builder = new ProcessBuilder(listToRun);
    504                 builder.directory(new File(getPluginDir()));
    505 
    506                 final StringBuilder debugstr = new StringBuilder();
    507 
    508                 // debug: print resulting cmdline
    509                 for (String s : builder.command())
    510                         debugstr.append(s + " ");
    511                 debugstr.append("\n");
    512                 Main.info(debugstr.toString());
    513 
    514                 final ToolProcess tp = new ToolProcess();
    515                 try {
    516                         tp.process = builder.start();
    517                 } catch (final IOException e) {
    518                         synchronized (debugstr) {
    519                                 Main.error(
    520                                                 tr("Error executing the script: ") +
    521                                                 debugstr.toString() + e.getMessage() + "\n" + e.getStackTrace());
    522                         }
    523                         return;
    524                 }
    525                 tp.running = true;
    526 
    527                 // redirect child process's stderr to JOSM stderr
    528                 new Thread(new Runnable() {
    529                         @Override
    530                         public void run() {
    531                                 try {
    532                                         byte[] buffer = new byte[1024];
    533                                         InputStream errStream = tp.process.getErrorStream();
    534                                         int len;
    535                                         while ((len = errStream.read(buffer)) > 0) {
    536                                                 synchronized (debugstr) {
    537                                                         debugstr.append(new String(buffer, 0, len));
    538                                                 }
    539                                                 System.err.write(buffer, 0, len);
    540                                         }
    541                                 } catch (IOException e) {
    542                                 }
    543                         }
    544                 }).start();
    545 
    546                 // Write stdin stream
    547                 Thread osmWriteThread = new Thread(new Runnable() {
    548                         @Override
    549                         public void run() {
    550                                 BBox bbox = null;
    551                                 final OutputStream outputStream = tp.process.getOutputStream();
    552                                 PrintWriter printWriter = null;
    553                                 try {
    554                                         printWriter = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
    555                                 } catch (Exception e) {
    556                                         Main.error(e);
    557                                 }
    558                                 final OsmWriter osmWriter = OsmWriterFactory.createOsmWriter(printWriter, true, null);
    559                                 Collection<OsmPrimitive> refObjects = currentCommand.getDepsObjects();
    560                                 Collection<OsmPrimitive> pObjects;
    561                                 osmWriter.header();
    562                                 Collection<OsmPrimitive> contents = new ArrayList<>();
    563                                 for (OsmPrimitive primitive : refObjects) {
    564                                         contents.add(primitive);
    565                                         if (bbox == null)
    566                                                 bbox = new BBox(primitive.getBBox());
    567                                         else
    568                                                 bbox.addPrimitive(primitive, 0.0);
    569                                 }
    570                                 osmWriter.writeNodes(new SubclassFilteredCollection<OsmPrimitive, Node>(contents, OsmPrimitive.nodePredicate));
    571                                 osmWriter.writeWays(new SubclassFilteredCollection<OsmPrimitive, Way>(contents, OsmPrimitive.wayPredicate));
    572                                 osmWriter.writeRelations(new SubclassFilteredCollection<OsmPrimitive, Relation>(contents, OsmPrimitive.relationPredicate));
    573                                 osmWriter.footer();
    574                                 osmWriter.flush();
    575 
    576                                 for (Parameter parameter : parameters) {
    577                                         if (!parameter.isOsm())
    578                                                 continue;
    579                                         contents = new ArrayList<>();
    580                                         osmWriter.header();
    581                                         pObjects = parameter.getParameterObjects();
    582                                         for (OsmPrimitive primitive : pObjects) {
    583                                                 contents.add(primitive);
    584                                                 if (bbox == null)
    585                                                         bbox = new BBox(primitive.getBBox());
    586                                                 else
    587                                                         bbox.addPrimitive(primitive, 0.0);
    588                                         }
    589                                         osmWriter.writeNodes(new SubclassFilteredCollection<OsmPrimitive, Node>(contents, OsmPrimitive.nodePredicate));
    590                                         osmWriter.writeWays(new SubclassFilteredCollection<OsmPrimitive, Way>(contents, OsmPrimitive.wayPredicate));
    591                                         osmWriter.writeRelations(new SubclassFilteredCollection<OsmPrimitive, Relation>(contents, OsmPrimitive.relationPredicate));
    592                                         osmWriter.footer();
    593                                         osmWriter.flush();
    594                                 }
    595 
    596                                 if (tracks) {
    597                                         try (GpxWriter gpxWriter = new GpxWriter(printWriter)) {
    598                                                 GpxFilter gpxFilter = new GpxFilter();
    599                                                 gpxFilter.initBboxFilter(bbox);
    600                                                 List<GpxLayer> gpxLayers = Main.map.mapView.getLayersOfType(GpxLayer.class);
    601                                                 for (GpxLayer gpxLayer : gpxLayers) {
    602                                                         gpxFilter.addGpxData(gpxLayer.data);
    603                                                 }
    604                                                 gpxWriter.write(gpxFilter.getGpxData());
    605                                         } catch (IOException e) {
    606                                                 Main.warn(e);
    607                                         }
    608                                 }
    609                                 Utils.close(osmWriter);
    610                                 synchronized (syncObj) {
    611                                         if (currentCommand.asynchronous) {
    612                                                 tp.running = false;
    613                                                 syncObj.notifyAll();
    614                                         }
    615                                 }
    616                         }
    617                 });
    618 
    619                 // Read stdout stream
    620                 final DataSet currentDataSet = Main.main.getCurrentDataSet();
    621                 final CommandLine that = this;
    622                 Thread osmParseThread = new Thread(new Runnable() {
    623                         @Override
    624                         public void run() {
    625                                 try {
    626                                         final OsmToCmd osmToCmd = new OsmToCmd(that, currentDataSet);
    627                                         String commandName = currentCommand.name;
    628                                         final InputStream inputStream = tp.process.getInputStream();
    629                                         osmToCmd.parseStream(inputStream);
    630                                         final List<org.openstreetmap.josm.command.Command> cmdlist = osmToCmd.getCommandList();
    631                                         if (!cmdlist.isEmpty()) {
    632                                                 final SequenceCommand cmd = new SequenceCommand(commandName, cmdlist);
    633                                                 SwingUtilities.invokeLater(new Runnable() {
    634                                                         @Override
    635                                                         public void run() {
    636                                                                 Main.main.undoRedo.add(cmd);
    637                                                         }
    638                                                 });
    639                                         }
    640                                 } catch (Exception e) {
    641                                 }
    642                                 finally {
    643                                         synchronized (syncObj) {
    644                                                 tp.running = false;
    645                                                 syncObj.notifyAll();
    646                                         }
    647                                 }
    648                         }
    649 
    650                 });
    651 
    652                 osmParseThread.start();
    653                 osmWriteThread.start();
    654 
    655                 synchronized (syncObj) {
    656                         try {
    657                                 syncObj.wait(Main.pref.getInteger("commandline.timeout", 20000));
    658                         } catch (InterruptedException e) {
    659                         }
    660                 }
    661                 if (tp.running) {
    662                         new Thread(new PleaseWaitRunnable(currentCommand.name) {
    663                                 @Override
    664                                 protected void realRun() {
    665                                         try {
    666                                                 progressMonitor.indeterminateSubTask(null);
    667                                                 synchronized (syncObj) {
    668                                                         if (tp.running)
    669                                                                 syncObj.wait();
    670                                                 }
    671                                         } catch (InterruptedException e) {
    672                                         }
    673                                 }
    674 
    675                                 @Override
    676                                 protected void cancel() {
    677                                         synchronized (syncObj) {
    678                                                 tp.running = false;
    679                                                 tp.process.destroy();
    680                                                 syncObj.notifyAll();
    681                                                 endInput();
    682                                         }
    683                                 }
    684 
    685                                 @Override
    686                                 protected void finish() {
    687                                 }
    688                         }).start();
    689                 }
    690                 endInput();
    691         }
     80    protected JTextField textField;
     81    protected JTextField historyField;
     82    private String prefix;
     83    private Mode mode;
     84    private ArrayList<Command> commands;
     85    private JMenu commandMenu;
     86    protected Command currentCommand;
     87    protected String commandSymbol;
     88    protected History history;
     89    protected MapFrame currentMapFrame;
     90    protected MapMode previousMode;
     91
     92    static final String pluginDir = Main.pref.getPluginsDirectory().getAbsolutePath() + "/CommandLine/";
     93
     94    @SuppressWarnings("serial")
     95    public CommandLine(PluginInformation info) {
     96        super(info);
     97        commandSymbol = ": ";
     98        history = new History(100);
     99        historyField = new DisableShortcutsOnFocusGainedTextField();
     100        textField = new DisableShortcutsOnFocusGainedTextField() {
     101            @Override
     102            protected void processKeyEvent(KeyEvent e) {
     103                if (e.getID() == KeyEvent.KEY_PRESSED) {
     104                    int code = e.getKeyCode();
     105                    if (code == KeyEvent.VK_ENTER) {
     106                        String commandText = textField.getText().substring(prefix.length());
     107                        switch (mode) {
     108                        case IDLE:
     109                            if (commandText.isEmpty()) {
     110                                commandText = history.getLastItem();
     111                            } else {
     112                                history.addItem(commandText);
     113                            }
     114                            Command command = findCommand(commandText, true);
     115                            if (command != null) {
     116                                startCommand(command);
     117                            } else {
     118                                setMode(Mode.IDLE);
     119                            }
     120                            break;
     121                        case SELECTION:
     122                            if (currentMapFrame.mapMode instanceof WayAction || currentMapFrame.mapMode instanceof NodeAction || currentMapFrame.mapMode instanceof RelationAction || currentMapFrame.mapMode instanceof AnyAction) {
     123                                Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
     124                                if (selected.size() > 0)
     125                                    loadParameter(selected, true);
     126                            }
     127                            else {
     128                                loadParameter(commandText, currentCommand.parameters.get(currentCommand.currentParameterNum).maxInstances == 1);
     129                            }
     130                            break;
     131                        case ADJUSTMENT:
     132                            break;
     133                        }
     134                        e.consume();
     135                    }
     136                    else if (code == KeyEvent.VK_UP) {
     137                        textField.setText(prefix + history.getPrevItem());
     138                        e.consume();
     139                    }
     140                    else if (code == KeyEvent.VK_DOWN) {
     141                        textField.setText(prefix + history.getNextItem());
     142                        e.consume();
     143                    }
     144                    else if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT) {
     145                        if (textField.getCaretPosition() <= prefix.length())
     146                            e.consume();
     147                    }
     148                    else if (code == KeyEvent.VK_HOME) {
     149                        setCaretPosition(prefix.length());
     150                        e.consume();
     151                    }
     152                    else if (code == KeyEvent.VK_ESCAPE) {
     153                        if (textField.getText().length() == prefix.length() && mode == Mode.IDLE)
     154                            deactivate();
     155                        else
     156                            endInput();
     157                        e.consume();
     158                    }
     159                    else if (code == KeyEvent.VK_DELETE || code == KeyEvent.VK_RIGHT || code == KeyEvent.VK_END) {
     160                    }
     161                    else {
     162                        e.consume();
     163                    }
     164                    if (textField.getCaretPosition() < prefix.length() || (textField.getSelectionStart() < prefix.length() && textField.getSelectionStart() > 0) )
     165                        e.consume();
     166                }
     167                if (e.getID() == KeyEvent.KEY_TYPED)
     168                    if (textField.getCaretPosition() < prefix.length() || (textField.getSelectionStart() < prefix.length() && textField.getSelectionStart() > 0) )
     169                        e.consume();
     170                super.processKeyEvent(e);
     171                if (textField.getText().length() < prefix.length()) { // Safe
     172                    setMode(mode);
     173                }
     174                if (e.getID() == KeyEvent.KEY_TYPED) {
     175                    if (e.getKeyChar() > 'A' && e.getKeyChar() < 'z') {
     176                        Command command = findCommand(textField.getText().substring(prefix.length()), false);
     177                        if (command != null) {
     178                            int currentPos = textField.getSelectionStart() == 0 ? textField.getCaretPosition() : textField.getSelectionStart();
     179                            textField.setText(prefix + command.name);
     180                            textField.setCaretPosition(currentPos);
     181                            textField.select(currentPos, prefix.length() + command.name.length());
     182                        }
     183                    }
     184                }
     185            }
     186            @Override
     187            protected void processMouseEvent(MouseEvent e) {
     188                super.processMouseEvent(e);
     189                if (e.getButton() == MouseEvent.BUTTON1 && e.getID() == MouseEvent.MOUSE_RELEASED) {
     190                    if (textField.getSelectionStart() > 0 && textField.getSelectionStart() < prefix.length())
     191                        textField.setSelectionStart(prefix.length());
     192                    else if (textField.getCaretPosition() < prefix.length())
     193                        textField.setCaretPosition(prefix.length());
     194                }
     195            }
     196        };
     197
     198        if (Main.main.menu != null) {
     199            commandMenu = Main.main.menu.addMenu("Commands", tr("Commands"), KeyEvent.VK_O, Main.main.menu.getDefaultMenuPos(), ht("/Plugin/CommandLine"));
     200            MainMenu.add(commandMenu, new CommandLineAction(this));
     201        }
     202        loadCommands();
     203        setMode(Mode.IDLE);
     204    }
     205
     206    public void startCommand(String commandName) {
     207        Command command = findCommand(commandName, true);
     208        if (command != null) {
     209            startCommand(command);
     210        }
     211    }
     212
     213    protected void startCommand(Command command) {
     214        if (Main.map == null)
     215            return;
     216        DataSet ds = Main.main.getCurrentDataSet();
     217        if (ds == null)
     218            return;
     219        currentCommand = command;
     220        currentCommand.resetLoading();
     221        parseSelection(ds.getSelected());
     222        if (!(Main.map.mapMode instanceof AnyAction || Main.map.mapMode instanceof DummyAction || Main.map.mapMode instanceof LengthAction || Main.map.mapMode instanceof NodeAction || Main.map.mapMode instanceof PointAction || Main.map.mapMode instanceof RelationAction || Main.map.mapMode instanceof WayAction)) {
     223            previousMode = Main.map.mapMode;
     224        }
     225        if (currentCommand.currentParameterNum < currentCommand.parameters.size())
     226            setMode(Mode.SELECTION);
     227        else
     228            runTool();
     229    }
     230
     231    @Override
     232    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     233        currentMapFrame = newFrame;
     234        if (oldFrame == null && newFrame != null) {
     235            JToolBar tb = new JToolBar();
     236            tb.setLayout(new BorderLayout());
     237            tb.setFloatable(false);
     238            tb.setOrientation(JToolBar.HORIZONTAL);
     239            tb.add(historyField, BorderLayout.NORTH);
     240            tb.add(textField, BorderLayout.SOUTH);
     241            currentMapFrame.add(tb, BorderLayout.NORTH);
     242            printHistory("Loaded CommandLine, version " + getPluginInformation().version);
     243        }
     244    }
     245
     246    protected void printHistory(final String text) {
     247        SwingUtilities.invokeLater(new Runnable() {
     248            @Override
     249            public void run() {
     250                historyField.setText(text);
     251            }
     252        });
     253    }
     254
     255    private void loadCommands() {
     256        commands = (new Loader(getPluginDir())).load();
     257        if (commands.isEmpty()) {
     258            if (!GraphicsEnvironment.isHeadless() && JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Main.parent,
     259                    tr("No command has been found. Would you like to download and install default commands now?"),
     260                    tr("No command found"), JOptionPane.YES_NO_CANCEL_OPTION)) {
     261                try {
     262                    downloadAndInstallDefaultCommands();
     263                    commands = (new Loader(getPluginDir())).load();
     264                    JOptionPane.showMessageDialog(Main.parent, tr("Default commands have been successfully installed"),
     265                            tr("Success"), JOptionPane.INFORMATION_MESSAGE);
     266                } catch (IOException e) {
     267                    Main.warn(e);
     268                    JOptionPane.showMessageDialog(Main.parent,
     269                            tr("Failed to download and install default commands.\n\nError: {0}", e.getMessage()),
     270                            tr("Warning"), JOptionPane.WARNING_MESSAGE);
     271                }
     272            }
     273        }
     274        for (Command command : commands) {
     275            commandMenu.add(new CommandAction(command, this));
     276        }
     277    }
     278
     279    private void downloadAndInstallDefaultCommands() throws IOException {
     280        String url = Main.pref.get("commandline.default.commands.url",
     281                "https://github.com/Foxhind/JOSM-CommandLine-commands/archive/master.zip");
     282        try (ZipInputStream zis = new ZipInputStream(HttpClient.create(new URL(url)).connect().getContent(), StandardCharsets.UTF_8)) {
     283            File dir = new File(getPluginDir());
     284            if (!dir.exists()) {
     285                dir.mkdirs();
     286            }
     287            ZipEntry entry = null;
     288            while ( (entry = zis.getNextEntry()) != null ) {
     289                if (!entry.isDirectory()) {
     290                    String name = entry.getName();
     291                    if (name.contains("/")) {
     292                        name = name.substring(name.lastIndexOf("/"));
     293                    }
     294                    File file = new File(dir + File.separator + name);
     295                    Main.info("Installing command file: "+file);
     296                    if (!file.createNewFile()) {
     297                        throw new IOException("Could not create file: " + file.getAbsolutePath());
     298                    }
     299                    // Write file
     300                    Files.copy(zis, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
     301                    // Set last modification date
     302                    long time = entry.getTime();
     303                    if (time > -1) {
     304                        file.setLastModified(time);
     305                    }
     306                }
     307            }
     308        }
     309    }
     310
     311    private Command findCommand(String text, boolean strict) {
     312        for (int i = 0; i < commands.size(); i++) {
     313            if (strict) {
     314                if ( commands.get(i).name.equalsIgnoreCase(text) ) {
     315                    return commands.get(i);
     316                }
     317            } else if ( commands.get(i).name.toLowerCase().startsWith( text.toLowerCase() ) && text.length() > 1 ) {
     318                return commands.get(i);
     319            }
     320        }
     321        return null;
     322    }
     323
     324    protected void setMode(Mode targetMode) {
     325        DataSet currentDataSet = Main.main.getCurrentDataSet();
     326        if (currentDataSet != null) {
     327            currentDataSet.clearSelection();
     328            Main.map.mapView.repaint();
     329        }
     330        if (targetMode == Mode.IDLE) {
     331            mode = Mode.IDLE;
     332            currentCommand = null;
     333            prefix = tr("Command") + commandSymbol;
     334            textField.setText(prefix);
     335        }
     336        else if (targetMode == Mode.SELECTION) {
     337            mode = Mode.SELECTION;
     338            Parameter currentParameter = currentCommand.parameters.get(currentCommand.currentParameterNum);
     339            prefix = tr(currentParameter.description == null ? currentParameter.name : currentParameter.description);
     340            if (currentParameter.getRawValue() instanceof Relay)
     341                prefix = prefix + " (" + ((Relay)(currentParameter.getRawValue())).getOptionsString() + ")";
     342            prefix += commandSymbol;
     343            String value = currentParameter.getValue();
     344            textField.setText(prefix + value);
     345            Type currentType = currentParameter.type;
     346            MapMode action = null;
     347            switch (currentType) {
     348            case POINT:
     349                action = new PointAction(currentMapFrame, this);
     350                break;
     351            case WAY:
     352                action = new WayAction(currentMapFrame, this);
     353                break;
     354            case NODE:
     355                action = new NodeAction(currentMapFrame, this);
     356                break;
     357            case RELATION:
     358                action = new RelationAction(currentMapFrame, this);
     359                break;
     360            case ANY:
     361                action = new AnyAction(currentMapFrame, this);
     362                break;
     363            case LENGTH:
     364                action = new LengthAction(currentMapFrame, this);
     365                break;
     366            case USERNAME:
     367                loadParameter(Main.pref.get("osm-server.username", null), true);
     368                action = new DummyAction(currentMapFrame, this);
     369                break;
     370            case IMAGERYURL:
     371                Layer layer = Main.map.mapView.getActiveLayer();
     372                if (layer != null) {
     373                    if (!(layer instanceof ImageryLayer)) {
     374                        List<ImageryLayer> imageryLayers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
     375                        if (imageryLayers.size() == 1) {
     376                            layer = imageryLayers.get(0);
     377                        }
     378                        else {
     379                            endInput();
     380                            return;
     381                        }
     382                    }
     383                }
     384                ImageryInfo info = ((ImageryLayer)layer).getInfo();
     385                String url = info.getUrl();
     386                String itype = info.getImageryType().getTypeString();
     387                loadParameter((url.equals("") ? itype : url), true);
     388                action = new DummyAction(currentMapFrame, this);
     389                break;
     390            case IMAGERYOFFSET:
     391                Layer olayer = Main.map.mapView.getActiveLayer();
     392                if (olayer != null) {
     393                    if (!(olayer instanceof ImageryLayer)) {
     394                        List<ImageryLayer> imageryLayers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
     395                        if (imageryLayers.size() == 1) {
     396                            olayer = imageryLayers.get(0);
     397                        }
     398                        else {
     399                            endInput();
     400                            return;
     401                        }
     402                    }
     403                }
     404                loadParameter((String.valueOf(((ImageryLayer)olayer).getDx()) + "," + String.valueOf(((ImageryLayer)olayer).getDy())), true);
     405                action = new DummyAction(currentMapFrame, this);
     406                break;
     407            default:
     408                action = new DummyAction(currentMapFrame, this);
     409                break;
     410            }
     411            currentMapFrame.selectMapMode(action);
     412            activate();
     413            textField.select(prefix.length(), textField.getText().length());
     414        }
     415        else if (targetMode == Mode.PROCESSING) {
     416            mode = Mode.PROCESSING;
     417            prefix = tr("Processing...");
     418            textField.setText(prefix);
     419            Main.map.mapView.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
     420        }
     421    }
     422
     423    public void activate() {
     424        textField.requestFocus();
     425        textField.setCaretPosition(textField.getText().length());
     426    }
     427
     428    public void deactivate() {
     429        Main.map.mapView.requestFocus();
     430    }
     431
     432    public void abortInput() {
     433        printHistory(tr("Aborted") + ".");
     434        endInput();
     435    }
     436
     437    public void endInput() {
     438        setMode(Mode.IDLE);
     439        Main.map.selectMapMode(previousMode);
     440        Main.map.mapView.repaint();
     441    }
     442
     443    public void loadParameter(Object obj, boolean next) {
     444        if (currentCommand.loadObject(obj)) {
     445            if (currentCommand.hasNextParameter()) {
     446                if (next) {
     447                    Parameter currentParameter = currentCommand.parameters.get(currentCommand.currentParameterNum);
     448                    String prefix = tr(currentParameter.description == null ? currentParameter.name : currentParameter.description);
     449                    prefix += commandSymbol;
     450                    String value = currentParameter.getValue();
     451                    printHistory(prefix + value);
     452                    currentCommand.nextParameter();
     453                    setMode(Mode.SELECTION);
     454                }
     455            } else {
     456                runTool();
     457            }
     458        } else {
     459            Main.info("Invalid argument");
     460            endInput();
     461        }
     462    }
     463
     464    private void parseSelection(Collection<OsmPrimitive> selection) {
     465        boolean ok = false;
     466        for (OsmPrimitive obj : selection) {
     467            ok = currentCommand.loadObject(obj);
     468            if (!ok)
     469                break;
     470        }
     471        if (ok) {
     472            currentCommand.nextParameter();
     473        } else {
     474            currentCommand.resetLoading();
     475        }
     476    }
     477
     478    private class ToolProcess {
     479        public Process process;
     480        public volatile boolean running;
     481    }
     482
     483    // Thanks to Upliner
     484    public void runTool() {
     485        setMode(Mode.PROCESSING);
     486        String commandToRun = currentCommand.run;
     487        final boolean tracks = currentCommand.tracks;
     488        final ArrayList<Parameter> parameters = currentCommand.parameters;
     489
     490        for (Parameter parameter : currentCommand.parameters) {
     491            commandToRun = commandToRun.replace("{" + parameter.name + "}", parameter.getValue());
     492        }
     493        for (Parameter parameter : currentCommand.optParameters) {
     494            commandToRun = commandToRun.replace("{" + parameter.name + "}", parameter.getValue());
     495        }
     496        String[] listToRun = commandToRun.split(" ");
     497
     498        // create the process
     499        final Object syncObj = new Object();
     500
     501        ProcessBuilder builder;
     502        builder = new ProcessBuilder(listToRun);
     503        builder.directory(new File(getPluginDir()));
     504
     505        final StringBuilder debugstr = new StringBuilder();
     506
     507        // debug: print resulting cmdline
     508        for (String s : builder.command())
     509            debugstr.append(s + " ");
     510        debugstr.append("\n");
     511        Main.info(debugstr.toString());
     512
     513        final ToolProcess tp = new ToolProcess();
     514        try {
     515            tp.process = builder.start();
     516        } catch (final IOException e) {
     517            synchronized (debugstr) {
     518                Main.error(
     519                        tr("Error executing the script: ") +
     520                        debugstr.toString() + e.getMessage() + "\n" + e.getStackTrace());
     521            }
     522            return;
     523        }
     524        tp.running = true;
     525
     526        // redirect child process's stderr to JOSM stderr
     527        new Thread(new Runnable() {
     528            @Override
     529            public void run() {
     530                try {
     531                    byte[] buffer = new byte[1024];
     532                    InputStream errStream = tp.process.getErrorStream();
     533                    int len;
     534                    while ((len = errStream.read(buffer)) > 0) {
     535                        synchronized (debugstr) {
     536                            debugstr.append(new String(buffer, 0, len));
     537                        }
     538                        System.err.write(buffer, 0, len);
     539                    }
     540                } catch (IOException e) {
     541                }
     542            }
     543        }).start();
     544
     545        // Write stdin stream
     546        Thread osmWriteThread = new Thread(new Runnable() {
     547            @Override
     548            public void run() {
     549                BBox bbox = null;
     550                final OutputStream outputStream = tp.process.getOutputStream();
     551                PrintWriter printWriter = null;
     552                try {
     553                    printWriter = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
     554                } catch (Exception e) {
     555                    Main.error(e);
     556                }
     557                final OsmWriter osmWriter = OsmWriterFactory.createOsmWriter(printWriter, true, null);
     558                Collection<OsmPrimitive> refObjects = currentCommand.getDepsObjects();
     559                Collection<OsmPrimitive> pObjects;
     560                osmWriter.header();
     561                Collection<OsmPrimitive> contents = new ArrayList<>();
     562                for (OsmPrimitive primitive : refObjects) {
     563                    contents.add(primitive);
     564                    if (bbox == null)
     565                        bbox = new BBox(primitive.getBBox());
     566                    else
     567                        bbox.addPrimitive(primitive, 0.0);
     568                }
     569                osmWriter.writeNodes(new SubclassFilteredCollection<OsmPrimitive, Node>(contents, OsmPrimitive.nodePredicate));
     570                osmWriter.writeWays(new SubclassFilteredCollection<OsmPrimitive, Way>(contents, OsmPrimitive.wayPredicate));
     571                osmWriter.writeRelations(new SubclassFilteredCollection<OsmPrimitive, Relation>(contents, OsmPrimitive.relationPredicate));
     572                osmWriter.footer();
     573                osmWriter.flush();
     574
     575                for (Parameter parameter : parameters) {
     576                    if (!parameter.isOsm())
     577                        continue;
     578                    contents = new ArrayList<>();
     579                    osmWriter.header();
     580                    pObjects = parameter.getParameterObjects();
     581                    for (OsmPrimitive primitive : pObjects) {
     582                        contents.add(primitive);
     583                        if (bbox == null)
     584                            bbox = new BBox(primitive.getBBox());
     585                        else
     586                            bbox.addPrimitive(primitive, 0.0);
     587                    }
     588                    osmWriter.writeNodes(new SubclassFilteredCollection<OsmPrimitive, Node>(contents, OsmPrimitive.nodePredicate));
     589                    osmWriter.writeWays(new SubclassFilteredCollection<OsmPrimitive, Way>(contents, OsmPrimitive.wayPredicate));
     590                    osmWriter.writeRelations(new SubclassFilteredCollection<OsmPrimitive, Relation>(contents, OsmPrimitive.relationPredicate));
     591                    osmWriter.footer();
     592                    osmWriter.flush();
     593                }
     594
     595                if (tracks) {
     596                    try (GpxWriter gpxWriter = new GpxWriter(printWriter)) {
     597                        GpxFilter gpxFilter = new GpxFilter();
     598                        gpxFilter.initBboxFilter(bbox);
     599                        List<GpxLayer> gpxLayers = Main.map.mapView.getLayersOfType(GpxLayer.class);
     600                        for (GpxLayer gpxLayer : gpxLayers) {
     601                            gpxFilter.addGpxData(gpxLayer.data);
     602                        }
     603                        gpxWriter.write(gpxFilter.getGpxData());
     604                    } catch (IOException e) {
     605                        Main.warn(e);
     606                    }
     607                }
     608                Utils.close(osmWriter);
     609                synchronized (syncObj) {
     610                    if (currentCommand.asynchronous) {
     611                        tp.running = false;
     612                        syncObj.notifyAll();
     613                    }
     614                }
     615            }
     616        });
     617
     618        // Read stdout stream
     619        final DataSet currentDataSet = Main.main.getCurrentDataSet();
     620        final CommandLine that = this;
     621        Thread osmParseThread = new Thread(new Runnable() {
     622            @Override
     623            public void run() {
     624                try {
     625                    final OsmToCmd osmToCmd = new OsmToCmd(that, currentDataSet);
     626                    String commandName = currentCommand.name;
     627                    final InputStream inputStream = tp.process.getInputStream();
     628                    osmToCmd.parseStream(inputStream);
     629                    final List<org.openstreetmap.josm.command.Command> cmdlist = osmToCmd.getCommandList();
     630                    if (!cmdlist.isEmpty()) {
     631                        final SequenceCommand cmd = new SequenceCommand(commandName, cmdlist);
     632                        SwingUtilities.invokeLater(new Runnable() {
     633                            @Override
     634                            public void run() {
     635                                Main.main.undoRedo.add(cmd);
     636                            }
     637                        });
     638                    }
     639                } catch (Exception e) {
     640                }
     641                finally {
     642                    synchronized (syncObj) {
     643                        tp.running = false;
     644                        syncObj.notifyAll();
     645                    }
     646                }
     647            }
     648
     649        });
     650
     651        osmParseThread.start();
     652        osmWriteThread.start();
     653
     654        synchronized (syncObj) {
     655            try {
     656                syncObj.wait(Main.pref.getInteger("commandline.timeout", 20000));
     657            } catch (InterruptedException e) {
     658            }
     659        }
     660        if (tp.running) {
     661            new Thread(new PleaseWaitRunnable(currentCommand.name) {
     662                @Override
     663                protected void realRun() {
     664                    try {
     665                        progressMonitor.indeterminateSubTask(null);
     666                        synchronized (syncObj) {
     667                            if (tp.running)
     668                                syncObj.wait();
     669                        }
     670                    } catch (InterruptedException e) {
     671                    }
     672                }
     673
     674                @Override
     675                protected void cancel() {
     676                    synchronized (syncObj) {
     677                        tp.running = false;
     678                        tp.process.destroy();
     679                        syncObj.notifyAll();
     680                        endInput();
     681                    }
     682                }
     683
     684                @Override
     685                protected void finish() {
     686                }
     687            }).start();
     688        }
     689        endInput();
     690    }
    692691}
Note: See TracChangeset for help on using the changeset viewer.