Ignore:
Timestamp:
2009-04-06T20:18:48+02:00 (17 years ago)
Author:
framm
Message:
  • Major redesign of how JOSM talks to the OSM server. Connections now all go through a new OsmApi class that finds out which version the server uses. JOSM should now be able to handle 0.5 and 0.6 without configuration change. Config options osm-server.version and osm-server.additional-versions now obsolete. Handling of error and cancel situations might still need some improvement.
Location:
trunk/src/org/openstreetmap/josm/io
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/DiffResultReader.java

    r1415 r1523  
    55
    66import java.io.IOException;
    7 import java.io.InputStream;
    8 import java.io.InputStreamReader;
     7import java.io.StringReader;
    98import java.util.Collection;
    109import java.util.HashMap;
     
    1817import org.openstreetmap.josm.data.osm.Relation;
    1918import org.openstreetmap.josm.data.osm.Way;
    20 import org.openstreetmap.josm.data.osm.visitor.Visitor;
     19import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
    2120import org.openstreetmap.josm.gui.PleaseWaitDialog;
    2221import org.xml.sax.Attributes;
     
    2726/**
    2827 */
    29 public class DiffResultReader implements Visitor {
     28public class DiffResultReader extends AbstractVisitor {
    3029
    3130    /**
     
    6564     * Parse the given input source and return the dataset.
    6665     */
    67     public static void parseDiffResult(InputStream source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, PleaseWaitDialog pleaseWaitDlg)
     66    public static void parseDiffResult(String source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, PleaseWaitDialog pleaseWaitDlg)
    6867    throws SAXException, IOException {
    6968
     
    7170       drr.processed = processed;
    7271       drr.newIdMap = newIdMap;
    73        InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
     72       InputSource inputSource = new InputSource(new StringReader(source));
    7473       try {
    7574           SAXParserFactory.newInstance().newSAXParser().parse(inputSource, drr.new Parser());
     
    8584
    8685       for (OsmPrimitive p : osm) {
    87            System.out.println("old: "+ p);
     86           //System.out.println("old: "+ p);
    8887           p.visit(drr);
    89            System.out.println("new: "+ p);
    90            System.out.println("");
     88           //System.out.println("new: "+ p);
     89           //System.out.println("");
    9190       }
    9291    }
  • trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java

    r1169 r1523  
    2222    InputStream fs = null;
    2323
    24     public MirroredInputStream(String name) throws IOException
    25     {
     24    public MirroredInputStream(String name) throws IOException {
    2625        this(name, null, -1L);
    2726    }
    2827
    29     public MirroredInputStream(String name, long maxTime) throws IOException
    30     {
     28    public MirroredInputStream(String name, long maxTime) throws IOException {
    3129        this(name, null, maxTime);
    3230    }
    3331
    34     public MirroredInputStream(String name, String destDir, long maxTime) throws IOException
    35     {
     32    public MirroredInputStream(String name, String destDir, long maxTime) throws IOException {
    3633        URL url;
    3734        File file = null;
    38         try
    39         {
     35        try {
    4036            url = new URL(name);
    41             if(url.getProtocol().equals("file"))
    42             {
     37            if (url.getProtocol().equals("file")) {
    4338                file = new File(name.substring("file:/".length()));
    44                 if(!file.exists())
     39                if (!file.exists())
    4540                    file = new File(name.substring("file://".length()));
     41            } else {
     42                file = checkLocal(url, destDir, maxTime);
    4643            }
    47             else
    48                 file = checkLocal(url, destDir, maxTime);
    49         }
    50         catch(java.net.MalformedURLException e)
    51         {
    52             if(name.startsWith("resource://"))
    53             {
     44        } catch (java.net.MalformedURLException e) {
     45            if(name.startsWith("resource://")) {
    5446                fs = getClass().getResourceAsStream(
    5547                name.substring("resource:/".length()));
    5648                return;
    5749            }
    58             else
    59                 file = new File(name);
     50            file = new File(name);
    6051        }
    61         if(file == null)
     52        if (file == null)
    6253            throw new IOException();
    6354        fs = new FileInputStream(file);
    6455    }
    6556
    66     private File checkLocal(URL url, String destDir, long maxTime)
    67     {
     57    private File checkLocal(URL url, String destDir, long maxTime) {
    6858        String localPath = Main.pref.get("mirror." + url);
    6959        File file = null;
    70         if(localPath != null && localPath.length() > 0)
    71         {
     60        if (localPath != null && localPath.length() > 0) {
    7261            String[] lp = localPath.split(";");
    7362            file = new File(lp[1]);
    74             if(maxTime <= 0)
     63            if (maxTime <= 0)
    7564                maxTime = Main.pref.getInteger("mirror.maxtime", 7*24*60*60);
    76             if(System.currentTimeMillis() - Long.parseLong(lp[0]) < maxTime*1000)
    77             {
    78                 if(file.exists())
    79                 {
     65            if (System.currentTimeMillis() - Long.parseLong(lp[0]) < maxTime*1000) {
     66                if(file.exists()) {
    8067                    return file;
    8168                }
     
    8673
    8774        File destDirFile = new File(destDir);
    88         if(!destDirFile.exists() )
     75        if (!destDirFile.exists())
    8976            destDirFile.mkdirs();
    9077
     
    9380        BufferedOutputStream bos = null;
    9481        BufferedInputStream bis = null;
    95         try
    96         {
     82        try {
    9783            URLConnection conn = url.openConnection();
    9884            conn.setConnectTimeout(5000);
     
    10187            byte[] buffer = new byte[4096];
    10288            int length;
    103             while((length = bis.read(buffer)) > -1)
     89            while ((length = bis.read(buffer)) > -1)
    10490                bos.write(buffer, 0, length);
    105         }
    106         catch(IOException ioe)
    107         {
    108             if(file != null)
     91        } catch(IOException ioe) {
     92            if (file != null)
    10993                return file;
    110             else
    111                 return null;
    112         }
    113         finally
    114         {
    115             if(bis != null)
    116             {
    117                 try
    118                 {
     94            return null;
     95        } finally {
     96            if (bis != null) {
     97                try {
    11998                    bis.close();
    120                 }
    121                 catch (IOException e)
    122                 {
     99                } catch (IOException e) {
    123100                    e.printStackTrace();
    124101                }
    125102            }
    126             if(bos != null)
    127             {
    128                 try
    129                 {
     103            if (bos != null) {
     104                try {
    130105                    bos.close();
    131                 }
    132                 catch (IOException e)
    133                 {
     106                } catch (IOException e) {
    134107                    e.printStackTrace();
    135108                }
  • trunk/src/org/openstreetmap/josm/io/MyHttpHandler.java

    r1169 r1523  
    99// Basically a copy of sun.net.www.protocol.http.Handler
    1010public class MyHttpHandler extends sun.net.www.protocol.http.Handler  {
    11             protected String proxy;
    12             protected int proxyPort;
     11    protected String proxy;
     12    protected int proxyPort;
    1313
    14             public MyHttpHandler() {
    15                 super();
    16                 proxy = null;
    17                 proxyPort = -1;
    18             }
     14    public MyHttpHandler() {
     15        super();
     16        proxy = null;
     17        proxyPort = -1;
     18    }
    1919
    20             protected java.net.URLConnection openConnection(URL u)
    21                     throws IOException {
    22                 return openConnection(u, (Proxy) null);
    23             }
    24             public MyHttpHandler(String proxy, int port) {
    25                 this.proxy = proxy;
    26                 proxyPort = port;
    27             }
     20    protected java.net.URLConnection openConnection(URL u)
     21    throws IOException {
     22        return openConnection(u, (Proxy) null);
     23    }
     24    public MyHttpHandler(String proxy, int port) {
     25        this.proxy = proxy;
     26        proxyPort = port;
     27    }
    2828
    29             protected java.net.URLConnection openConnection(URL u, Proxy p)
    30                     throws IOException {
    31                 return new MyHttpURLConnection(u, p, this);
    32             }
     29    protected java.net.URLConnection openConnection(URL u, Proxy p)
     30    throws IOException {
     31        return new MyHttpURLConnection(u, p, this);
     32    }
    3333}
  • trunk/src/org/openstreetmap/josm/io/OsmConnection.java

    r1397 r1523  
    4949     */
    5050    static {
    51         //TODO: refactor this crap (maybe just insert the damn auth http-header by yourself)
     51        // TODO: current authentication handling is sub-optimal in that it seems to use the same authenticator for
     52        // any kind of request. HTTP requests executed by plugins, e.g. to password-protected WMS servers,
     53        // will use the same username/password which is undesirable.
    5254        try {
    5355            HttpURLConnection.setFollowRedirects(true);
  • trunk/src/org/openstreetmap/josm/io/OsmReader.java

    r1499 r1523  
    88import java.io.InputStreamReader;
    99import java.util.ArrayList;
    10 import java.util.Arrays;
    1110import java.util.Collection;
    1211import java.util.HashMap;
    13 import java.util.HashSet;
    1412import java.util.LinkedList;
    1513import java.util.Map;
     
    130128     private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>();
    131129
    132      /**
    133       * List of protocol versions that will be accepted on reading
    134       */
    135      private HashSet<String> allowedVersions = new HashSet<String>();
    136 
    137130     private class Parser extends DefaultHandler {
    138131          /**
     
    164157                         if (atts == null)
    165158                              throw new SAXException(tr("Unknown version"));
    166                          if (!allowedVersions.contains(atts.getValue("version")))
    167                               throw new SAXException(tr("Unknown version")+": "+atts.getValue("version"));
     159                         String v = atts.getValue("version");
     160                         if (v == null)
     161                             throw new SAXException(tr("Version number missing from OSM data"));
     162                         if (!(v.equals("0.5") || v.equals("0.6")))
     163                             throw new SAXException(tr("Unknown version: {0}", v));
    168164                         // save generator attribute for later use when creating DataSource objects
    169165                         generator = atts.getValue("generator");
    170 
    171 
    172                     } else if (qName.equals("bound")) {
    173                          // old style bounds.
    174                          // TODO: remove this around 1st October 2008.
    175                          // - this is a bit of a hack; since we still write out old style bound objects,
    176                          // we don't want to load them both. so when writing, we add a "note" tag the our
    177                          // old-style bound, and when reading, ignore those with a "note".
    178                          String note = atts.getValue("note");
    179                          if (note == null) {
    180                              System.out.println("Notice: old style <bound> element detected; support for these will be dropped in a future release.");
    181                              String bbox = atts.getValue("box");
    182                              String origin = atts.getValue("origin");
    183                              if (origin == null) origin = "";
    184                              if (bbox != null) {
    185                                   String[] b = bbox.split(",");
    186                                   Bounds bounds = new Bounds();
    187                                   if (b.length == 4)
    188                                        bounds = new Bounds(
    189                                                  new LatLon(Double.parseDouble(b[0]),Double.parseDouble(b[1])),
    190                                                  new LatLon(Double.parseDouble(b[2]),Double.parseDouble(b[3])));
    191                                   DataSource src = new DataSource(bounds, origin);
    192                                   ds.dataSources.add(src);
    193                              }
    194                          }
     166                         ds.version = v;
     167                         
    195168                    } else if (qName.equals("bounds")) {
    196169                         // new style bounds.
     
    277250               return Double.parseDouble(atts.getValue(value));
    278251          }
    279      }
    280 
    281      /**
    282       * Constructor initializes list of allowed protocol versions.
    283       */
    284      public OsmReader() {
    285           // first add the main server version
    286           allowedVersions.add(Main.pref.get("osm-server.version", "0.5"));
    287           // now also add all compatible versions
    288           String[] additionalVersions =
    289                Main.pref.get("osm-server.additional-versions", "").split("/,/");
    290           if (additionalVersions.length == 1 && additionalVersions[0].length() == 0)
    291                additionalVersions = new String[] {};
    292           allowedVersions.addAll(Arrays.asList(additionalVersions));
    293252     }
    294253
     
    491450          osm.references = ref == null ? new DataSet() : ref;
    492451
    493 
    494452          currSource = source;
    495453
  • trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java

    r1169 r1523  
    3232            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
    3333            final DataSet data = OsmReader.parseDataSet(in, null, Main.pleaseWaitDlg);
    34 //          String origin = Main.pref.get("osm-server.url")+"/"+Main.pref.get("osm-server.version", "0.5");
    3534//          Bounds bounds = new Bounds(new LatLon(lat1, lon1), new LatLon(lat2, lon2));
    3635//          DataSource src = new DataSource(bounds, origin);
  • trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java

    r1444 r1523  
    5252            final DataSet data = osm.getDs();
    5353
    54 //          String origin = Main.pref.get("osm-server.url")+"/"+Main.pref.get("osm-server.version", "0.5");
    5554//          Bounds bounds = new Bounds(new LatLon(lat1, lon1), new LatLon(lat2, lon2));
    5655//          DataSource src = new DataSource(bounds, origin);
  • trunk/src/org/openstreetmap/josm/io/OsmServerReader.java

    r1353 r1523  
    2727 */
    2828public abstract class OsmServerReader extends OsmConnection {
     29   
     30    private OsmApi api = new OsmApi();
     31   
    2932    /**
    3033     * Open a connection to the given url and return a reader on the input stream
     
    3538     */
    3639    protected InputStream getInputStream(String urlStr, PleaseWaitDialog pleaseWaitDlg) throws IOException {
    37         String version = Main.pref.get("osm-server.version", "0.5");
    38         urlStr = Main.pref.get("osm-server.url")+"/"+version+"/" + urlStr;
     40        api.initialize();
     41        urlStr = api.getBaseUrl() + urlStr;
    3942        return getInputStreamRaw(urlStr, pleaseWaitDlg);
    4043    }
     
    4346
    4447//        System.out.println("download: "+urlStr);
    45         initAuthentication();
    4648        URL url = new URL(urlStr);
    4749        activeConnection = (HttpURLConnection)url.openConnection();
  • trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java

    r1415 r1523  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.io.BufferedReader;
    7 import java.io.ByteArrayOutputStream;
    8 import java.io.IOException;
    9 import java.io.InputStream;
    10 import java.io.InputStreamReader;
    11 import java.io.OutputStream;
    12 import java.io.OutputStreamWriter;
    13 import java.io.PrintWriter;
    14 import java.io.UnsupportedEncodingException;
    15 import java.lang.Math;
    16 import java.net.ConnectException;
    17 import java.net.HttpURLConnection;
    18 import java.net.URL;
    19 import java.net.UnknownHostException;
    20 import java.net.SocketTimeoutException;
    216import java.util.Collection;
    227import java.util.LinkedList;
     8
    239import javax.swing.JOptionPane;
    2410
    2511import org.openstreetmap.josm.Main;
    26 import org.openstreetmap.josm.data.osm.Relation;
    27 import org.openstreetmap.josm.data.osm.Node;
    2812import org.openstreetmap.josm.data.osm.OsmPrimitive;
    29 import org.openstreetmap.josm.data.osm.Way;
    30 import org.openstreetmap.josm.data.osm.Changeset;
    31 import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor;
    3213import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
    33 import org.openstreetmap.josm.data.osm.visitor.Visitor;
    34 import org.xml.sax.SAXException;
    35 import org.openstreetmap.josm.io.XmlWriter.OsmWriterInterface;
    3614
    3715/**
     
    4119 * those in deleted, which are ignored - All objects in deleted list are
    4220 * deleted. - All remaining objects with modified flag set are updated.
    43  *
    44  * This class implements visitor and will perform the correct upload action on
    45  * the visited element.
    46  *
    47  * @author imi
    4821 */
    49 public class OsmServerWriter extends OsmConnection implements Visitor {
     22public class OsmServerWriter {
    5023
    5124    /**
     
    5831    public Collection<OsmPrimitive> processed;
    5932
    60     /**
    61      * Whether the operation should be aborted as soon as possible.
    62      */
    63     // use the inherited variable
    64     // private boolean cancel = false;
    65 
    66     /**
    67      * Object describing current changeset
    68      */
    69     private Changeset changeset;
    70 
    71     /**
    72      * Send the dataset to the server. Ask the user first and does nothing if he
    73      * does not want to send the data.
    74      */
     33    private OsmApi api = new OsmApi();
     34   
    7535    private static final int MSECS_PER_SECOND = 1000;
    7636    private static final int SECONDS_PER_MINUTE = 60;
     
    9656    }
    9757
    98     public void uploadOsm(Collection<OsmPrimitive> list) throws SAXException {
     58    /**
     59     * Send the dataset to the server.
     60     * @param the_version version of the data set
     61     * @param list list of objects to send
     62     */
     63    public void uploadOsm(String the_version, Collection<OsmPrimitive> list) {
    9964        processed = new LinkedList<OsmPrimitive>();
    100         initAuthentication();
     65        api.initialize();
    10166
    10267        Main.pleaseWaitDlg.progress.setMaximum(list.size());
    10368        Main.pleaseWaitDlg.progress.setValue(0);
    10469
    105         // controls whether or not we open and close a changeset. API 0.6 requires changesets.
    106         boolean useChangesets = Main.pref.get("osm-server.version", "0.5").equals("0.6");
     70        boolean useChangesets = api.hasChangesetSupport();
     71       
     72        // controls whether or not we try and upload the whole bunch in one go
     73        boolean useDiffUploads = Main.pref.getBoolean("osm-server.atomic-upload",
     74            "0.6".equals(api.getVersion()));
    10775
    108         // controls whether or not we try and uplaod the whole bunch in one go
    109         boolean useDiffUploads = Main.pref.getBoolean("osm-server.atomic-upload",
    110             Main.pref.get("osm-server.version", "0.5").equals("0.6"));
    111 
     76        // solicit commit comment from user
    11277        String comment = null;
    11378        while (useChangesets && comment == null) {
     
    11782            if (comment == null)
    11883                return;
    119             /* Don't let people just hit enter */
    120             if( comment.trim().length() >= 3 )
     84            // Don't let people just hit enter
     85            if (comment.trim().length() >= 3)
    12186                break;
    12287            comment = null;
    12388        }
     89       
     90        // create changeset if required
    12491        try {
    125             if (useChangesets && !startChangeset(10, comment))
    126                 return;
    127         }
    128         catch (OsmTransferException ex) {
     92            if (useChangesets) api.createChangeset(comment);
     93        } catch (OsmTransferException ex) {
    12994            dealWithTransferException(ex);
    13095            return;
     
    13398        try {
    13499            if (useDiffUploads) {
    135                 uploadDiff(10, list);
     100                // all in one go
     101                processed.addAll(api.uploadDiff(list));
    136102            } else {
     103                // upload changes individually (90% of code is for the status display...)
    137104                NameVisitor v = new NameVisitor();
    138105                uploadStartTime = System.currentTimeMillis();
    139106                for (OsmPrimitive osm : list) {
    140                     if (cancel)
    141                         return;
    142107                    osm.visit(v);
    143108                    int progress = Main.pleaseWaitDlg.progress.getValue();
    144109                    String time_left_str = timeLeft(progress, list.size());
    145110                    Main.pleaseWaitDlg.currentAction.setText(
    146                     tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})",
    147                     Math.round(100.0*progress/list.size()), progress,
    148                     list.size(), time_left_str, tr(v.className), v.name, osm.id));
    149                     osm.visit(this);
     111                            tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})",
     112                                    Math.round(100.0*progress/list.size()), progress,
     113                                    list.size(), time_left_str, tr(v.className), v.name, osm.id));
     114                    makeApiRequest(osm);
     115                    processed.add(osm);
    150116                    Main.pleaseWaitDlg.progress.setValue(progress+1);
    151117                }
    152118            }
    153             if (useChangesets) stopChangeset(10);
    154         } catch (RuntimeException e) {
     119            if (useChangesets) api.stopChangeset();
     120        } catch (OsmTransferException e) {
    155121            try {
    156                 if (useChangesets) stopChangeset(10);
    157             }
    158             catch (OsmTransferException ex) {
    159                 dealWithTransferException(ex);
    160             }
    161             e.printStackTrace();
    162             throw new SAXException(tr("An error occurred: {0}",e.getMessage()));
    163         }
    164         catch (OsmTransferException e) {
    165             try {
    166                 if (useChangesets) stopChangeset(10);
    167             }
    168             catch (OsmTransferException ex) {
    169                 dealWithTransferException(ex);
     122                if (useChangesets) api.stopChangeset();
     123            } catch (Exception ee) {
     124                // ignore nested exception
    170125            }
    171126            dealWithTransferException(e);
     
    173128    }
    174129
    175     /* FIXME: This code is terrible, please fix it!!!! */
    176 
    177     /* Ok, this needs some explanation: The problem is that the code for
    178      * retrying requests is intertwined with the code that generates the
    179      * actual request. This means that for the retry code for the
    180      * changeset stuff, it's basically a copy/cut/change slightly
    181      * process. What actually needs to happen is that the retrying needs
    182      * to be split from the creation of the requests and the retry loop
    183      * handled in one place (preferably without recursion). While at you
    184      * can fix the issue where hitting cancel doesn't do anything while
    185      * retrying. - Mv0 Apr 2008
    186      *
    187      * Cancelling has an effect now, maybe it does not always catch on. Florian Heer, Aug 08
    188      */
    189     private boolean startChangeset(int retries, String comment) throws OsmTransferException {
    190         Main.pleaseWaitDlg.currentAction.setText(tr("Opening changeset..."));
    191         changeset = new Changeset();
    192         changeset.put( "created_by", "JOSM" );
    193         changeset.put( "comment", comment );
    194         try {
    195             if (cancel)
    196                 return false; // assume cancel
    197             String version = Main.pref.get("osm-server.version", "0.6");
    198             URL url = new URL(
    199                     Main.pref.get("osm-server.url") +
    200                     "/" + version +
    201                     "/" + "changeset" +
    202                     "/" + "create");
    203             System.out.print("upload to: "+url+ "..." );
    204             activeConnection = (HttpURLConnection)url.openConnection();
    205             activeConnection.setConnectTimeout(15000);
    206             activeConnection.setRequestMethod("PUT");
    207             addAuth(activeConnection);
    208 
    209             activeConnection.setDoOutput(true);
    210             OutputStream out = activeConnection.getOutputStream();
    211             OsmWriter.output(out, changeset);
    212             out.close();
    213 
    214             activeConnection.connect();
    215             System.out.println("connected");
    216 
    217             int retCode = activeConnection.getResponseCode();
    218             if (retCode == 200)
    219                 changeset.id = readId(activeConnection.getInputStream());
    220             System.out.println("got return: "+retCode+" with id "+changeset.id);
    221             String retMsg = activeConnection.getResponseMessage();
    222             activeConnection.disconnect();
    223             if (retCode == 404)    {
    224                 throw new OsmTransferException(tr("Server does not support changesets"));
    225             }
    226             if (retCode != 200 && retCode != 412) {
    227                 if (retries >= 0) {
    228                     retries--;
    229                     if(sleepAndListen()) return false;
    230                     System.out.println("retrying ("+retries+" left)");
    231                     return startChangeset(retries, comment);
    232                 }
    233 
    234                 // Look for a detailed error message from the server
    235                 retMsg += "\n" + readString(activeConnection.getInputStream());
    236 
    237                 // Report our error
    238                 ByteArrayOutputStream o = new ByteArrayOutputStream();
    239                 OsmWriter.output(o, changeset);
    240                 System.out.println(new String(o.toByteArray(), "UTF-8").toString());
    241                 throw new OsmTransferException (retCode + " " + retMsg);
    242             }
    243         } catch (UnknownHostException e) {
    244             throw new OsmTransferException(tr("Unknown host")+": "+e.getMessage(), e);
    245         } catch(SocketTimeoutException e) {
    246             System.out.println(" timed out, retries left: " + retries);
    247             if (cancel)
    248                 return false; // assume cancel
    249             if (retries-- > 0)
    250                 startChangeset(retries, comment);
    251             else
    252                 throw new OsmTransferException (e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    253         }
    254         catch (ConnectException e) {
    255             System.out.println(" timed out, retries left: " + retries);
    256             if (cancel)
    257                 return false; // assume cancel
    258             if (retries-- > 0)
    259                 startChangeset(retries, comment);
    260             else
    261                 throw new OsmTransferException (e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    262         }
    263 
    264         catch (Exception e) {
    265             if (cancel)
    266                 return false; // assume cancel
    267             if (e instanceof OsmTransferException)
    268                 throw (OsmTransferException)e;
    269             if (e instanceof RuntimeException)
    270                 throw (RuntimeException)e;
    271             throw new RuntimeException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    272         }
    273         return true;
    274     }
    275 
    276     private void uploadDiff(int retries, Collection<OsmPrimitive> list) throws OsmTransferException {
    277 
    278         CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset);
    279 
    280         for (OsmPrimitive osm : list) {
    281             int progress = Main.pleaseWaitDlg.progress.getValue();
    282             Main.pleaseWaitDlg.currentAction.setText(tr("Preparing..."));
    283             if (cancel)
    284                 return;
    285             osm.visit(duv);
    286             Main.pleaseWaitDlg.progress.setValue(progress+1);
    287         }
    288         System.out.println("the document:\n");
    289         String diff = duv.getDocument();
    290         System.out.println(diff);
    291 
    292         Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
    293         try {
    294             if (cancel)
    295                 return; // assume cancel
    296             String version = Main.pref.get("osm-server.version", "0.6");
    297             URL url = new URL(
    298                     Main.pref.get("osm-server.url") +
    299                     "/" + version +
    300                     "/" + "changeset" +
    301                     "/" + changeset.id +
    302                     "/upload" );
    303             System.out.print("upload to: "+url+ "..." );
    304             activeConnection = (HttpURLConnection)url.openConnection();
    305             activeConnection.setConnectTimeout(15000);
    306             activeConnection.setRequestMethod("POST");
    307             addAuth(activeConnection);
    308 
    309             activeConnection.setDoOutput(true);
    310             PrintWriter out;
    311             try {
    312                 out = new PrintWriter(new OutputStreamWriter(activeConnection.getOutputStream(), "UTF-8"));
    313             } catch (UnsupportedEncodingException e) {
    314                 throw new RuntimeException(e);
    315             }
    316             out.print(diff);
    317             out.close();
    318 
    319             activeConnection.connect();
    320             System.out.println("connected");
    321 
    322             int retCode = activeConnection.getResponseCode();
    323             String retMsg = "";
    324 
    325             if (retCode == 200) {
    326                 DiffResultReader.parseDiffResult(activeConnection.getInputStream(), list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
    327             } else if (retCode != 200 && retCode != 412) {
    328                 if (retries >= 0) {
    329                     retries--;
    330                     if(sleepAndListen()) return;
    331                     System.out.println("retrying ("+retries+" left)");
    332                     stopChangeset(retries);
    333                 } else {
    334                     // Look for a detailed error message from the server
    335                     retMsg += "\n" + readString(activeConnection.getInputStream());
    336 
    337                     // Report our error
    338                     ByteArrayOutputStream o = new ByteArrayOutputStream();
    339                     OsmWriter.output(o, changeset);
    340                     System.out.println(new String(o.toByteArray(), "UTF-8").toString());
    341                     throw new OsmTransferException(retCode+" "+retMsg);
    342                 }
    343             }
    344         } catch (UnknownHostException e) {
    345             throw new OsmTransferException(tr("Unknown host")+": "+e.getMessage(), e);
    346         } catch(SocketTimeoutException e) {
    347             System.out.println(" timed out, retries left: " + retries);
    348             if (cancel)
    349                 return; // assume cancel
    350             if (retries-- > 0)
    351                 stopChangeset(retries);
    352             else
    353                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    354         } catch(ConnectException e) {
    355             System.out.println(" timed out, retries left: " + retries);
    356             if (cancel)
    357                 return; // assume cancel
    358             if (retries-- > 0)
    359                 stopChangeset(retries);
    360             else
    361                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    362         } catch (Exception e) {
    363             if (cancel)
    364                 return; // assume cancel
    365             if (e instanceof OsmTransferException)
    366                 throw (OsmTransferException)e;
    367             if (e instanceof RuntimeException)
    368                 throw (RuntimeException)e;
    369             throw new RuntimeException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    370         }
    371     }
    372 
    373 
    374     private void stopChangeset(int retries) throws OsmTransferException {
    375         Main.pleaseWaitDlg.currentAction.setText(tr("Closing changeset..."));
    376         try {
    377             if (cancel)
    378                 return; // assume cancel
    379             String version = Main.pref.get("osm-server.version", "0.6");
    380             URL url = new URL(
    381                     Main.pref.get("osm-server.url") +
    382                     "/" + version +
    383                     "/" + "changeset" +
    384                     "/" + changeset.id +
    385                     "/close" );
    386             System.out.print("upload to: "+url+ "..." );
    387             activeConnection = (HttpURLConnection)url.openConnection();
    388             activeConnection.setConnectTimeout(15000);
    389             activeConnection.setRequestMethod("PUT");
    390             addAuth(activeConnection);
    391 
    392             activeConnection.setDoOutput(true);
    393             OutputStream out = activeConnection.getOutputStream();
    394             OsmWriter.output(out, changeset);
    395             out.close();
    396 
    397             activeConnection.connect();
    398             System.out.println("connected");
    399 
    400             int retCode = activeConnection.getResponseCode();
    401             System.out.println("got return: "+retCode);
    402             String retMsg = activeConnection.getResponseMessage();
    403             activeConnection.disconnect();
    404             if (retCode == 404)    {
    405                 System.out.println("Server does not support changesets, or the changeset could not be found, continuing");
    406                 return;
    407             }
    408             if (retCode != 200 && retCode != 412) {
    409                 if (retries >= 0) {
    410                     retries--;
    411                     if(sleepAndListen()) return;
    412                     System.out.println("retrying ("+retries+" left)");
    413                     stopChangeset(retries);
    414                 } else {
    415                     // Look for a detailed error message from the server
    416                     retMsg += readString(activeConnection.getInputStream());
    417 
    418                     // Report our error
    419                     ByteArrayOutputStream o = new ByteArrayOutputStream();
    420                     OsmWriter.output(o, changeset);
    421                     System.out.println(new String(o.toByteArray(), "UTF-8").toString());
    422                     throw new OsmTransferException(retCode+" "+retMsg);
    423                 }
    424             }
    425         } catch (UnknownHostException e) {
    426             throw new OsmTransferException(tr("Unknown host")+": "+e.getMessage(), e);
    427         } catch(SocketTimeoutException e) {
    428             System.out.println(" timed out, retries left: " + retries);
    429             if (cancel)
    430                 return; // assume cancel
    431             if (retries-- > 0)
    432                 stopChangeset(retries);
    433             else
    434                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    435         } catch(ConnectException e) {
    436             System.out.println(" timed out, retries left: " + retries);
    437             if (cancel)
    438                 return; // assume cancel
    439             if (retries-- > 0)
    440                 stopChangeset(retries);
    441             else
    442                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    443         } catch (Exception e) {
    444             if (cancel)
    445                 return; // assume cancel
    446             if (e instanceof OsmTransferException)
    447                 throw (OsmTransferException)e;
    448             if (e instanceof RuntimeException)
    449                 throw (RuntimeException)e;
    450             throw new RuntimeException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    451         }
    452     }
    453 
    454     private boolean sleepAndListen() {
    455         // System.out.print("backing off for 10 seconds...");
    456         for(int i=0; i < 10; i++) {
    457             if(cancel || isAuthCancelled()) {
    458                 if(!cancel) cancel();
    459                 return true;
    460             }
    461             try {
    462                 Thread.sleep(1000);
    463             } catch (InterruptedException ex) {}
    464         }
    465         return false;
    466     }
    467 
    468     /**
    469      * Upload a single node.
    470      */
    471     public void visit(Node n) {
    472         if (n.deleted) {
    473             sendRequest("DELETE", "node", n, true);
     130    void makeApiRequest(OsmPrimitive osm) throws OsmTransferException {
     131        if (osm.deleted) {
     132            api.deletePrimitive(osm);
     133        } else if (osm.id == 0) {
     134            api.createPrimitive(osm);
    474135        } else {
    475             sendRequest("PUT", "node", n, true);
    476         }
    477         processed.add(n);
    478     }
    479 
    480     /**
    481      * Upload a whole way with the complete node id list.
    482      */
    483     public void visit(Way w) {
    484         if (w.deleted) {
    485             sendRequest("DELETE", "way", w, true);
    486         } else {
    487             sendRequest("PUT", "way", w, true);
    488         }
    489         processed.add(w);
    490     }
    491 
    492     /**
    493      * Upload an relation with all members.
    494      */
    495     public void visit(Relation e) {
    496         if (e.deleted) {
    497             sendRequest("DELETE", "relation", e, true);
    498         } else {
    499             sendRequest("PUT", "relation", e, true);
    500         }
    501         processed.add(e);
    502     }
    503 
    504     /**
    505      * Read a long from the input stream and return it.
    506      */
    507     private long readId(InputStream inputStream) throws IOException {
    508         BufferedReader in = new BufferedReader(new InputStreamReader(
    509                 inputStream));
    510         String s = in.readLine();
    511         if (s == null)
    512             return 0;
    513         try {
    514             return Long.parseLong(s);
    515         } catch (NumberFormatException e) {
    516             return 0;
    517         }
    518     }
    519 
    520     /**
    521      * Consume the input stream and return it as a string.
    522      */
    523     private String readString(InputStream inputStream) throws IOException {
    524         BufferedReader in = new BufferedReader(new InputStreamReader(
    525                 inputStream));
    526         StringBuffer sb = new StringBuffer();
    527         String s;
    528         while((s = in.readLine()) != null) {
    529             sb.append(s);
    530             sb.append("\n");
    531         }
    532         return sb.toString();
    533     }
    534 
    535     /**
    536      * Send the request. The objects id will be replaced if it was 0 before
    537      * (on add requests).
    538      *
    539      * @param requestMethod The http method used when talking with the server.
    540      * @param urlSuffix The suffix to add at the server url.
    541      * @param osm The primitive to encode to the server.
    542      * @param body the body to be sent
    543      */
    544     private void sendRequestRetry(String requestMethod, String urlSuffix,
    545             OsmPrimitive osm, OsmWriterInterface body, int retries) throws OsmTransferException {
    546         try {
    547             if (cancel)
    548                 return; // assume cancel
    549             String version = Main.pref.get("osm-server.version", "0.5");
    550             URL url = new URL(
    551                     new URL(Main.pref.get("osm-server.url") +
    552                     "/" + version + "/"),
    553                     urlSuffix +
    554                     "/" + (osm.id==0 ? "create" : osm.id),
    555                     new MyHttpHandler());
    556             System.out.print("upload to: "+url+ "..." );
    557             activeConnection = (HttpURLConnection)url.openConnection();
    558             activeConnection.setConnectTimeout(15000);
    559             activeConnection.setRequestMethod(requestMethod);
    560             addAuth(activeConnection);
    561             if (body != null) {
    562                 activeConnection.setDoOutput(true);
    563                 OutputStream out = activeConnection.getOutputStream();
    564                 OsmWriter.output(out, body);
    565                 out.close();
    566             }
    567             activeConnection.connect();
    568             System.out.println("connected");
    569 
    570             int retCode = activeConnection.getResponseCode();
    571             /* When creating new, the returned value is the new id, otherwise it is the new version */
    572             if (retCode == 200)    {
    573                 if (osm.id == 0) {
    574                     osm.id = readId(activeConnection.getInputStream());
    575                     osm.version = 1;
    576                 } else {
    577                     int read_version = (int)readId(activeConnection.getInputStream());
    578                     if (read_version > 0)
    579                         osm.version = read_version;
    580                 }
    581             } else {
    582                 System.out.println("got return: "+retCode+" with id "+osm.id);
    583             }
    584             activeConnection.disconnect();
    585             if (retCode == 410 && requestMethod.equals("DELETE"))
    586                 return; // everything fine.. was already deleted.
    587             else if (retCode != 200) {
    588                 if (retries >= 0 && retCode != 412)    {
    589                     retries--;
    590                     if(sleepAndListen()) return;
    591                     System.out.println("retrying ("+retries+" left)");
    592                     sendRequestRetry(requestMethod, urlSuffix, osm, body, retries);
    593                 } else {
    594                     String retMsg = activeConnection.getResponseMessage();
    595                     // Look for a detailed error message from the server
    596                     if (activeConnection.getHeaderField("Error") != null)
    597                         retMsg += "\n" + activeConnection.getHeaderField("Error");
    598 
    599                     // Report our error
    600                     ByteArrayOutputStream o = new ByteArrayOutputStream();
    601                     OsmWriter.output(o, body);
    602                     System.out.println(new String(o.toByteArray(), "UTF-8").toString());
    603                     throw new OsmTransferException(retCode+" "+retMsg);
    604                 }
    605             }
    606         } catch (UnknownHostException e) {
    607             throw new OsmTransferException(tr("Unknown host")+": "+e.getMessage(), e);
    608         } catch(SocketTimeoutException e) {
    609             System.out.println(" timed out, retries left: " + retries);
    610             if (cancel)
    611                 return; // assume cancel
    612             if (retries-- > 0)
    613                 sendRequestRetry(requestMethod, urlSuffix, osm, body, retries);
    614             else
    615                 throw new OsmTransferException (e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    616         } catch(ConnectException e) {
    617             System.out.println(" timed out, retries left: " + retries);
    618             if (cancel)
    619                 return; // assume cancel
    620             if (retries-- > 0)
    621                 sendRequestRetry(requestMethod, urlSuffix, osm, body, retries);
    622             else
    623                 throw new OsmTransferException (e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    624         } catch (Exception e) {
    625             if (cancel)
    626                 return; // assume cancel
    627             if (e instanceof OsmTransferException)
    628                 throw (OsmTransferException)e;
    629             if (e instanceof RuntimeException)
    630                 throw (RuntimeException)e;
    631             throw new RuntimeException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    632         }
    633     }
    634 
    635     private void sendRequest(String requestMethod, String urlSuffix,
    636             OsmPrimitive osm, boolean addBody)  {
    637         XmlWriter.OsmWriterInterface body = null;
    638         if (addBody) {
    639                 body = new OsmWriter.Single(osm, true, changeset);
    640         }
    641         try {
    642             sendRequestRetry(requestMethod, urlSuffix, osm, body, 10);
    643         }
    644         catch (OsmTransferException e) {
    645             dealWithTransferException (e);
     136            api.modifyPrimitive(osm);
    646137        }
    647138    }
     
    649140    private void dealWithTransferException (OsmTransferException e) {
    650141        Main.pleaseWaitDlg.currentAction.setText(tr("Transfer aborted due to error (will wait for 5 seconds):") + e.getMessage());
    651         cancel = true;
    652142        try {
    653143            Thread.sleep(5000);
  • trunk/src/org/openstreetmap/josm/io/OsmWriter.java

    r1499 r1523  
    66import java.util.Map.Entry;
    77
    8 import org.openstreetmap.josm.Main;
     8import org.openstreetmap.josm.data.osm.Changeset;
    99import org.openstreetmap.josm.data.osm.DataSet;
    1010import org.openstreetmap.josm.data.osm.DataSource;
     11import org.openstreetmap.josm.data.osm.Node;
     12import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1113import org.openstreetmap.josm.data.osm.Relation;
    1214import org.openstreetmap.josm.data.osm.RelationMember;
    13 import org.openstreetmap.josm.data.osm.Node;
    14 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    15 import org.openstreetmap.josm.data.osm.Changeset;
    1615import org.openstreetmap.josm.data.osm.Way;
    1716import org.openstreetmap.josm.data.osm.visitor.Visitor;
     
    2625
    2726    /**
    28      * The counter for new created objects. Starting at -1 and goes down.
     27     * The counter for newly created objects. Starts at -1 and goes down.
    2928     */
    3029    private long newIdCounter = -1;
     30 
    3131    /**
    3232     * All newly created ids and their primitive that uses it. This is a back reference
     
    3535    public HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();
    3636
    37     private final boolean osmConform;
    38     private final Changeset changeset;
    39 
    40     public abstract static class Osm implements OsmWriterInterface {
    41         public void header(PrintWriter out) {
    42             out.print("<osm version='");
    43             out.print(Main.pref.get("osm-server.version", "0.5"));
    44             out.println("' generator='JOSM'>");
    45         }
    46         public void footer(PrintWriter out) {
    47             out.println("</osm>");
    48         }
    49     }
    50 
    51     // simple helper to write the object's class to the out stream
    52     private Visitor typeWriteVisitor = new Visitor() {
    53         public void visit(Node n) { out.print("node"); }
    54         public void visit(Way w) { out.print("way"); }
    55         public void visit(Relation e) { out.print("relation"); }
    56     };
    57 
    58     /**
    59      * An output writer for function output that writes everything of the given dataset into
    60      * the xml
    61      */
    62     public static final class All extends Osm {
    63         private final DataSet ds;
    64         private final boolean osmConform;
    65 
    66         /**
    67          * Construct an writer function
    68          * @param osmConform <code>true</code>, if the xml should be 100% osm conform. In this
    69          *      case, not all information can be retrieved later (as example, modified state
    70          *      is lost and id's remain 0 instead of decrementing from -1)
    71          */
    72         public All(DataSet ds, boolean osmConform) {
    73             this.ds = ds;
    74             this.osmConform = osmConform;
    75         }
    76 
    77         public void write(PrintWriter out) {
    78             Visitor writer = new OsmWriter(out, osmConform, null);
    79             for (Node n : ds.nodes)
    80                 if (shouldWrite(n))
    81                     writer.visit(n);
    82             for (Way w : ds.ways)
    83                 if (shouldWrite(w))
    84                     writer.visit(w);
    85             for (Relation e : ds.relations)
    86                 if (shouldWrite(e))
    87                     writer.visit(e);
    88         }
    89 
    90         private boolean shouldWrite(OsmPrimitive osm) {
    91             return osm.id != 0 || !osm.deleted;
    92         }
    93 
    94         @Override public void header(PrintWriter out) {
    95             super.header(out);
    96             for (DataSource s : ds.dataSources) {
    97                 out.println("  <bounds minlat='"
    98                 + s.bounds.min.lat()+"' minlon='"
    99                 + s.bounds.min.lon()+"' maxlat='"
    100                 + s.bounds.max.lat()+"' maxlon='"
    101                 + s.bounds.max.lon()
    102                 +"' origin='"+XmlWriter.encode(s.origin)+"' />");
    103             }
    104         }
    105     }
    106 
    107     /**
    108      * An output writer for functino output that writes only one specific primitive into
    109      * the xml
    110      */
    111     public static final class Single extends Osm {
    112         private final OsmPrimitive osm;
    113         private final boolean osmConform;
    114         private final Changeset changeset;
    115 
    116         public Single(OsmPrimitive osm, boolean osmConform, Changeset changeset) {
    117             this.osm = osm;
    118             this.osmConform = osmConform;
    119             this.changeset = changeset;
    120         }
    121 
    122         public void write(PrintWriter out) {
    123             osm.visit(new OsmWriter(out, osmConform, changeset));
    124         }
    125     }
    126 
    127     public OsmWriter(PrintWriter out, boolean osmConform, Changeset changeset) {
     37    private boolean osmConform;
     38    private boolean withBody = true;
     39    private String version;
     40    private Changeset changeset;
     41   
     42    public OsmWriter(PrintWriter out, boolean osmConform, String version) {
    12843        super(out);
    12944        this.osmConform = osmConform;
    130         this.changeset = changeset;
     45        this.version = version;
     46    }
     47   
     48    public void setWithBody(boolean wb) {
     49        this.withBody = wb;
     50    }
     51    public void setChangeset(Changeset cs) {
     52        this.changeset = cs;
     53    }
     54    public void setVersion(String v) {
     55        this.version = v;
     56    }
     57   
     58    public void header() {
     59        out.println("<?xml version='1.0' encoding='UTF-8'?>");
     60        out.print("<osm version='");
     61        out.print(version);
     62        out.println("' generator='JOSM'>");
     63    }
     64    public void footer() {
     65        out.println("</osm>");
     66    }
     67
     68    public void writeContent(DataSet ds) {
     69        for (Node n : ds.nodes)
     70            if (shouldWrite(n))
     71                visit(n);
     72        for (Way w : ds.ways)
     73            if (shouldWrite(w))
     74                visit(w);
     75        for (Relation e : ds.relations)
     76            if (shouldWrite(e))
     77                visit(e);
     78    }
     79
     80    private boolean shouldWrite(OsmPrimitive osm) {
     81        return osm.id != 0 || !osm.deleted;
     82    }
     83
     84    public void writeDataSources(DataSet ds) {
     85        for (DataSource s : ds.dataSources) {
     86            out.println("  <bounds minlat='"
     87                    + s.bounds.min.lat()+"' minlon='"
     88                    + s.bounds.min.lon()+"' maxlat='"
     89                    + s.bounds.max.lat()+"' maxlon='"
     90                    + s.bounds.max.lon()
     91                    +"' origin='"+XmlWriter.encode(s.origin)+"' />");
     92        }
    13193    }
    13294
     
    13597        addCommon(n, "node");
    13698        out.print(" lat='"+n.coor.lat()+"' lon='"+n.coor.lon()+"'");
    137         addTags(n, "node", true);
     99        if (!withBody) {
     100            out.println("/>"); 
     101        } else {
     102            addTags(n, "node", true);
     103        }
    138104    }
    139105
     
    141107        if (w.incomplete) return;
    142108        addCommon(w, "way");
    143         out.println(">");
    144         for (Node n : w.nodes)
    145             out.println("    <nd ref='"+getUsedId(n)+"' />");
    146         addTags(w, "way", false);
     109        if (!withBody) {
     110            out.println("/>"); 
     111        } else {
     112            out.println(">");
     113            for (Node n : w.nodes)
     114                out.println("    <nd ref='"+getUsedId(n)+"' />");
     115            addTags(w, "way", false);
     116        }
    147117    }
    148118
     
    150120        if (e.incomplete) return;
    151121        addCommon(e, "relation");
    152         out.println(">");
    153         for (RelationMember em : e.members) {
    154             out.print("    <member type='");
    155             em.member.visit(typeWriteVisitor);
    156             out.println("' ref='"+getUsedId(em.member)+"' role='" +
    157                 XmlWriter.encode(em.role) + "' />");
    158         }
    159         addTags(e, "relation", false);
    160     }
    161 
     122        if (!withBody) {
     123            out.println("/>"); 
     124        } else {
     125            out.println(">");
     126            for (RelationMember em : e.members) {
     127                out.print("    <member type='");
     128                out.print(OsmApi.which(em.member));
     129                out.println("' ref='"+getUsedId(em.member)+"' role='" +
     130                        XmlWriter.encode(em.role) + "' />");
     131            }
     132            addTags(e, "relation", false);
     133        }
     134    }
     135
     136    public void visit(Changeset cs) {
     137        addCommon(cs, "changeset");
     138        out.println(">\n");
     139        addTags(cs, "changeset", false);
     140    }
     141
     142    public final void footer(PrintWriter out) {
     143        out.println("</osm>");
     144    }
    162145
    163146    /**
     
    192175     */
    193176    private void addCommon(OsmPrimitive osm, String tagname) {
    194         out.print("  <"+tagname+" id='"+getUsedId(osm)+"'");
     177        long id = getUsedId(osm);
     178        out.print("  <"+tagname);
     179        if (id != 0) {
     180             out.print(" id='"+getUsedId(osm)+"'");
     181        }
    195182        if (!osmConform) {
    196183            String action = null;
  • trunk/src/org/openstreetmap/josm/io/XmlWriter.java

    r1169 r1523  
    22package org.openstreetmap.josm.io;
    33
    4 import java.io.OutputStream;
    5 import java.io.OutputStreamWriter;
    64import java.io.PrintWriter;
    7 import java.io.UnsupportedEncodingException;
    85import java.util.HashMap;
    96
     
    1512public class XmlWriter {
    1613
    17     /**
    18      * The interface to write the data into an Osm stream
    19      * @author immanuel.scholz
    20      */
    21     public static interface OsmWriterInterface {
    22         void header(PrintWriter out);
    23         void write(PrintWriter out);
    24         void footer(PrintWriter out);
    25     }
    26 
    27 
    28     protected XmlWriter(PrintWriter out) {
     14    protected PrintWriter out;
     15   
     16    public XmlWriter(PrintWriter out) {
    2917        this.out = out;
    3018    }
    31 
     19   
    3220    /**
    3321     * Encode the given string in XML1.0 format.
     
    4937
    5038    /**
    51      * Write the header and start tag, then call the runnable to add all real tags and finally
    52      * "closes" the xml by writing the footer.
    53      */
    54     public static void output(OutputStream outStream, OsmWriterInterface outputWriter) {
    55         PrintWriter out;
    56         try {
    57             out = new PrintWriter(new OutputStreamWriter(outStream, "UTF-8"));
    58         } catch (UnsupportedEncodingException e) {
    59             throw new RuntimeException(e);
    60         }
    61         out.println("<?xml version='1.0' encoding='UTF-8'?>");
    62         outputWriter.header(out);
    63         outputWriter.write(out);
    64         outputWriter.footer(out);
    65         out.flush();
    66         out.close();
    67     }
    68 
    69     /**
    7039     * The output writer to save the values to.
    7140     */
    72     protected final PrintWriter out;
    7341    final private static HashMap<Character, String> encoding = new HashMap<Character, String>();
    7442    static {
Note: See TracChangeset for help on using the changeset viewer.