Ignore:
Timestamp:
2008-12-23T15:07:05+01:00 (18 years ago)
Author:
stoecker
Message:

removed usage of tab stops

Location:
trunk/src/org/openstreetmap/josm/io
Files:
19 edited

Legend:

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

    r999 r1169  
    1515public class BoundingBoxDownloader extends OsmServerReader {
    1616
    17         /**
    18         * The boundings of the desired map data.
    19         */
    20         private final double lat1;
    21         private final double lon1;
    22         private final double lat2;
    23         private final double lon2;
     17    /**
     18    * The boundings of the desired map data.
     19    */
     20    private final double lat1;
     21    private final double lon1;
     22    private final double lat2;
     23    private final double lon2;
    2424
    25         public BoundingBoxDownloader(double lat1, double lon1, double lat2, double lon2) {
    26                 this.lat1 = lat1;
    27                 this.lon1 = lon1;
    28                 this.lat2 = lat2;
    29                 this.lon2 = lon2;
    30                 // store the bounding box in the preferences so it can be
    31                 // re-used across invocations of josm
    32                 Main.pref.put("osm-download.bounds", lat1+";"+lon1+";"+lat2+";"+lon2);
    33         }
     25    public BoundingBoxDownloader(double lat1, double lon1, double lat2, double lon2) {
     26        this.lat1 = lat1;
     27        this.lon1 = lon1;
     28        this.lat2 = lat2;
     29        this.lon2 = lon2;
     30        // store the bounding box in the preferences so it can be
     31        // re-used across invocations of josm
     32        Main.pref.put("osm-download.bounds", lat1+";"+lon1+";"+lat2+";"+lon2);
     33    }
    3434
    35         /**
    36         * Retrieve raw gps waypoints from the server API.
    37         * @return A list of all primitives retrieved. Currently, the list of lists
    38         *      contain only one list, since the server cannot distinguish between
    39         *      ways.
    40         */
    41         public GpxData parseRawGps() throws IOException, SAXException {
    42                 Main.pleaseWaitDlg.progress.setValue(0);
    43                 Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
    44                 try {
    45                         String url = "trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=";
     35    /**
     36    * Retrieve raw gps waypoints from the server API.
     37    * @return A list of all primitives retrieved. Currently, the list of lists
     38    *      contain only one list, since the server cannot distinguish between
     39    *      ways.
     40    */
     41    public GpxData parseRawGps() throws IOException, SAXException {
     42        Main.pleaseWaitDlg.progress.setValue(0);
     43        Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
     44        try {
     45            String url = "trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=";
    4646
    47                         boolean done = false;
    48                         GpxData result = null;
    49                         for (int i = 0;!done;++i) {
    50                                 Main.pleaseWaitDlg.currentAction.setText(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
    51                                 InputStream in = getInputStream(url+i, Main.pleaseWaitDlg);
    52                                 if (in == null)
    53                                         break;
    54                                 GpxData currentGpx = new GpxReader(in, null).data;
    55                                 if (result == null) {
    56                                         result = currentGpx;
    57                                 } else if (currentGpx.hasTrackPoints()) {
    58                                         result.mergeFrom(currentGpx);
    59                                 } else{
    60                                         done = true;
    61                                 }
    62                                 in.close();
    63                                 activeConnection = null;
    64                         }
    65                         result.fromServer = true;
    66                         return result;
    67                 } catch (IllegalArgumentException e) {
    68                         // caused by HttpUrlConnection in case of illegal stuff in the response
    69                         if (cancel)
    70                                 return null;
    71                         throw new SAXException("Illegal characters within the HTTP-header response", e);
    72                 } catch (IOException e) {
    73                         if (cancel)
    74                                 return null;
    75                         throw e;
    76                 } catch (SAXException e) {
    77                         throw e;
    78                 } catch (Exception e) {
    79                         if (cancel)
    80                                 return null;
    81                         if (e instanceof RuntimeException)
    82                                 throw (RuntimeException)e;
    83                         throw new RuntimeException(e);
    84                 }
    85         }
     47            boolean done = false;
     48            GpxData result = null;
     49            for (int i = 0;!done;++i) {
     50                Main.pleaseWaitDlg.currentAction.setText(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000)));
     51                InputStream in = getInputStream(url+i, Main.pleaseWaitDlg);
     52                if (in == null)
     53                    break;
     54                GpxData currentGpx = new GpxReader(in, null).data;
     55                if (result == null) {
     56                    result = currentGpx;
     57                } else if (currentGpx.hasTrackPoints()) {
     58                    result.mergeFrom(currentGpx);
     59                } else{
     60                    done = true;
     61                }
     62                in.close();
     63                activeConnection = null;
     64            }
     65            result.fromServer = true;
     66            return result;
     67        } catch (IllegalArgumentException e) {
     68            // caused by HttpUrlConnection in case of illegal stuff in the response
     69            if (cancel)
     70                return null;
     71            throw new SAXException("Illegal characters within the HTTP-header response", e);
     72        } catch (IOException e) {
     73            if (cancel)
     74                return null;
     75            throw e;
     76        } catch (SAXException e) {
     77            throw e;
     78        } catch (Exception e) {
     79            if (cancel)
     80                return null;
     81            if (e instanceof RuntimeException)
     82                throw (RuntimeException)e;
     83            throw new RuntimeException(e);
     84        }
     85    }
    8686
    87         /**
    88         * Read the data from the osm server address.
    89         * @return A data set containing all data retrieved from that url
    90         */
    91         public DataSet parseOsm() throws SAXException, IOException {
    92                 try {
    93                         Main.pleaseWaitDlg.progress.setValue(0);
    94                         Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
    95                         final InputStream in = getInputStream("map?bbox="+lon1+","+lat1+","+lon2+","+lat2, Main.pleaseWaitDlg);
    96                         if (in == null)
    97                                 return null;
    98                         Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
    99                         final DataSet data = OsmReader.parseDataSet(in, null, Main.pleaseWaitDlg);
    100                         in.close();
    101                         activeConnection = null;
    102                         return data;
    103                 } catch (IOException e) {
    104                         if (cancel)
    105                                 return null;
    106                         throw e;
    107                 } catch (SAXException e) {
    108                         throw e;
    109                 } catch (Exception e) {
    110                         if (cancel)
    111                                 return null;
    112                         if (e instanceof RuntimeException)
    113                                 throw (RuntimeException)e;
    114                         throw new RuntimeException(e);
    115                 }
    116         }
     87    /**
     88    * Read the data from the osm server address.
     89    * @return A data set containing all data retrieved from that url
     90    */
     91    public DataSet parseOsm() throws SAXException, IOException {
     92        try {
     93            Main.pleaseWaitDlg.progress.setValue(0);
     94            Main.pleaseWaitDlg.currentAction.setText(tr("Contacting OSM Server..."));
     95            final InputStream in = getInputStream("map?bbox="+lon1+","+lat1+","+lon2+","+lat2, Main.pleaseWaitDlg);
     96            if (in == null)
     97                return null;
     98            Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
     99            final DataSet data = OsmReader.parseDataSet(in, null, Main.pleaseWaitDlg);
     100            in.close();
     101            activeConnection = null;
     102            return data;
     103        } catch (IOException e) {
     104            if (cancel)
     105                return null;
     106            throw e;
     107        } catch (SAXException e) {
     108            throw e;
     109        } catch (Exception e) {
     110            if (cancel)
     111                return null;
     112            if (e instanceof RuntimeException)
     113                throw (RuntimeException)e;
     114            throw new RuntimeException(e);
     115        }
     116    }
    117117}
  • trunk/src/org/openstreetmap/josm/io/DiffResultReader.java

    r1071 r1169  
    4141 */
    4242public class DiffResultReader implements Visitor {
    43    
     43
    4444    /**
    4545     * mapping from old id to new id/version
    … …  
    4747    private Map<String, Long[]> versions = new HashMap<String, Long[]>();
    4848    private Collection<OsmPrimitive> processed;
    49     private Map<OsmPrimitive,Long> newIdMap; 
     49    private Map<OsmPrimitive,Long> newIdMap;
    5050
    51     /** 
     51    /**
    5252     * List of protocol versions that will be accepted on reading
    5353     */
    54    
     54
    5555    private class Parser extends DefaultHandler {
    5656
    … …  
    8181     *  elemet found there is returned.
    8282     */
    83     public static void parseDiffResult(InputStream source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, PleaseWaitDialog pleaseWaitDlg) 
     83    public static void parseDiffResult(InputStream source, Collection<OsmPrimitive> osm, Collection<OsmPrimitive> processed, Map<OsmPrimitive,Long> newIdMap, PleaseWaitDialog pleaseWaitDlg)
    8484    throws SAXException, IOException {
    8585
    … …  
    107107       }
    108108    }
    109    
     109
    110110    public void visit(Node n) {
    111111        String key = "node:" + (newIdMap.containsKey(n) ? newIdMap.get(n) : n.id);
    … …  
    127127                w.id = nv[0]; w.version = nv[1].intValue();
    128128            }
    129         }       
     129        }
    130130    }
    131131    public void visit(Relation r) {
    … …  
    137137                r.id = nv[0]; r.version = nv[1].intValue();
    138138            }
    139         }   
     139        }
    140140    }
    141141}
  • trunk/src/org/openstreetmap/josm/io/GpxReader.java

    r1122 r1169  
    3535 */
    3636public class GpxReader {
    37         // TODO: implement GPX 1.0 parsing
    38 
    39         /**
    40         * The resulting gpx data
    41         */
    42         public GpxData data;
    43         public enum state { init, metadata, wpt, rte, trk, ext, author, link, trkseg }
    44 
    45         private class Parser extends DefaultHandler {
    46 
    47                 private GpxData currentData;
    48                 private GpxTrack currentTrack;
    49                 private Collection<WayPoint> currentTrackSeg;
    50                 private GpxRoute currentRoute;
    51                 private WayPoint currentWayPoint;
    52 
    53                 private state currentState = state.init;
    54        
    55                 private GpxLink currentLink;
    56                 private Stack<state> states;
    57 
    58                 private StringBuffer accumulator = new StringBuffer();
    59 
    60                 @Override public void startDocument() {
    61                         accumulator = new StringBuffer();
    62                         states = new Stack<state>();
    63                         currentData = new GpxData();
    64                 }               
    65 
    66                 private double parseCoord(String s) {
    67                         try {
    68                                 return Double.parseDouble(s);
    69                         } catch (NumberFormatException ex) {
    70                                 return Double.NaN;
    71                         }
    72                 }
    73 
    74                 private LatLon parseLatLon(Attributes atts) {
    75                         return new LatLon(
    76                                 parseCoord(atts.getValue("lat")),
    77                                 parseCoord(atts.getValue("lon")));
    78                 }
    79 
    80                 @Override public void startElement(String namespaceURI, String qName, String rqName, Attributes atts) throws SAXException {
    81                         switch(currentState) {
    82                         case init:
    83                                 if (qName.equals("metadata")) {
    84                                         states.push(currentState);
    85                                         currentState = state.metadata;
    86                                 } else if (qName.equals("wpt")) {
    87                                         states.push(currentState);
    88                                         currentState = state.wpt;
    89                                         currentWayPoint = new WayPoint(parseLatLon(atts));
    90                                 } else if (qName.equals("rte")) {
    91                                         states.push(currentState);
    92                                         currentState = state.rte;
    93                                         currentRoute = new GpxRoute();
    94                                 } else if (qName.equals("trk")) {
    95                                         states.push(currentState);
    96                                         currentState = state.trk;
    97                                         currentTrack = new GpxTrack();
    98                                 } else if (qName.equals("extensions")) {
    99                                         states.push(currentState);
    100                                         currentState = state.ext;
    101                                 }
    102                                 break;
    103                         case author:
    104                                 if (qName.equals("link")) {
    105                                         states.push(currentState);
    106                                         currentState = state.link;
    107                                         currentLink = new GpxLink(atts.getValue("href"));
    108                                 }
    109                                 break;
    110                         case trk:
    111                                 if (qName.equals("trkseg")) {
    112                                         states.push(currentState);
    113                                         currentState = state.trkseg;
    114                                         currentTrackSeg = new ArrayList<WayPoint>();
    115                                 } else if (qName.equals("link")) {
    116                                         states.push(currentState);
    117                                         currentState = state.link;
    118                                         currentLink = new GpxLink(atts.getValue("href"));
    119                                 } else if (qName.equals("extensions")) {
    120                                         states.push(currentState);
    121                                         currentState = state.ext;
    122                                 }
    123                                 break;
    124                         case metadata:
    125                                 if (qName.equals("author")) {
    126                                         states.push(currentState);
    127                                         currentState = state.author;
    128                                 } else if (qName.equals("extensions")) {
    129                                         states.push(currentState);
    130                                         currentState = state.ext;
    131                                 }
    132                                 break;
    133                         case trkseg:
    134                                 if (qName.equals("trkpt")) {
    135                                         states.push(currentState);
    136                                         currentState = state.wpt;
    137                                         currentWayPoint = new WayPoint(parseLatLon(atts));
    138                                 }
    139                                 break;
    140                         case wpt:
    141                                 if (qName.equals("link")) {
    142                                         states.push(currentState);
    143                                         currentState = state.link;
    144                                         currentLink = new GpxLink(atts.getValue("href"));
    145                                 } else if (qName.equals("extensions")) {
    146                                         states.push(currentState);
    147                                         currentState = state.ext;
    148                                 }
    149                                 break;
    150                         case rte:
    151                                 if (qName.equals("link")) {
    152                                         states.push(currentState);
    153                                         currentState = state.link;
    154                                         currentLink = new GpxLink(atts.getValue("href"));
    155                                 } else if (qName.equals("rtept")) {
    156                                         states.push(currentState);
    157                                         currentState = state.wpt;
    158                                         currentWayPoint = new WayPoint(parseLatLon(atts));
    159                                 } else if (qName.equals("extensions")) {
    160                                         states.push(currentState);
    161                                         currentState = state.ext;
    162                                 }
    163                                 break;
    164                         default:
    165                         }
    166                         accumulator.setLength(0);
    167                 }
    168 
    169                 @Override public void characters(char[] ch, int start, int length) {
    170                         accumulator.append(ch, start, length);
    171                 }
    172 
    173                 private Map<String, Object> getAttr() {
    174                         switch (currentState) {
    175                                 case rte: return currentRoute.attr;
    176                                 case metadata: return currentData.attr;
    177                                 case wpt: return currentWayPoint.attr;
    178                                 case trk: return currentTrack.attr;
    179                                 default: return null;
    180                         }
    181                 }
    182 
    183                 @Override public void endElement(String namespaceURI, String qName, String rqName) {
    184                         switch (currentState) {
    185                         case metadata:
    186                                 if (qName.equals("name") || qName.equals("desc") ||
    187                                                 qName.equals("time") || qName.equals("keywords")) {
    188                                         currentData.attr.put(qName, accumulator.toString());
    189                                 } else if (qName.equals("metadata")) {
    190                                         currentState = states.pop();
    191                                 }
    192                                 //TODO: parse copyright, bounds, extensions
    193                                 break;
    194                         case author:
    195                                 if (qName.equals("author")) {
    196                                         currentState = states.pop();
    197                                 } else if (qName.equals("name") || qName.equals("email")) {
    198                                         currentData.attr.put("author" + qName, accumulator.toString());
    199                                 } else if (qName.equals("link")) {
    200                                         currentData.attr.put("authorlink", currentLink);
    201                                 }
    202                                 break;
    203                         case link:
    204                                 if (qName.equals("text")) {
    205                                         currentLink.text = accumulator.toString();
    206                                 } else if (qName.equals("type")) {
    207                                         currentLink.type = accumulator.toString();
    208                                 } else if (qName.equals("link")) {
    209                                         // <link>URL</link>
    210                                         if (currentLink.uri == null)
    211                                                 currentLink.uri = accumulator.toString();
    212 
    213                                         currentState = states.pop();
    214                                 }
    215                                 if (currentState == state.author) {
    216                                         currentData.attr.put("authorlink", currentLink);
    217                                 } else if (currentState != state.link) {
    218                                         Map<String, Object> attr = getAttr();
    219                                         if (!attr.containsKey("link")) {
    220                                                 attr.put("link", new LinkedList<GpxLink>());
    221                                         }
    222                                         ((Collection<GpxLink>) attr.get("link")).add(currentLink);
    223                                 }
    224                                 break;
    225                         case wpt:
    226                                 if (qName.equals("ele") || qName.equals("magvar")
    227                                                 || qName.equals("geoidheight") || qName.equals("name")
    228                                                 || qName.equals("sym") || qName.equals("type")) {
    229                                         currentWayPoint.attr.put(qName, accumulator.toString());
    230                                 } else if (qName.equals("time")) {
    231                                         currentWayPoint.attr.put(qName, accumulator.toString());
    232                                         currentWayPoint.setTime();                                     
    233                                 } else if (qName.equals("cmt") || qName.equals("desc")) {
    234                                         currentWayPoint.attr.put(qName, accumulator.toString());
    235                                         currentWayPoint.setGarminCommentTime(qName);                                   
    236                                 } else if (qName.equals("rtept")) {
    237                                         currentState = states.pop();
    238                                         currentRoute.routePoints.add(currentWayPoint);
    239                                 } else if (qName.equals("trkpt")) {
    240                                         currentState = states.pop();
    241                                         currentTrackSeg.add(currentWayPoint);
    242                                 } else if (qName.equals("wpt")) {
    243                                         currentState = states.pop();
    244                                         currentData.waypoints.add(currentWayPoint);
    245                                 }
    246                                 break;
    247                         case trkseg:
    248                                 if (qName.equals("trkseg")) {
    249                                         currentState = states.pop();
    250                                         currentTrack.trackSegs.add(currentTrackSeg);
    251                                 }
    252                                 break;
    253                         case trk:
    254                                 if (qName.equals("trk")) {
    255                                         currentState = states.pop();
    256                                         currentData.tracks.add(currentTrack);
    257                                 } else if (qName.equals("name") || qName.equals("cmt")
    258                                                 || qName.equals("desc") || qName.equals("src")
    259                                                 || qName.equals("type") || qName.equals("number")) {
    260                                         currentTrack.attr.put(qName, accumulator.toString());
    261                                 }
    262                                 break;
    263                         case ext:
    264                                 if (qName.equals("extensions")) {
    265                                         currentState = states.pop();
    266                                 }
    267                                 break;
    268                         default:
    269                                 if (qName.equals("wpt")) {
    270                                         currentState = states.pop();
    271                                 } else if (qName.equals("rte")) {
    272                                         currentState = states.pop();
    273                                         currentData.routes.add(currentRoute);
    274                                 }
    275                         }
    276                 }
    277 
    278                 @Override public void endDocument() throws SAXException  {
    279                         if (!states.empty()) {
    280                                 throw new SAXException(tr("Parse error: invalid document structure for gpx document"));
    281                         }
    282                         data = currentData;
    283                 }
    284         }
    285 
    286         /**
    287         * Parse the input stream and store the result in trackData and markerData
    288          *
    289         * @param relativeMarkerPath The directory to use as relative path for all &lt;wpt&gt; 
    290         *    marker tags. Maybe <code>null</code>, in which case no relative urls are constructed for the markers. 
    291         */
    292         public GpxReader(InputStream source, File relativeMarkerPath) throws SAXException, IOException {
    293                
    294                 Parser parser = new Parser();
    295                 InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
    296                 try {
    297                         SAXParserFactory factory = SAXParserFactory.newInstance();
    298                         factory.setNamespaceAware(true);
    299                         factory.newSAXParser().parse(inputSource, parser);
    300                 } catch (ParserConfigurationException e) {
    301                         e.printStackTrace(); // broken SAXException chaining
    302                         throw new SAXException(e);
    303                 }
    304         }
     37    // TODO: implement GPX 1.0 parsing
     38
     39    /**
     40    * The resulting gpx data
     41    */
     42    public GpxData data;
     43    public enum state { init, metadata, wpt, rte, trk, ext, author, link, trkseg }
     44
     45    private class Parser extends DefaultHandler {
     46
     47        private GpxData currentData;
     48        private GpxTrack currentTrack;
     49        private Collection<WayPoint> currentTrackSeg;
     50        private GpxRoute currentRoute;
     51        private WayPoint currentWayPoint;
     52
     53        private state currentState = state.init;
     54
     55        private GpxLink currentLink;
     56        private Stack<state> states;
     57
     58        private StringBuffer accumulator = new StringBuffer();
     59
     60        @Override public void startDocument() {
     61            accumulator = new StringBuffer();
     62            states = new Stack<state>();
     63            currentData = new GpxData();
     64        }
     65
     66        private double parseCoord(String s) {
     67            try {
     68                return Double.parseDouble(s);
     69            } catch (NumberFormatException ex) {
     70                return Double.NaN;
     71            }
     72        }
     73
     74        private LatLon parseLatLon(Attributes atts) {
     75            return new LatLon(
     76                parseCoord(atts.getValue("lat")),
     77                parseCoord(atts.getValue("lon")));
     78        }
     79
     80        @Override public void startElement(String namespaceURI, String qName, String rqName, Attributes atts) throws SAXException {
     81            switch(currentState) {
     82            case init:
     83                if (qName.equals("metadata")) {
     84                    states.push(currentState);
     85                    currentState = state.metadata;
     86                } else if (qName.equals("wpt")) {
     87                    states.push(currentState);
     88                    currentState = state.wpt;
     89                    currentWayPoint = new WayPoint(parseLatLon(atts));
     90                } else if (qName.equals("rte")) {
     91                    states.push(currentState);
     92                    currentState = state.rte;
     93                    currentRoute = new GpxRoute();
     94                } else if (qName.equals("trk")) {
     95                    states.push(currentState);
     96                    currentState = state.trk;
     97                    currentTrack = new GpxTrack();
     98                } else if (qName.equals("extensions")) {
     99                    states.push(currentState);
     100                    currentState = state.ext;
     101                }
     102                break;
     103            case author:
     104                if (qName.equals("link")) {
     105                    states.push(currentState);
     106                    currentState = state.link;
     107                    currentLink = new GpxLink(atts.getValue("href"));
     108                }
     109                break;
     110            case trk:
     111                if (qName.equals("trkseg")) {
     112                    states.push(currentState);
     113                    currentState = state.trkseg;
     114                    currentTrackSeg = new ArrayList<WayPoint>();
     115                } else if (qName.equals("link")) {
     116                    states.push(currentState);
     117                    currentState = state.link;
     118                    currentLink = new GpxLink(atts.getValue("href"));
     119                } else if (qName.equals("extensions")) {
     120                    states.push(currentState);
     121                    currentState = state.ext;
     122                }
     123                break;
     124            case metadata:
     125                if (qName.equals("author")) {
     126                    states.push(currentState);
     127                    currentState = state.author;
     128                } else if (qName.equals("extensions")) {
     129                    states.push(currentState);
     130                    currentState = state.ext;
     131                }
     132                break;
     133            case trkseg:
     134                if (qName.equals("trkpt")) {
     135                    states.push(currentState);
     136                    currentState = state.wpt;
     137                    currentWayPoint = new WayPoint(parseLatLon(atts));
     138                }
     139                break;
     140            case wpt:
     141                if (qName.equals("link")) {
     142                    states.push(currentState);
     143                    currentState = state.link;
     144                    currentLink = new GpxLink(atts.getValue("href"));
     145                } else if (qName.equals("extensions")) {
     146                    states.push(currentState);
     147                    currentState = state.ext;
     148                }
     149                break;
     150            case rte:
     151                if (qName.equals("link")) {
     152                    states.push(currentState);
     153                    currentState = state.link;
     154                    currentLink = new GpxLink(atts.getValue("href"));
     155                } else if (qName.equals("rtept")) {
     156                    states.push(currentState);
     157                    currentState = state.wpt;
     158                    currentWayPoint = new WayPoint(parseLatLon(atts));
     159                } else if (qName.equals("extensions")) {
     160                    states.push(currentState);
     161                    currentState = state.ext;
     162                }
     163                break;
     164            default:
     165            }
     166            accumulator.setLength(0);
     167        }
     168
     169        @Override public void characters(char[] ch, int start, int length) {
     170            accumulator.append(ch, start, length);
     171        }
     172
     173        private Map<String, Object> getAttr() {
     174            switch (currentState) {
     175                case rte: return currentRoute.attr;
     176                case metadata: return currentData.attr;
     177                case wpt: return currentWayPoint.attr;
     178                case trk: return currentTrack.attr;
     179                default: return null;
     180            }
     181        }
     182
     183        @Override public void endElement(String namespaceURI, String qName, String rqName) {
     184            switch (currentState) {
     185            case metadata:
     186                if (qName.equals("name") || qName.equals("desc") ||
     187                        qName.equals("time") || qName.equals("keywords")) {
     188                    currentData.attr.put(qName, accumulator.toString());
     189                } else if (qName.equals("metadata")) {
     190                    currentState = states.pop();
     191                }
     192                //TODO: parse copyright, bounds, extensions
     193                break;
     194            case author:
     195                if (qName.equals("author")) {
     196                    currentState = states.pop();
     197                } else if (qName.equals("name") || qName.equals("email")) {
     198                    currentData.attr.put("author" + qName, accumulator.toString());
     199                } else if (qName.equals("link")) {
     200                    currentData.attr.put("authorlink", currentLink);
     201                }
     202                break;
     203            case link:
     204                if (qName.equals("text")) {
     205                    currentLink.text = accumulator.toString();
     206                } else if (qName.equals("type")) {
     207                    currentLink.type = accumulator.toString();
     208                } else if (qName.equals("link")) {
     209                    // <link>URL</link>
     210                    if (currentLink.uri == null)
     211                        currentLink.uri = accumulator.toString();
     212
     213                    currentState = states.pop();
     214                }
     215                if (currentState == state.author) {
     216                    currentData.attr.put("authorlink", currentLink);
     217                } else if (currentState != state.link) {
     218                    Map<String, Object> attr = getAttr();
     219                    if (!attr.containsKey("link")) {
     220                        attr.put("link", new LinkedList<GpxLink>());
     221                    }
     222                    ((Collection<GpxLink>) attr.get("link")).add(currentLink);
     223                }
     224                break;
     225            case wpt:
     226                if (qName.equals("ele") || qName.equals("magvar")
     227                        || qName.equals("geoidheight") || qName.equals("name")
     228                        || qName.equals("sym") || qName.equals("type")) {
     229                    currentWayPoint.attr.put(qName, accumulator.toString());
     230                } else if (qName.equals("time")) {
     231                    currentWayPoint.attr.put(qName, accumulator.toString());
     232                    currentWayPoint.setTime();
     233                } else if (qName.equals("cmt") || qName.equals("desc")) {
     234                    currentWayPoint.attr.put(qName, accumulator.toString());
     235                    currentWayPoint.setGarminCommentTime(qName);
     236                } else if (qName.equals("rtept")) {
     237                    currentState = states.pop();
     238                    currentRoute.routePoints.add(currentWayPoint);
     239                } else if (qName.equals("trkpt")) {
     240                    currentState = states.pop();
     241                    currentTrackSeg.add(currentWayPoint);
     242                } else if (qName.equals("wpt")) {
     243                    currentState = states.pop();
     244                    currentData.waypoints.add(currentWayPoint);
     245                }
     246                break;
     247            case trkseg:
     248                if (qName.equals("trkseg")) {
     249                    currentState = states.pop();
     250                    currentTrack.trackSegs.add(currentTrackSeg);
     251                }
     252                break;
     253            case trk:
     254                if (qName.equals("trk")) {
     255                    currentState = states.pop();
     256                    currentData.tracks.add(currentTrack);
     257                } else if (qName.equals("name") || qName.equals("cmt")
     258                        || qName.equals("desc") || qName.equals("src")
     259                        || qName.equals("type") || qName.equals("number")) {
     260                    currentTrack.attr.put(qName, accumulator.toString());
     261                }
     262                break;
     263            case ext:
     264                if (qName.equals("extensions")) {
     265                    currentState = states.pop();
     266                }
     267                break;
     268            default:
     269                if (qName.equals("wpt")) {
     270                    currentState = states.pop();
     271                } else if (qName.equals("rte")) {
     272                    currentState = states.pop();
     273                    currentData.routes.add(currentRoute);
     274                }
     275            }
     276        }
     277
     278        @Override public void endDocument() throws SAXException  {
     279            if (!states.empty()) {
     280                throw new SAXException(tr("Parse error: invalid document structure for gpx document"));
     281            }
     282            data = currentData;
     283        }
     284    }
     285
     286    /**
     287    * Parse the input stream and store the result in trackData and markerData
     288     *
     289    * @param relativeMarkerPath The directory to use as relative path for all &lt;wpt&gt;
     290    *    marker tags. Maybe <code>null</code>, in which case no relative urls are constructed for the markers.
     291    */
     292    public GpxReader(InputStream source, File relativeMarkerPath) throws SAXException, IOException {
     293
     294        Parser parser = new Parser();
     295        InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
     296        try {
     297            SAXParserFactory factory = SAXParserFactory.newInstance();
     298            factory.setNamespaceAware(true);
     299            factory.newSAXParser().parse(inputSource, parser);
     300        } catch (ParserConfigurationException e) {
     301            e.printStackTrace(); // broken SAXException chaining
     302            throw new SAXException(e);
     303        }
     304    }
    305305}
  • trunk/src/org/openstreetmap/josm/io/GpxWriter.java

    r1164 r1169  
    9797        for (WayPoint pnt : data.waypoints) {
    9898            wayPoint(pnt, WAY_POINT);
    99         }       
    100     }
    101    
     99        }
     100    }
     101
    102102    private void writeRoutes() {
    103103        for (GpxRoute rte : data.routes) {
    … …  
    110110        }
    111111    }
    112    
     112
    113113    private void writeTracks() {
    114114        for (GpxTrack trk : data.tracks) {
    … …  
    140140        indent += "  ";
    141141    }
    142    
     142
    143143    private void inline(String tag, String attributes) {
    144144        out.println(indent + "<" + tag + " " + attributes + " />");
    … …  
    155155    }
    156156
    157     /**       
     157    /**
    158158     * if content not null, open tag, write encoded content, and close tag
    159159     * else do nothing.
    … …  
    168168    }
    169169
    170     /**       
     170    /**
    171171     * output link
    172172     */
    … …  
    180180    }
    181181
    182     /**       
     182    /**
    183183     * output a point
    184184     */
  • trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java

    r999 r1169  
    2020 */
    2121public class MirroredInputStream extends InputStream {
    22         InputStream fs = null;
     22    InputStream fs = null;
    2323
    24         public MirroredInputStream(String name) throws IOException
    25         {
    26                 this(name, null, -1L);
    27         }
     24    public MirroredInputStream(String name) throws IOException
     25    {
     26        this(name, null, -1L);
     27    }
    2828
    29         public MirroredInputStream(String name, long maxTime) throws IOException
    30         {
    31                 this(name, null, maxTime);
    32         }
     29    public MirroredInputStream(String name, long maxTime) throws IOException
     30    {
     31        this(name, null, maxTime);
     32    }
    3333
    34         public MirroredInputStream(String name, String destDir, long maxTime) throws IOException
    35         {
    36                 URL url;
    37                 File file = null;
    38                 try
    39                 {
    40                         url = new URL(name);
    41                         if(url.getProtocol().equals("file"))
    42                         {
    43                                 file = new File(name.substring("file:/".length()));
    44                                 if(!file.exists())
    45                                         file = new File(name.substring("file://".length()));
    46                         }
    47                         else
    48                                 file = checkLocal(url, destDir, maxTime);
    49                 }
    50                 catch(java.net.MalformedURLException e)
    51                 {
    52                         if(name.startsWith("resource://"))
    53                         {
    54                                 fs = getClass().getResourceAsStream(
    55                                 name.substring("resource:/".length()));
    56                                 return;
    57                         }
    58                         else
    59                                 file = new File(name);
    60                 }
    61                 if(file == null)
    62                         throw new IOException();
    63                 fs = new FileInputStream(file);
    64         }
     34    public MirroredInputStream(String name, String destDir, long maxTime) throws IOException
     35    {
     36        URL url;
     37        File file = null;
     38        try
     39        {
     40            url = new URL(name);
     41            if(url.getProtocol().equals("file"))
     42            {
     43                file = new File(name.substring("file:/".length()));
     44                if(!file.exists())
     45                    file = new File(name.substring("file://".length()));
     46            }
     47            else
     48                file = checkLocal(url, destDir, maxTime);
     49        }
     50        catch(java.net.MalformedURLException e)
     51        {
     52            if(name.startsWith("resource://"))
     53            {
     54                fs = getClass().getResourceAsStream(
     55                name.substring("resource:/".length()));
     56                return;
     57            }
     58            else
     59                file = new File(name);
     60        }
     61        if(file == null)
     62            throw new IOException();
     63        fs = new FileInputStream(file);
     64    }
    6565
    66         private File checkLocal(URL url, String destDir, long maxTime)
    67         {
    68                 String localPath = Main.pref.get("mirror." + url);
    69                 File file = null;
    70                 if(localPath != null && localPath.length() > 0)
    71                 {
    72                         String[] lp = localPath.split(";");
    73                         file = new File(lp[1]);
    74                         if(maxTime <= 0)
    75                                 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                                 {
    80                                         return file;
    81                                 }
    82                         }
    83                 }
    84                 if(destDir == null)
    85                         destDir = Main.pref.getPreferencesDir();
     66    private File checkLocal(URL url, String destDir, long maxTime)
     67    {
     68        String localPath = Main.pref.get("mirror." + url);
     69        File file = null;
     70        if(localPath != null && localPath.length() > 0)
     71        {
     72            String[] lp = localPath.split(";");
     73            file = new File(lp[1]);
     74            if(maxTime <= 0)
     75                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                {
     80                    return file;
     81                }
     82            }
     83        }
     84        if(destDir == null)
     85            destDir = Main.pref.getPreferencesDir();
    8686
    87                 File destDirFile = new File(destDir);
    88                 if(!destDirFile.exists() )
    89                         destDirFile.mkdirs();
     87        File destDirFile = new File(destDir);
     88        if(!destDirFile.exists() )
     89            destDirFile.mkdirs();
    9090
    91                 localPath = "mirror_" + new File(url.getPath()).getName();
    92                 destDirFile = new File(destDir, localPath + ".tmp");
    93                 BufferedOutputStream bos = null;
    94                 BufferedInputStream bis = null;
    95                 try
    96                 {
    97                         URLConnection conn = url.openConnection();
    98                         conn.setConnectTimeout(5000);
    99                         bis = new BufferedInputStream(conn.getInputStream());
    100                         bos = new BufferedOutputStream( new FileOutputStream(destDirFile));
    101                         byte[] buffer = new byte[4096];
    102                         int length;
    103                         while((length = bis.read(buffer)) > -1)
    104                                 bos.write(buffer, 0, length);
    105                 }
    106                 catch(IOException ioe)
    107                 {
    108                         if(file != null)
    109                                 return file;
    110                         else
    111                                 return null;
    112                 }
    113                 finally
    114                 {
    115                         if(bis != null)
    116                         {
    117                                 try
    118                                 {
    119                                         bis.close();
    120                                 }
    121                                 catch (IOException e)
    122                                 {
    123                                         e.printStackTrace();
    124                                 }
    125                         }
    126                         if(bos != null)
    127                         {
    128                                 try
    129                                 {
    130                                         bos.close();
    131                                 }
    132                                 catch (IOException e)
    133                                 {
    134                                         e.printStackTrace();
    135                                 }
    136                         }
    137                         file = new File(destDir, localPath);
    138                         destDirFile.renameTo(file);
    139                         Main.pref.put("mirror." + url, System.currentTimeMillis() + ";" + file);
    140                 }
     91        localPath = "mirror_" + new File(url.getPath()).getName();
     92        destDirFile = new File(destDir, localPath + ".tmp");
     93        BufferedOutputStream bos = null;
     94        BufferedInputStream bis = null;
     95        try
     96        {
     97            URLConnection conn = url.openConnection();
     98            conn.setConnectTimeout(5000);
     99            bis = new BufferedInputStream(conn.getInputStream());
     100            bos = new BufferedOutputStream( new FileOutputStream(destDirFile));
     101            byte[] buffer = new byte[4096];
     102            int length;
     103            while((length = bis.read(buffer)) > -1)
     104                bos.write(buffer, 0, length);
     105        }
     106        catch(IOException ioe)
     107        {
     108            if(file != null)
     109                return file;
     110            else
     111                return null;
     112        }
     113        finally
     114        {
     115            if(bis != null)
     116            {
     117                try
     118                {
     119                    bis.close();
     120                }
     121                catch (IOException e)
     122                {
     123                    e.printStackTrace();
     124                }
     125            }
     126            if(bos != null)
     127            {
     128                try
     129                {
     130                    bos.close();
     131                }
     132                catch (IOException e)
     133                {
     134                    e.printStackTrace();
     135                }
     136            }
     137            file = new File(destDir, localPath);
     138            destDirFile.renameTo(file);
     139            Main.pref.put("mirror." + url, System.currentTimeMillis() + ";" + file);
     140        }
    141141
    142                 return file;
    143         }
    144         public int available() throws IOException
    145         { return fs.available(); }
    146         public void close() throws IOException
    147         { fs.close(); }
    148         public int read() throws IOException
    149         { return fs.read(); }
    150         public int read(byte[] b) throws IOException
    151         { return fs.read(b); }
    152         public int read(byte[] b, int off, int len) throws IOException
    153         { return fs.read(b,off, len); }
    154         public long skip(long n) throws IOException
    155         { return fs.skip(n); }
     142        return file;
     143    }
     144    public int available() throws IOException
     145    { return fs.available(); }
     146    public void close() throws IOException
     147    { fs.close(); }
     148    public int read() throws IOException
     149    { return fs.read(); }
     150    public int read(byte[] b) throws IOException
     151    { return fs.read(b); }
     152    public int read(byte[] b, int off, int len) throws IOException
     153    { return fs.read(b,off, len); }
     154    public long skip(long n) throws IOException
     155    { return fs.skip(n); }
    156156}
  • trunk/src/org/openstreetmap/josm/io/MultiPartFormOutputStream.java

    r627 r1169  
    33
    44License
    5                                
     5
    66Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved.
    7 Redistribution and use in source and binary forms, with or without modification, 
     7Redistribution and use in source and binary forms, with or without modification,
    88are permitted provided that the following conditions are met:
    9  
    10     * Redistribution of source code must retain the above copyright notice, this list 
     9
     10    * Redistribution of source code must retain the above copyright notice, this list
    1111      of conditions and the following disclaimer.
    1212
    13     * Redistribution in binary form must reproduce the above copyright notice, this 
    14       list of conditions and the following disclaimer in the documentation and/or other 
     13    * Redistribution in binary form must reproduce the above copyright notice, this
     14      list of conditions and the following disclaimer in the documentation and/or other
    1515      materials provided with the distribution.
    1616
    17  
    18 Neither the name of Sun Microsystems, Inc. or the names of contributors may be used to 
    19 endorse or promote products derived from this software without specific prior written 
     17
     18Neither the name of Sun Microsystems, Inc. or the names of contributors may be used to
     19endorse or promote products derived from this software without specific prior written
    2020permission.
    21  
    22 This software is provided "AS IS," without a warranty of any kind. ALL EXPRESS OR IMPLIED 
    23 CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
    24 FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, 
    25 INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS 
    26 A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT 
    27 WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, 
    28 INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 
    29 REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS 
     21
     22This software is provided "AS IS," without a warranty of any kind. ALL EXPRESS OR IMPLIED
     23CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
     24FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS,
     25INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS
     26A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT
     27WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
     28INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
     29REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS
    3030SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    31  
    32 You acknowledge that this software is not designed, licensed or intended for use in the 
    33 design, construction, operation or maintenance of any nuclear facility. 
     31
     32You acknowledge that this software is not designed, licensed or intended for use in the
     33design, construction, operation or maintenance of any nuclear facility.
    3434*/
    3535
    … …  
    4444import java.net.URLConnection;
    4545
    46          
     46
    4747/**
    48  * <code>MultiPartFormOutputStream</code> is used to write 
    49  * "multipart/form-data" to a <code>java.net.URLConnection</code> for 
    50  * POSTing.  This is primarily for file uploading to HTTP servers. 
    51  * 
     48 * <code>MultiPartFormOutputStream</code> is used to write
     49 * "multipart/form-data" to a <code>java.net.URLConnection</code> for
     50 * POSTing.  This is primarily for file uploading to HTTP servers.
     51 *
    5252 * @since  JDK1.3
    5353 */
    5454public class MultiPartFormOutputStream extends OsmConnection {
    55         /**
    56         * The line end characters. 
    57         */
    58         private static final String NEWLINE = "\r\n";
    59 
    60         /**
    61         * The boundary prefix. 
    62         */
    63         private static final String PREFIX = "--";
    64 
    65         /**
    66         * The output stream to write to. 
    67         */
    68         private DataOutputStream out = null;
    69 
    70         /**
    71         * The multipart boundary string. 
    72         */
    73         private String boundary = null;
    74 
    75         /**
    76         * Creates a new <code>MultiPartFormOutputStream</code> object using 
    77         * the specified output stream and boundary.  The boundary is required 
    78         * to be created before using this method, as described in the 
    79         * description for the <code>getContentType(String)</code> method. 
    80         * The boundary is only checked for <code>null</code> or empty string, 
    81         * but it is recommended to be at least 6 characters.  (Or use the 
    82         * static createBoundary() method to create one.)
    83          *
    84         * @param  os        the output stream
    85         * @param  boundary  the boundary
    86         * @see  #createBoundary()
    87         * @see  #getContentType(String)
    88         */
    89         public MultiPartFormOutputStream(OutputStream os, String boundary) {
    90                 if(os == null) {
    91                         throw new IllegalArgumentException("Output stream is required.");
    92                 }
    93                 if(boundary == null || boundary.length() == 0) {
    94                         throw new IllegalArgumentException("Boundary stream is required.");
    95                 }
    96                 this.out = new DataOutputStream(os);
    97                 this.boundary = boundary;
    98                 initAuthentication();
    99         }
    100 
    101         /**
    102         * Writes an boolean field value. 
    103          *
    104         * @param  name   the field name (required)
    105         * @param  value  the field value
    106         * @throws  java.io.IOException  on input/output errors
    107         */
    108         public void writeField(String name, boolean value) 
    109         throws java.io.IOException {
    110                 writeField(name, new Boolean(value).toString());
    111         }
    112 
    113         /**
    114         * Writes an double field value. 
    115          *
    116         * @param  name   the field name (required)
    117         * @param  value  the field value
    118         * @throws  java.io.IOException  on input/output errors
    119         */
    120         public void writeField(String name, double value) 
    121         throws java.io.IOException {
    122                 writeField(name, Double.toString(value));
    123         }
    124 
    125         /**
    126         * Writes an float field value. 
    127          *
    128         * @param  name   the field name (required)
    129         * @param  value  the field value
    130         * @throws  java.io.IOException  on input/output errors
    131         */
    132         public void writeField(String name, float value) 
    133         throws java.io.IOException {
    134                 writeField(name, Float.toString(value));
    135         }
    136 
    137         /**
    138         * Writes an long field value. 
    139          *
    140         * @param  name   the field name (required)
    141         * @param  value  the field value
    142         * @throws  java.io.IOException  on input/output errors
    143         */
    144         public void writeField(String name, long value) 
    145         throws java.io.IOException {
    146                 writeField(name, Long.toString(value));
    147         }
    148 
    149         /**
    150         * Writes an int field value. 
    151          *
    152         * @param  name   the field name (required)
    153         * @param  value  the field value
    154         * @throws  java.io.IOException  on input/output errors
    155         */
    156         public void writeField(String name, int value) 
    157         throws java.io.IOException {
    158                 writeField(name, Integer.toString(value));
    159         }
    160 
    161         /**
    162         * Writes an short field value. 
    163          *
    164         * @param  name   the field name (required)
    165         * @param  value  the field value
    166         * @throws  java.io.IOException  on input/output errors
    167         */
    168         public void writeField(String name, short value) 
    169         throws java.io.IOException {
    170                 writeField(name, Short.toString(value));
    171         }
    172 
    173         /**
    174         * Writes an char field value. 
    175          *
    176         * @param  name   the field name (required)
    177         * @param  value  the field value
    178         * @throws  java.io.IOException  on input/output errors
    179         */
    180         public void writeField(String name, char value) 
    181         throws java.io.IOException {
    182                 writeField(name, new Character(value).toString());
    183         }
    184 
    185         /**
    186         * Writes an string field value.  If the value is null, an empty string 
    187         * is sent (""). 
    188          *
    189         * @param  name   the field name (required)
    190         * @param  value  the field value
    191         * @throws  java.io.IOException  on input/output errors
    192         */
    193         public void writeField(String name, String value) 
    194         throws java.io.IOException {
    195                 if(name == null) {
    196                         throw new IllegalArgumentException("Name cannot be null or empty.");
    197                 }
    198                 if(value == null) {
    199                         value = "";
    200                 }
    201                 /*
    202                         --boundary\r\n
    203                         Content-Disposition: form-data; name="<fieldName>"\r\n
    204                         \r\n
    205                         <value>\r\n
    206                 */
    207                 // write boundary
    208                 out.writeBytes(PREFIX);
    209                 out.writeBytes(boundary);
    210                 out.writeBytes(NEWLINE);
    211                 // write content header
    212                 out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"");
    213                 out.writeBytes(NEWLINE);
    214                 out.writeBytes(NEWLINE);
    215                 // write content
    216                 out.writeBytes(value);
    217                 out.writeBytes(NEWLINE);
    218                 out.flush();
    219         }
    220 
    221         /**
    222         * Writes a file's contents.  If the file is null, does not exists, or 
    223         * is a directory, a <code>java.lang.IllegalArgumentException</code> 
    224         * will be thrown. 
    225          *
    226         * @param  name      the field name
    227         * @param  mimeType  the file content type (optional, recommended)
    228         * @param  file      the file (the file must exist)
    229         * @throws  java.io.IOException  on input/output errors
    230         */
    231         public void writeFile(String name, String mimeType, java.io.File file) 
    232         throws java.io.IOException {
    233                 if(file == null) {
    234                         throw new IllegalArgumentException("File cannot be null.");
    235                 }
    236                 if(!file.exists()) {
    237                         throw new IllegalArgumentException("File does not exist.");
    238                 }
    239                 if(file.isDirectory()) {
    240                         throw new IllegalArgumentException("File cannot be a directory.");
    241                 }
    242                 writeFile(name, mimeType, file.getCanonicalPath(), new FileInputStream(file));
    243         }
    244 
    245         /**
    246         * Writes a input stream's contents.  If the input stream is null, a 
    247         * <code>java.lang.IllegalArgumentException</code> will be thrown. 
    248          *
    249         * @param  name      the field name
    250         * @param  mimeType  the file content type (optional, recommended)
    251         * @param  fileName  the file name (required)
    252         * @param  is        the input stream
    253         * @throws  java.io.IOException  on input/output errors
    254         */
    255         public void writeFile(String name, String mimeType, 
    256                         String fileName, InputStream is) 
    257         throws java.io.IOException {
    258                 if(is == null) {
    259                         throw new IllegalArgumentException("Input stream cannot be null.");
    260                 }
    261                 if(fileName == null || fileName.length() == 0) {
    262                         throw new IllegalArgumentException("File name cannot be null or empty.");
    263                 }
    264                 /*
    265                         --boundary\r\n
    266                         Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
    267                         Content-Type: <mime-type>\r\n
    268                         \r\n
    269                         <file-data>\r\n
    270                 */
    271                 // write boundary
    272                 out.writeBytes(PREFIX);
    273                 out.writeBytes(boundary);
    274                 out.writeBytes(NEWLINE);
    275                 // write content header
    276                 out.writeBytes("Content-Disposition: form-data; name=\"" + name + 
    277                                 "\"; filename=\"" + fileName + "\"");
    278                 out.writeBytes(NEWLINE);
    279                 if(mimeType != null) {
    280                         out.writeBytes("Content-Type: " + mimeType);
    281                         out.writeBytes(NEWLINE);
    282                 }
    283                 out.writeBytes(NEWLINE);
    284                 // write content
    285                 byte[] data = new byte[1024];
    286                 int r = 0;
    287                 while((r = is.read(data, 0, data.length)) != -1) {
    288                         out.write(data, 0, r);
    289                 }
    290                 // close input stream, but ignore any possible exception for it
    291                 try {
    292                         is.close();
    293                 } catch(Exception e) {}
    294                 out.writeBytes(NEWLINE);
    295                 out.flush();
    296         }
    297 
    298         /**
    299         * Writes the given bytes.  The bytes are assumed to be the contents 
    300         * of a file, and will be sent as such.  If the data is null, a 
    301         * <code>java.lang.IllegalArgumentException</code> will be thrown. 
    302          *
    303         * @param  name      the field name
    304         * @param  mimeType  the file content type (optional, recommended)
    305         * @param  fileName  the file name (required)
    306         * @param  data      the file data
    307         * @throws  java.io.IOException  on input/output errors
    308         */
    309         public void writeFile(String name, String mimeType, 
    310                         String fileName, byte[] data) 
    311         throws java.io.IOException {
    312                 if(data == null) {
    313                         throw new IllegalArgumentException("Data cannot be null.");
    314                 }
    315                 if(fileName == null || fileName.length() == 0) {
    316                         throw new IllegalArgumentException("File name cannot be null or empty.");
    317                 }
    318                 /*
    319                         --boundary\r\n
    320                         Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
    321                         Content-Type: <mime-type>\r\n
    322                         \r\n
    323                         <file-data>\r\n
    324                 */
    325                 // write boundary
    326                 out.writeBytes(PREFIX);
    327                 out.writeBytes(boundary);
    328                 out.writeBytes(NEWLINE);
    329                 // write content header
    330                 out.writeBytes("Content-Disposition: form-data; name=\"" + name + 
    331                                 "\"; filename=\"" + fileName + "\"");
    332                 out.writeBytes(NEWLINE);
    333                 if(mimeType != null) {
    334                         out.writeBytes("Content-Type: " + mimeType);
    335                         out.writeBytes(NEWLINE);
    336                 }
    337                 out.writeBytes(NEWLINE);
    338                 // write content
    339                 out.write(data, 0, data.length);
    340                 out.writeBytes(NEWLINE);
    341                 out.flush();
    342         }
    343 
    344         /**
    345         * Flushes the stream.  Actually, this method does nothing, as the only 
    346         * write methods are highly specialized and automatically flush. 
    347         */
    348         public void flush() {
    349                 // out.flush();
    350         }
    351 
    352         /**
    353         * Closes the stream.  <br/>
    354         * <br/>
    355         * <b>NOTE:</b> This method <b>MUST</b> be called to finalize the 
    356         * multipart stream.
    357          *
    358         * @throws  java.io.IOException  on input/output errors
    359         */
    360         public void close() throws java.io.IOException {
    361                 // write final boundary
    362                 out.writeBytes(PREFIX);
    363                 out.writeBytes(boundary);
    364                 out.writeBytes(PREFIX);
    365                 out.writeBytes(NEWLINE);
    366                 out.flush();
    367                 out.close();
    368         }
    369 
    370         /**
    371         * Gets the multipart boundary string being used by this stream. 
    372          *
    373         * @return  the boundary
    374         */
    375         public String getBoundary() {
    376                 return this.boundary;
    377         }
    378 
    379         /**
    380         * Creates a new <code>java.net.URLConnection</code> object from the 
    381         * specified <code>java.net.URL</code>.  This is a convenience method 
    382         * which will set the <code>doInput</code>, <code>doOutput</code>, 
    383         * <code>useCaches</code> and <code>defaultUseCaches</code> fields to 
    384         * the appropriate settings in the correct order. 
    385          *
    386         * @return  a <code>java.net.URLConnection</code> object for the URL
    387         * @throws  java.io.IOException  on input/output errors
    388         */
    389         public static URLConnection createConnection(URL url) 
    390         throws java.io.IOException {
    391                 URLConnection urlConn = url.openConnection();
    392                 if(urlConn instanceof HttpURLConnection) {
    393                         HttpURLConnection httpConn = (HttpURLConnection)urlConn;
    394                         httpConn.setRequestMethod("POST");
    395                 }
    396                 urlConn.setDoInput(true);
    397                 urlConn.setDoOutput(true);
    398                 urlConn.setUseCaches(false);
    399                 urlConn.setDefaultUseCaches(false);
    400                 return urlConn;
    401         }
    402 
    403         /**
    404         * Creates a multipart boundary string by concatenating 20 hyphens (-) 
    405         * and the hexadecimal (base-16) representation of the current time in 
    406         * milliseconds. 
    407          *
    408         * @return  a multipart boundary string
    409         * @see  #getContentType(String)
    410         */
    411         public static String createBoundary() {
    412                 return "--------------------" + 
    413                 Long.toString(System.currentTimeMillis(), 16);
    414         }
    415 
    416         /**
    417         * Gets the content type string suitable for the 
    418         * <code>java.net.URLConnection</code> which includes the multipart 
    419         * boundary string.  <br/>
    420         * <br/>
    421         * This method is static because, due to the nature of the 
    422         * <code>java.net.URLConnection</code> class, once the output stream 
    423         * for the connection is acquired, it's too late to set the content 
    424         * type (or any other request parameter).  So one has to create a 
    425         * multipart boundary string first before using this class, such as 
    426         * with the <code>createBoundary()</code> method. 
    427          *
    428         * @param  boundary  the boundary string
    429         * @return  the content type string
    430         * @see  #createBoundary()
    431         */
    432         public static String getContentType(String boundary) {
    433                 return "multipart/form-data; boundary=" + boundary;
    434         }
     55    /**
     56    * The line end characters.
     57    */
     58    private static final String NEWLINE = "\r\n";
     59
     60    /**
     61    * The boundary prefix.
     62    */
     63    private static final String PREFIX = "--";
     64
     65    /**
     66    * The output stream to write to.
     67    */
     68    private DataOutputStream out = null;
     69
     70    /**
     71    * The multipart boundary string.
     72    */
     73    private String boundary = null;
     74
     75    /**
     76    * Creates a new <code>MultiPartFormOutputStream</code> object using
     77    * the specified output stream and boundary.  The boundary is required
     78    * to be created before using this method, as described in the
     79    * description for the <code>getContentType(String)</code> method.
     80    * The boundary is only checked for <code>null</code> or empty string,
     81    * but it is recommended to be at least 6 characters.  (Or use the
     82    * static createBoundary() method to create one.)
     83     *
     84    * @param  os        the output stream
     85    * @param  boundary  the boundary
     86    * @see  #createBoundary()
     87    * @see  #getContentType(String)
     88    */
     89    public MultiPartFormOutputStream(OutputStream os, String boundary) {
     90        if(os == null) {
     91            throw new IllegalArgumentException("Output stream is required.");
     92        }
     93        if(boundary == null || boundary.length() == 0) {
     94            throw new IllegalArgumentException("Boundary stream is required.");
     95        }
     96        this.out = new DataOutputStream(os);
     97        this.boundary = boundary;
     98        initAuthentication();
     99    }
     100
     101    /**
     102    * Writes an boolean field value.
     103     *
     104    * @param  name   the field name (required)
     105    * @param  value  the field value
     106    * @throws  java.io.IOException  on input/output errors
     107    */
     108    public void writeField(String name, boolean value)
     109    throws java.io.IOException {
     110        writeField(name, new Boolean(value).toString());
     111    }
     112
     113    /**
     114    * Writes an double field value.
     115     *
     116    * @param  name   the field name (required)
     117    * @param  value  the field value
     118    * @throws  java.io.IOException  on input/output errors
     119    */
     120    public void writeField(String name, double value)
     121    throws java.io.IOException {
     122        writeField(name, Double.toString(value));
     123    }
     124
     125    /**
     126    * Writes an float field value.
     127     *
     128    * @param  name   the field name (required)
     129    * @param  value  the field value
     130    * @throws  java.io.IOException  on input/output errors
     131    */
     132    public void writeField(String name, float value)
     133    throws java.io.IOException {
     134        writeField(name, Float.toString(value));
     135    }
     136
     137    /**
     138    * Writes an long field value.
     139     *
     140    * @param  name   the field name (required)
     141    * @param  value  the field value
     142    * @throws  java.io.IOException  on input/output errors
     143    */
     144    public void writeField(String name, long value)
     145    throws java.io.IOException {
     146        writeField(name, Long.toString(value));
     147    }
     148
     149    /**
     150    * Writes an int field value.
     151     *
     152    * @param  name   the field name (required)
     153    * @param  value  the field value
     154    * @throws  java.io.IOException  on input/output errors
     155    */
     156    public void writeField(String name, int value)
     157    throws java.io.IOException {
     158        writeField(name, Integer.toString(value));
     159    }
     160
     161    /**
     162    * Writes an short field value.
     163     *
     164    * @param  name   the field name (required)
     165    * @param  value  the field value
     166    * @throws  java.io.IOException  on input/output errors
     167    */
     168    public void writeField(String name, short value)
     169    throws java.io.IOException {
     170        writeField(name, Short.toString(value));
     171    }
     172
     173    /**
     174    * Writes an char field value.
     175     *
     176    * @param  name   the field name (required)
     177    * @param  value  the field value
     178    * @throws  java.io.IOException  on input/output errors
     179    */
     180    public void writeField(String name, char value)
     181    throws java.io.IOException {
     182        writeField(name, new Character(value).toString());
     183    }
     184
     185    /**
     186    * Writes an string field value.  If the value is null, an empty string
     187    * is sent ("").
     188     *
     189    * @param  name   the field name (required)
     190    * @param  value  the field value
     191    * @throws  java.io.IOException  on input/output errors
     192    */
     193    public void writeField(String name, String value)
     194    throws java.io.IOException {
     195        if(name == null) {
     196            throw new IllegalArgumentException("Name cannot be null or empty.");
     197        }
     198        if(value == null) {
     199            value = "";
     200        }
     201        /*
     202            --boundary\r\n
     203            Content-Disposition: form-data; name="<fieldName>"\r\n
     204            \r\n
     205            <value>\r\n
     206        */
     207        // write boundary
     208        out.writeBytes(PREFIX);
     209        out.writeBytes(boundary);
     210        out.writeBytes(NEWLINE);
     211        // write content header
     212        out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"");
     213        out.writeBytes(NEWLINE);
     214        out.writeBytes(NEWLINE);
     215        // write content
     216        out.writeBytes(value);
     217        out.writeBytes(NEWLINE);
     218        out.flush();
     219    }
     220
     221    /**
     222    * Writes a file's contents.  If the file is null, does not exists, or
     223    * is a directory, a <code>java.lang.IllegalArgumentException</code>
     224    * will be thrown.
     225     *
     226    * @param  name      the field name
     227    * @param  mimeType  the file content type (optional, recommended)
     228    * @param  file      the file (the file must exist)
     229    * @throws  java.io.IOException  on input/output errors
     230    */
     231    public void writeFile(String name, String mimeType, java.io.File file)
     232    throws java.io.IOException {
     233        if(file == null) {
     234            throw new IllegalArgumentException("File cannot be null.");
     235        }
     236        if(!file.exists()) {
     237            throw new IllegalArgumentException("File does not exist.");
     238        }
     239        if(file.isDirectory()) {
     240            throw new IllegalArgumentException("File cannot be a directory.");
     241        }
     242        writeFile(name, mimeType, file.getCanonicalPath(), new FileInputStream(file));
     243    }
     244
     245    /**
     246    * Writes a input stream's contents.  If the input stream is null, a
     247    * <code>java.lang.IllegalArgumentException</code> will be thrown.
     248     *
     249    * @param  name      the field name
     250    * @param  mimeType  the file content type (optional, recommended)
     251    * @param  fileName  the file name (required)
     252    * @param  is        the input stream
     253    * @throws  java.io.IOException  on input/output errors
     254    */
     255    public void writeFile(String name, String mimeType,
     256            String fileName, InputStream is)
     257    throws java.io.IOException {
     258        if(is == null) {
     259            throw new IllegalArgumentException("Input stream cannot be null.");
     260        }
     261        if(fileName == null || fileName.length() == 0) {
     262            throw new IllegalArgumentException("File name cannot be null or empty.");
     263        }
     264        /*
     265            --boundary\r\n
     266            Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
     267            Content-Type: <mime-type>\r\n
     268            \r\n
     269            <file-data>\r\n
     270        */
     271        // write boundary
     272        out.writeBytes(PREFIX);
     273        out.writeBytes(boundary);
     274        out.writeBytes(NEWLINE);
     275        // write content header
     276        out.writeBytes("Content-Disposition: form-data; name=\"" + name +
     277                "\"; filename=\"" + fileName + "\"");
     278        out.writeBytes(NEWLINE);
     279        if(mimeType != null) {
     280            out.writeBytes("Content-Type: " + mimeType);
     281            out.writeBytes(NEWLINE);
     282        }
     283        out.writeBytes(NEWLINE);
     284        // write content
     285        byte[] data = new byte[1024];
     286        int r = 0;
     287        while((r = is.read(data, 0, data.length)) != -1) {
     288            out.write(data, 0, r);
     289        }
     290        // close input stream, but ignore any possible exception for it
     291        try {
     292            is.close();
     293        } catch(Exception e) {}
     294        out.writeBytes(NEWLINE);
     295        out.flush();
     296    }
     297
     298    /**
     299    * Writes the given bytes.  The bytes are assumed to be the contents
     300    * of a file, and will be sent as such.  If the data is null, a
     301    * <code>java.lang.IllegalArgumentException</code> will be thrown.
     302     *
     303    * @param  name      the field name
     304    * @param  mimeType  the file content type (optional, recommended)
     305    * @param  fileName  the file name (required)
     306    * @param  data      the file data
     307    * @throws  java.io.IOException  on input/output errors
     308    */
     309    public void writeFile(String name, String mimeType,
     310            String fileName, byte[] data)
     311    throws java.io.IOException {
     312        if(data == null) {
     313            throw new IllegalArgumentException("Data cannot be null.");
     314        }
     315        if(fileName == null || fileName.length() == 0) {
     316            throw new IllegalArgumentException("File name cannot be null or empty.");
     317        }
     318        /*
     319            --boundary\r\n
     320            Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
     321            Content-Type: <mime-type>\r\n
     322            \r\n
     323            <file-data>\r\n
     324        */
     325        // write boundary
     326        out.writeBytes(PREFIX);
     327        out.writeBytes(boundary);
     328        out.writeBytes(NEWLINE);
     329        // write content header
     330        out.writeBytes("Content-Disposition: form-data; name=\"" + name +
     331                "\"; filename=\"" + fileName + "\"");
     332        out.writeBytes(NEWLINE);
     333        if(mimeType != null) {
     334            out.writeBytes("Content-Type: " + mimeType);
     335            out.writeBytes(NEWLINE);
     336        }
     337        out.writeBytes(NEWLINE);
     338        // write content
     339        out.write(data, 0, data.length);
     340        out.writeBytes(NEWLINE);
     341        out.flush();
     342    }
     343
     344    /**
     345    * Flushes the stream.  Actually, this method does nothing, as the only
     346    * write methods are highly specialized and automatically flush.
     347    */
     348    public void flush() {
     349        // out.flush();
     350    }
     351
     352    /**
     353    * Closes the stream.  <br/>
     354    * <br/>
     355    * <b>NOTE:</b> This method <b>MUST</b> be called to finalize the
     356    * multipart stream.
     357     *
     358    * @throws  java.io.IOException  on input/output errors
     359    */
     360    public void close() throws java.io.IOException {
     361        // write final boundary
     362        out.writeBytes(PREFIX);
     363        out.writeBytes(boundary);
     364        out.writeBytes(PREFIX);
     365        out.writeBytes(NEWLINE);
     366        out.flush();
     367        out.close();
     368    }
     369
     370    /**
     371    * Gets the multipart boundary string being used by this stream.
     372     *
     373    * @return  the boundary
     374    */
     375    public String getBoundary() {
     376        return this.boundary;
     377    }
     378
     379    /**
     380    * Creates a new <code>java.net.URLConnection</code> object from the
     381    * specified <code>java.net.URL</code>.  This is a convenience method
     382    * which will set the <code>doInput</code>, <code>doOutput</code>,
     383    * <code>useCaches</code> and <code>defaultUseCaches</code> fields to
     384    * the appropriate settings in the correct order.
     385     *
     386    * @return  a <code>java.net.URLConnection</code> object for the URL
     387    * @throws  java.io.IOException  on input/output errors
     388    */
     389    public static URLConnection createConnection(URL url)
     390    throws java.io.IOException {
     391        URLConnection urlConn = url.openConnection();
     392        if(urlConn instanceof HttpURLConnection) {
     393            HttpURLConnection httpConn = (HttpURLConnection)urlConn;
     394            httpConn.setRequestMethod("POST");
     395        }
     396        urlConn.setDoInput(true);
     397        urlConn.setDoOutput(true);
     398        urlConn.setUseCaches(false);
     399        urlConn.setDefaultUseCaches(false);
     400        return urlConn;
     401    }
     402
     403    /**
     404    * Creates a multipart boundary string by concatenating 20 hyphens (-)
     405    * and the hexadecimal (base-16) representation of the current time in
     406    * milliseconds.
     407     *
     408    * @return  a multipart boundary string
     409    * @see  #getContentType(String)
     410    */
     411    public static String createBoundary() {
     412        return "--------------------" +
     413        Long.toString(System.currentTimeMillis(), 16);
     414    }
     415
     416    /**
     417    * Gets the content type string suitable for the
     418    * <code>java.net.URLConnection</code> which includes the multipart
     419    * boundary string.  <br/>
     420    * <br/>
     421    * This method is static because, due to the nature of the
     422    * <code>java.net.URLConnection</code> class, once the output stream
     423    * for the connection is acquired, it's too late to set the content
     424    * type (or any other request parameter).  So one has to create a
     425    * multipart boundary string first before using this class, such as
     426    * with the <code>createBoundary()</code> method.
     427     *
     428    * @param  boundary  the boundary string
     429    * @return  the content type string
     430    * @see  #createBoundary()
     431    */
     432    public static String getContentType(String boundary) {
     433        return "multipart/form-data; boundary=" + boundary;
     434    }
    435435}
  • trunk/src/org/openstreetmap/josm/io/MyHttpHandler.java

    r655 r1169  
    2626                proxyPort = port;
    2727            }
    28  
     28
    2929            protected java.net.URLConnection openConnection(URL u, Proxy p)
    3030                    throws IOException {
  • trunk/src/org/openstreetmap/josm/io/NmeaReader.java

    r1167 r1169  
    2828public class NmeaReader {
    2929
    30         /** Handler for the different types that NMEA speaks. */
    31         public static enum NMEA_TYPE {
    32 
    33                 /** RMC = recommended minimum sentence C. */
    34                 GPRMC("$GPRMC"),
    35                 /** GPS positions. */
    36                 GPGGA("$GPGGA"),
    37                 /** SA = satellites active. */
    38                 GPGSA("$GPGSA"),
    39                 /** Course over ground and ground speed */
    40                 GPVTG("$GPVTG");
    41 
    42                 private final String type;
    43 
    44                 NMEA_TYPE(String type) {
    45                         this.type = type;
    46                 }
    47 
    48                 public String getType() {
    49                         return this.type;
    50                 }
    51 
    52                 public boolean equals(String type) {
    53                         return this.type.equals(type);
    54                 }
    55         }
    56 
    57         // GPVTG
    58         public static enum GPVTG {
    59                 COURSE(1),COURSE_REF(2), // true course
    60                 COURSE_M(3), COURSE_M_REF(4), // magnetic course
    61                 SPEED_KN(5), SPEED_KN_UNIT(6), // speed in knots
    62                 SPEED_KMH(7), SPEED_KMH_UNIT(8), // speed in km/h
    63                 REST(9); // version-specific rest
    64 
    65                 public final int position;
    66 
    67                 GPVTG(int position) {
    68                         this.position = position;
    69                 }
    70         }
    71 
    72         // The following only applies to GPRMC
    73         public static enum GPRMC {
    74                 TIME(1),
    75                 /** Warning from the receiver (A = data ok, V = warning) */
    76                 RECEIVER_WARNING(2),
    77                 WIDTH_NORTH(3), WIDTH_NORTH_NAME(4), // Latitude, NS
    78                 LENGTH_EAST(5), LENGTH_EAST_NAME(6), // Longitude, EW
    79                 SPEED(7), COURSE(8), DATE(9),           // Speed in knots
    80                 MAGNETIC_DECLINATION(10), UNKNOWN(11),  // magnetic declination
    81                 /**
    82                 * Mode (A = autonom; D = differential; E = estimated; N = not valid; S
    83                 * = simulated)
    84                 *
    85                 * @since NMEA 2.3
    86                 */
    87                 MODE(12);
    88 
    89                 public final int position;
    90 
    91                 GPRMC(int position) {
    92                         this.position = position;
    93                 }
    94         }
    95 
    96         // The following only applies to GPGGA
    97         public static enum GPGGA {
    98                 TIME(1), LATITUDE(2), LATITUDE_NAME(3), LONGITUDE(4), LONGITUDE_NAME(5),
    99                 /**
    100                 * Quality (0 = invalid, 1 = GPS, 2 = DGPS, 6 = estimanted (@since NMEA
    101                 * 2.3))
    102                 */
    103                 QUALITY(6), SATELLITE_COUNT(7),
    104                 HDOP(8), // HDOP (horizontal dilution of precision)
    105                 HEIGHT(9), HEIGHT_UNTIS(10), // height above NN (above geoid)
    106                 HEIGHT_2(11), HEIGHT_2_UNTIS(12), // height geoid - height ellipsoid (WGS84)
    107                 GPS_AGE(13),// Age of differential GPS data
    108                 REF(14); // REF station
    109 
    110                 public final int position;
    111                 GPGGA(int position) {
    112                         this.position = position;
    113                 }
    114         }
    115 
    116         public static enum GPGSA {
    117                 AUTOMATIC(1),
    118                 FIX_TYPE(2), // 1 = not fixed, 2 = 2D fixed, 3 = 3D fixed)
    119                 // PRN numbers for max 12 satellites
    120                 PRN_1(3), PRN_2(4), PRN_3(5), PRN_4(6), PRN_5(7), PRN_6(8),
    121                 PRN_7(9), PRN_8(10), PRN_9(11), PRN_10(12), PRN_11(13), PRN_12(14),
    122                 PDOP(15),   // PDOP (precision)
    123                 HDOP(16),   // HDOP (horizontal precision)
    124                 VDOP(17), ; // VDOP (vertical precision)
    125 
    126                 public final int position;
    127                 GPGSA(int position) {
    128                         this.position = position;
    129                 }
    130         }
    131 
    132         public GpxData data;
     30    /** Handler for the different types that NMEA speaks. */
     31    public static enum NMEA_TYPE {
     32
     33        /** RMC = recommended minimum sentence C. */
     34        GPRMC("$GPRMC"),
     35        /** GPS positions. */
     36        GPGGA("$GPGGA"),
     37        /** SA = satellites active. */
     38        GPGSA("$GPGSA"),
     39        /** Course over ground and ground speed */
     40        GPVTG("$GPVTG");
     41
     42        private final String type;
     43
     44        NMEA_TYPE(String type) {
     45            this.type = type;
     46        }
     47
     48        public String getType() {
     49            return this.type;
     50        }
     51
     52        public boolean equals(String type) {
     53            return this.type.equals(type);
     54        }
     55    }
     56
     57    // GPVTG
     58    public static enum GPVTG {
     59        COURSE(1),COURSE_REF(2), // true course
     60        COURSE_M(3), COURSE_M_REF(4), // magnetic course
     61        SPEED_KN(5), SPEED_KN_UNIT(6), // speed in knots
     62        SPEED_KMH(7), SPEED_KMH_UNIT(8), // speed in km/h
     63        REST(9); // version-specific rest
     64
     65        public final int position;
     66
     67        GPVTG(int position) {
     68            this.position = position;
     69        }
     70    }
     71
     72    // The following only applies to GPRMC
     73    public static enum GPRMC {
     74        TIME(1),
     75        /** Warning from the receiver (A = data ok, V = warning) */
     76        RECEIVER_WARNING(2),
     77        WIDTH_NORTH(3), WIDTH_NORTH_NAME(4), // Latitude, NS
     78        LENGTH_EAST(5), LENGTH_EAST_NAME(6), // Longitude, EW
     79        SPEED(7), COURSE(8), DATE(9),           // Speed in knots
     80        MAGNETIC_DECLINATION(10), UNKNOWN(11),  // magnetic declination
     81        /**
     82        * Mode (A = autonom; D = differential; E = estimated; N = not valid; S
     83        * = simulated)
     84        *
     85        * @since NMEA 2.3
     86        */
     87        MODE(12);
     88
     89        public final int position;
     90
     91        GPRMC(int position) {
     92            this.position = position;
     93        }
     94    }
     95
     96    // The following only applies to GPGGA
     97    public static enum GPGGA {
     98        TIME(1), LATITUDE(2), LATITUDE_NAME(3), LONGITUDE(4), LONGITUDE_NAME(5),
     99        /**
     100        * Quality (0 = invalid, 1 = GPS, 2 = DGPS, 6 = estimanted (@since NMEA
     101        * 2.3))
     102        */
     103        QUALITY(6), SATELLITE_COUNT(7),
     104        HDOP(8), // HDOP (horizontal dilution of precision)
     105        HEIGHT(9), HEIGHT_UNTIS(10), // height above NN (above geoid)
     106        HEIGHT_2(11), HEIGHT_2_UNTIS(12), // height geoid - height ellipsoid (WGS84)
     107        GPS_AGE(13),// Age of differential GPS data
     108        REF(14); // REF station
     109
     110        public final int position;
     111        GPGGA(int position) {
     112            this.position = position;
     113        }
     114    }
     115
     116    public static enum GPGSA {
     117        AUTOMATIC(1),
     118        FIX_TYPE(2), // 1 = not fixed, 2 = 2D fixed, 3 = 3D fixed)
     119        // PRN numbers for max 12 satellites
     120        PRN_1(3), PRN_2(4), PRN_3(5), PRN_4(6), PRN_5(7), PRN_6(8),
     121        PRN_7(9), PRN_8(10), PRN_9(11), PRN_10(12), PRN_11(13), PRN_12(14),
     122        PDOP(15),   // PDOP (precision)
     123        HDOP(16),   // HDOP (horizontal precision)
     124        VDOP(17), ; // VDOP (vertical precision)
     125
     126        public final int position;
     127        GPGSA(int position) {
     128            this.position = position;
     129        }
     130    }
     131
     132    public GpxData data;
    133133
    134134//  private final static SimpleDateFormat GGATIMEFMT =
    135135//      new SimpleDateFormat("HHmmss.SSS");
    136         private final static SimpleDateFormat RMCTIMEFMT =
    137                 new SimpleDateFormat("ddMMyyHHmmss.SSS");
    138 
    139         // functons for reading the error stats
    140         public NMEAParserState ps;
    141 
    142         public int getParserUnknown() {
    143                 return ps.unknown;
    144         }
    145         public int getParserZeroCoordinates() {
    146                 return ps.zero_coord;
    147         }
    148         public int getParserChecksumErrors() {
    149                 return ps.checksum_errors;
    150         }
    151         public int getParserMalformed() {
    152                 return ps.malformed;
    153         }
    154         public int getNumberOfCoordinates() {
    155                 return ps.success;
    156         }
    157 
    158         public NmeaReader(InputStream source, File relativeMarkerPath) {
    159 
    160                 // create the data tree
    161                 data = new GpxData();
    162                 GpxTrack currentTrack = new GpxTrack();
    163                 data.tracks.add(currentTrack);
    164 
    165                 try {
    166                         BufferedReader rd =
    167                                 new BufferedReader(new InputStreamReader(source));
    168 
    169                         StringBuffer sb = new StringBuffer(1024);
    170                         int loopstart_char = rd.read();
    171                         if(loopstart_char == -1) {// zero size file
    172                                 //TODO tell user about the problem?
    173                                 return;
    174                         }
    175                         sb.append((char)loopstart_char);
    176                         ps = new NMEAParserState();
    177                         ps.p_Date="010100"; // TODO date problem
    178                         while(true) {
    179                                 // don't load unparsable files completely to memory
    180                                 if(sb.length()>=1020) sb.delete(0, sb.length()-1);
    181                                 int c = rd.read();
    182                                 if(c=='$') {
    183                                         ParseNMEASentence(sb.toString(), ps);
    184                                         sb.delete(0, sb.length());
    185                                         sb.append('$');
    186                                 } else if(c == -1) {
    187                                         // EOF: add last WayPoint if it works out
    188                                         ParseNMEASentence(sb.toString(),ps);
    189                                         break;
    190                                 } else sb.append((char)c);
    191                         }
    192                         rd.close();
    193                         Object[] wparr = ps.waypoints.toArray();
    194                         currentTrack.trackSegs.add(ps.waypoints);
    195                         data.recalculateBounds();
    196 
    197                 } catch (final IOException e) {
    198                         // TODO tell user about the problem?
    199                 }
    200         }
    201         private class NMEAParserState {
    202                 protected Collection<WayPoint> waypoints = new ArrayList<WayPoint>();
    203                 protected String p_Time;
    204                 protected String p_Date;
    205                 protected WayPoint p_Wp;
    206 
    207                 protected int success = 0; // number of successfully parsend sentences
    208                 protected int malformed = 0;
    209                 protected int checksum_errors = 0;
    210                 protected int unknown = 0;
    211                 protected int zero_coord = 0;
    212         }
    213 
    214         // Parses split up sentences into WayPoints which are stored
    215         // in the collection in the NMEAParserState object.
    216         // Returns true if the input made sence, false otherwise.
    217         private boolean ParseNMEASentence(String s, NMEAParserState ps) {
    218                 try {
    219                         if(s.equals("")) throw(null);
    220 
    221                         // checksum check:
    222                         // the bytes between the $ and the * are xored;
    223                         // if there is no * or other meanities it will throw
    224                         // and result in a malformed packet.
    225                         String[] chkstrings = s.split("\\*");
    226                         byte[] chb = chkstrings[0].getBytes();
    227                         int chk=0;
    228                         for(int i = 1; i < chb.length; i++) chk ^= chb[i];
    229                         if(Integer.parseInt(chkstrings[1].substring(0,2),16) != chk) {
    230                                 //System.out.println("Checksum error");
    231                                 ps.checksum_errors++;
    232                                 ps.p_Wp=null;
    233                                 return false;
    234                         }
    235                         // now for the content
    236                         String[] e = chkstrings[0].split(",");
    237                         String accu;
    238 
    239                         WayPoint currentwp = ps.p_Wp;
    240                         String currentDate = ps.p_Date;
    241 
    242                         // handle the packet content
    243                         if(e[0].equals("$GPGGA")) {
    244                                 // Position
    245                                 LatLon latLon = parseLatLon(
    246                                                 e[GPGGA.LATITUDE_NAME.position],
    247                                                 e[GPGGA.LONGITUDE_NAME.position],
    248                                                 e[GPGGA.LATITUDE.position],
    249                                                 e[GPGGA.LONGITUDE.position]
    250                                         );
    251                                 if(latLon==null) throw(null); // malformed
    252 
    253                                 if((latLon.lat()==0.0) && (latLon.lon()==0.0)) {
    254                                         ps.zero_coord++;
    255                                         return false;
    256                                 }
    257 
    258                                 // time
    259                                 accu = e[GPGGA.TIME.position];
    260                                 Date d = RMCTIMEFMT.parse(currentDate+accu, new ParsePosition(0));
    261                                 if (d == null) throw(null); // malformed
    262 
    263                                 if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(accu)) {
    264                                         // this node is newer than the previous, create a new waypoint.
    265                                         // no matter if previous WayPoint was null, we got something
    266                                         // better now.
    267                                         ps.p_Time=accu;
    268                                         currentwp = new WayPoint(latLon);
    269                                 }
    270                                 if(!currentwp.attr.containsKey("time")) {
    271                                         // As this sentence has no complete time only use it
    272                                         // if there is no time so far
    273                                         String gpxdate = WayPoint.GPXTIMEFMT.format(d);
    274                                         currentwp.attr.put("time", gpxdate);
    275                                 }
    276                                 // elevation
    277                                 accu=e[GPGGA.HEIGHT_UNTIS.position];
    278                                 if(accu.equals("M")) {
    279                                                 // Ignore heights that are not in meters for now
    280                                                 accu=e[GPGGA.HEIGHT.position];
    281                                                 if(!accu.equals("")) {
    282                                                 Double.parseDouble(accu);
    283                                                 // if it throws it's malformed; this should only happen if the
    284                                                 // device sends nonstandard data.
    285                                                 if(!accu.equals("")) currentwp.attr.put("ele", accu);
    286                                         }
    287                                 }
    288                                 // number of sattelites
    289                                 accu=e[GPGGA.SATELLITE_COUNT.position];
    290                                 int sat = 0;
    291                                 if(!accu.equals("")) {
    292                                         sat = Integer.parseInt(accu);
    293                                         currentwp.attr.put("sat", accu);
    294                                 }
    295                                 // h-dilution
    296                                 accu=e[GPGGA.HDOP.position];
    297                                 if(!accu.equals("")) {
    298                                         Double.parseDouble(accu);
    299                                         currentwp.attr.put("hdop", accu);
    300                                 }
    301                                 // fix
    302                                 accu=e[GPGGA.QUALITY.position];
    303                                 if(!accu.equals("")) {
    304                                         int fixtype = Integer.parseInt(accu);
    305                                         switch(fixtype) {
    306                                         case 0:
    307                                                 currentwp.attr.put("fix", "none");
    308                                                 break;
    309                                         case 1:
    310                                                 if(sat < 4) currentwp.attr.put("fix", "2d");
    311                                                 else currentwp.attr.put("fix", "3d");
    312                                                 break;
    313                                         case 2:
    314                                                 currentwp.attr.put("fix", "dgps");
    315                                                 break;
    316                                         default:
    317                                                 break;
    318                                         }
    319                                 }
    320                         } else if(e[0].equals("$GPVTG")) {
    321                                 // COURSE
    322                                 accu = e[GPVTG.COURSE_REF.position];
    323                                 if(accu.equals("T")) {
    324                                         // other values than (T)rue are ignored
    325                                         accu = e[GPVTG.COURSE.position];
    326                                         if(!accu.equals("")) {
    327                                                 Double.parseDouble(accu);
    328                                                 currentwp.attr.put("course", accu);
    329                                         }
    330                                 }
    331                                 // SPEED
    332                                 accu = e[GPVTG.SPEED_KMH_UNIT.position];
    333                                 if(accu.startsWith("K")) {
    334                                         accu = e[GPVTG.SPEED_KMH.position];
    335                                         if(!accu.equals("")) {
    336                                                 double speed = Double.parseDouble(accu);
    337                                                 speed /= 3.6; // speed in m/s
    338                                                 currentwp.attr.put("speed", Double.toString(speed));
    339                                         }
    340                                 }
    341                         } else if(e[0].equals("$GPGSA")) {
    342                                 // vdop
    343                                 accu=e[GPGSA.VDOP.position];
    344                                 if(!accu.equals("")) {
    345                                         Double.parseDouble(accu);
    346                                         currentwp.attr.put("vdop", accu);
    347                                 }
    348                                 // hdop
    349                                 accu=e[GPGSA.HDOP.position];
    350                                 if(!accu.equals("")) {
    351                                         Double.parseDouble(accu);
    352                                         currentwp.attr.put("hdop", accu);
    353                                 }
    354                                 // pdop
    355                                 accu=e[GPGSA.PDOP.position];
    356                                 if(!accu.equals("")) {
    357                                         Double.parseDouble(accu);
    358                                         currentwp.attr.put("pdop", accu);
    359                                 }
    360                         }
    361                         else if(e[0].equals("$GPRMC")) {
    362                                 // coordinates
    363                                 LatLon latLon = parseLatLon(
    364                                                 e[GPRMC.WIDTH_NORTH_NAME.position],
    365                                                 e[GPRMC.LENGTH_EAST_NAME.position],
    366                                                 e[GPRMC.WIDTH_NORTH.position],
    367                                                 e[GPRMC.LENGTH_EAST.position]
    368                                         );
    369                                 if(latLon==null) throw(null);
    370                                 if((latLon.lat()==0.0) && (latLon.lon()==0.0)) {
    371                                         ps.zero_coord++;
    372                                         return false;
    373                                 }
    374                                 // time
    375                                 currentDate = e[GPRMC.DATE.position];
    376                                 String time = e[GPRMC.TIME.position];
    377 
    378                                 Date d = RMCTIMEFMT.parse(currentDate+time, new ParsePosition(0));
    379                                 if (d == null) throw(null);
    380 
    381                                 if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(time)) {
    382                                         // this node is newer than the previous, create a new waypoint.
    383                                         ps.p_Time=time;
    384                                         currentwp = new WayPoint(latLon);
    385                                 }
    386                                 // time: this sentence has complete time so always use it.
    387                                 String gpxdate = WayPoint.GPXTIMEFMT.format(d);
    388                                 currentwp.attr.put("time", gpxdate);
    389                                 // speed
    390                                 accu = e[GPRMC.SPEED.position];
    391                                 if(!accu.equals("") && !currentwp.attr.containsKey("speed")) {
    392                                         double speed = Double.parseDouble(accu);
    393                                         speed *= 0.514444444; // to m/s
    394                                         currentwp.attr.put("speed", Double.toString(speed));
    395                                 }
    396                                 // course
    397                                 accu = e[GPRMC.COURSE.position];
    398                                 if(!accu.equals("") && !currentwp.attr.containsKey("course")) {
    399                                         Double.parseDouble(accu);
    400                                         currentwp.attr.put("course", accu);
    401                                 }
    402 
    403                                 // TODO fix?
    404                                 // * Mode (A = autonom; D = differential; E = estimated; N = not valid; S
    405                                 // * = simulated)
    406                                 // *
    407                                 // * @since NMEA 2.3
    408                                 //
    409                                 //MODE(12);
    410                         } else {
    411                                 ps.unknown++;
    412                                 return false;
    413                         }
    414                         ps.p_Date = currentDate;
    415                         if(ps.p_Wp != currentwp) {
    416                                 if(ps.p_Wp!=null) {
    417                                         ps.p_Wp.setTime();
    418                                 }
    419                                 ps.p_Wp = currentwp;
    420                                 ps.waypoints.add(currentwp);
    421                                 ps.success++;
    422                                 return true;
    423                         }
    424                         return true;
    425 
    426                 } catch(Exception x) {
    427                         // out of bounds and such
    428                         //System.out.println("Malformed line: "+s.toString().trim());
    429                         ps.malformed++;
    430                         ps.p_Wp=null;
    431                         return false;
    432                 }
    433         }
    434 
    435         private LatLon parseLatLon(String ew, String ns, String dlat, String dlon)
    436                 throws NumberFormatException {
    437                 String widthNorth = dlat.trim();
    438                 String lengthEast = dlon.trim();
    439 
    440                 // return a zero latlon instead of null so it is logged as zero coordinate
    441                 // instead of malformed sentence
    442                 if(widthNorth.equals("")&&lengthEast.equals("")) return new LatLon(0.0,0.0);
    443 
    444                 // The format is xxDDLL.LLLL
    445                 // xx optional whitespace
    446                 // DD (int) degres
    447                 // LL.LLLL (double) latidude
    448                 int latdegsep = widthNorth.indexOf('.') - 2;
    449                 if (latdegsep < 0) return null;
    450 
    451                 int latdeg = Integer.parseInt(widthNorth.substring(0, latdegsep));
    452                 double latmin = Double.parseDouble(widthNorth.substring(latdegsep));
    453                 double lat = latdeg + latmin / 60;
    454                 if ("S".equals(ns)) {
    455                         if(!ew.equals("N")) return null;
    456                         lat = -lat;
    457                 }
    458 
    459                 int londegsep = lengthEast.indexOf('.') - 2;
    460                 if (londegsep < 0) return null;
    461 
    462                 int londeg = Integer.parseInt(lengthEast.substring(0, londegsep));
    463                 double lonmin = Double.parseDouble(lengthEast.substring(londegsep));
    464                 double lon = londeg + lonmin / 60;
    465                 if ("W".equals(ew)) {
    466                         if(!ew.equals("E")) return null;
    467                         lon = -lon;
    468                 }
    469                 return new LatLon(lat, lon);
    470         }
     136    private final static SimpleDateFormat RMCTIMEFMT =
     137        new SimpleDateFormat("ddMMyyHHmmss.SSS");
     138
     139    // functons for reading the error stats
     140    public NMEAParserState ps;
     141
     142    public int getParserUnknown() {
     143        return ps.unknown;
     144    }
     145    public int getParserZeroCoordinates() {
     146        return ps.zero_coord;
     147    }
     148    public int getParserChecksumErrors() {
     149        return ps.checksum_errors;
     150    }
     151    public int getParserMalformed() {
     152        return ps.malformed;
     153    }
     154    public int getNumberOfCoordinates() {
     155        return ps.success;
     156    }
     157
     158    public NmeaReader(InputStream source, File relativeMarkerPath) {
     159
     160        // create the data tree
     161        data = new GpxData();
     162        GpxTrack currentTrack = new GpxTrack();
     163        data.tracks.add(currentTrack);
     164
     165        try {
     166            BufferedReader rd =
     167                new BufferedReader(new InputStreamReader(source));
     168
     169            StringBuffer sb = new StringBuffer(1024);
     170            int loopstart_char = rd.read();
     171            if(loopstart_char == -1) {// zero size file
     172                //TODO tell user about the problem?
     173                return;
     174            }
     175            sb.append((char)loopstart_char);
     176            ps = new NMEAParserState();
     177            ps.p_Date="010100"; // TODO date problem
     178            while(true) {
     179                // don't load unparsable files completely to memory
     180                if(sb.length()>=1020) sb.delete(0, sb.length()-1);
     181                int c = rd.read();
     182                if(c=='$') {
     183                    ParseNMEASentence(sb.toString(), ps);
     184                    sb.delete(0, sb.length());
     185                    sb.append('$');
     186                } else if(c == -1) {
     187                    // EOF: add last WayPoint if it works out
     188                    ParseNMEASentence(sb.toString(),ps);
     189                    break;
     190                } else sb.append((char)c);
     191            }
     192            rd.close();
     193            Object[] wparr = ps.waypoints.toArray();
     194            currentTrack.trackSegs.add(ps.waypoints);
     195            data.recalculateBounds();
     196
     197        } catch (final IOException e) {
     198            // TODO tell user about the problem?
     199        }
     200    }
     201    private class NMEAParserState {
     202        protected Collection<WayPoint> waypoints = new ArrayList<WayPoint>();
     203        protected String p_Time;
     204        protected String p_Date;
     205        protected WayPoint p_Wp;
     206
     207        protected int success = 0; // number of successfully parsend sentences
     208        protected int malformed = 0;
     209        protected int checksum_errors = 0;
     210        protected int unknown = 0;
     211        protected int zero_coord = 0;
     212    }
     213
     214    // Parses split up sentences into WayPoints which are stored
     215    // in the collection in the NMEAParserState object.
     216    // Returns true if the input made sence, false otherwise.
     217    private boolean ParseNMEASentence(String s, NMEAParserState ps) {
     218        try {
     219            if(s.equals("")) throw(null);
     220
     221            // checksum check:
     222            // the bytes between the $ and the * are xored;
     223            // if there is no * or other meanities it will throw
     224            // and result in a malformed packet.
     225            String[] chkstrings = s.split("\\*");
     226            byte[] chb = chkstrings[0].getBytes();
     227            int chk=0;
     228            for(int i = 1; i < chb.length; i++) chk ^= chb[i];
     229            if(Integer.parseInt(chkstrings[1].substring(0,2),16) != chk) {
     230                //System.out.println("Checksum error");
     231                ps.checksum_errors++;
     232                ps.p_Wp=null;
     233                return false;
     234            }
     235            // now for the content
     236            String[] e = chkstrings[0].split(",");
     237            String accu;
     238
     239            WayPoint currentwp = ps.p_Wp;
     240            String currentDate = ps.p_Date;
     241
     242            // handle the packet content
     243            if(e[0].equals("$GPGGA")) {
     244                // Position
     245                LatLon latLon = parseLatLon(
     246                        e[GPGGA.LATITUDE_NAME.position],
     247                        e[GPGGA.LONGITUDE_NAME.position],
     248                        e[GPGGA.LATITUDE.position],
     249                        e[GPGGA.LONGITUDE.position]
     250                    );
     251                if(latLon==null) throw(null); // malformed
     252
     253                if((latLon.lat()==0.0) && (latLon.lon()==0.0)) {
     254                    ps.zero_coord++;
     255                    return false;
     256                }
     257
     258                // time
     259                accu = e[GPGGA.TIME.position];
     260                Date d = RMCTIMEFMT.parse(currentDate+accu, new ParsePosition(0));
     261                if (d == null) throw(null); // malformed
     262
     263                if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(accu)) {
     264                    // this node is newer than the previous, create a new waypoint.
     265                    // no matter if previous WayPoint was null, we got something
     266                    // better now.
     267                    ps.p_Time=accu;
     268                    currentwp = new WayPoint(latLon);
     269                }
     270                if(!currentwp.attr.containsKey("time")) {
     271                    // As this sentence has no complete time only use it
     272                    // if there is no time so far
     273                    String gpxdate = WayPoint.GPXTIMEFMT.format(d);
     274                    currentwp.attr.put("time", gpxdate);
     275                }
     276                // elevation
     277                accu=e[GPGGA.HEIGHT_UNTIS.position];
     278                if(accu.equals("M")) {
     279                        // Ignore heights that are not in meters for now
     280                        accu=e[GPGGA.HEIGHT.position];
     281                        if(!accu.equals("")) {
     282                        Double.parseDouble(accu);
     283                        // if it throws it's malformed; this should only happen if the
     284                        // device sends nonstandard data.
     285                        if(!accu.equals("")) currentwp.attr.put("ele", accu);
     286                    }
     287                }
     288                // number of sattelites
     289                accu=e[GPGGA.SATELLITE_COUNT.position];
     290                int sat = 0;
     291                if(!accu.equals("")) {
     292                    sat = Integer.parseInt(accu);
     293                    currentwp.attr.put("sat", accu);
     294                }
     295                // h-dilution
     296                accu=e[GPGGA.HDOP.position];
     297                if(!accu.equals("")) {
     298                    Double.parseDouble(accu);
     299                    currentwp.attr.put("hdop", accu);
     300                }
     301                // fix
     302                accu=e[GPGGA.QUALITY.position];
     303                if(!accu.equals("")) {
     304                    int fixtype = Integer.parseInt(accu);
     305                    switch(fixtype) {
     306                    case 0:
     307                        currentwp.attr.put("fix", "none");
     308                        break;
     309                    case 1:
     310                        if(sat < 4) currentwp.attr.put("fix", "2d");
     311                        else currentwp.attr.put("fix", "3d");
     312                        break;
     313                    case 2:
     314                        currentwp.attr.put("fix", "dgps");
     315                        break;
     316                    default:
     317                        break;
     318                    }
     319                }
     320            } else if(e[0].equals("$GPVTG")) {
     321                // COURSE
     322                accu = e[GPVTG.COURSE_REF.position];
     323                if(accu.equals("T")) {
     324                    // other values than (T)rue are ignored
     325                    accu = e[GPVTG.COURSE.position];
     326                    if(!accu.equals("")) {
     327                        Double.parseDouble(accu);
     328                        currentwp.attr.put("course", accu);
     329                    }
     330                }
     331                // SPEED
     332                accu = e[GPVTG.SPEED_KMH_UNIT.position];
     333                if(accu.startsWith("K")) {
     334                    accu = e[GPVTG.SPEED_KMH.position];
     335                    if(!accu.equals("")) {
     336                        double speed = Double.parseDouble(accu);
     337                        speed /= 3.6; // speed in m/s
     338                        currentwp.attr.put("speed", Double.toString(speed));
     339                    }
     340                }
     341            } else if(e[0].equals("$GPGSA")) {
     342                // vdop
     343                accu=e[GPGSA.VDOP.position];
     344                if(!accu.equals("")) {
     345                    Double.parseDouble(accu);
     346                    currentwp.attr.put("vdop", accu);
     347                }
     348                // hdop
     349                accu=e[GPGSA.HDOP.position];
     350                if(!accu.equals("")) {
     351                    Double.parseDouble(accu);
     352                    currentwp.attr.put("hdop", accu);
     353                }
     354                // pdop
     355                accu=e[GPGSA.PDOP.position];
     356                if(!accu.equals("")) {
     357                    Double.parseDouble(accu);
     358                    currentwp.attr.put("pdop", accu);
     359                }
     360            }
     361            else if(e[0].equals("$GPRMC")) {
     362                // coordinates
     363                LatLon latLon = parseLatLon(
     364                        e[GPRMC.WIDTH_NORTH_NAME.position],
     365                        e[GPRMC.LENGTH_EAST_NAME.position],
     366                        e[GPRMC.WIDTH_NORTH.position],
     367                        e[GPRMC.LENGTH_EAST.position]
     368                    );
     369                if(latLon==null) throw(null);
     370                if((latLon.lat()==0.0) && (latLon.lon()==0.0)) {
     371                    ps.zero_coord++;
     372                    return false;
     373                }
     374                // time
     375                currentDate = e[GPRMC.DATE.position];
     376                String time = e[GPRMC.TIME.position];
     377
     378                Date d = RMCTIMEFMT.parse(currentDate+time, new ParsePosition(0));
     379                if (d == null) throw(null);
     380
     381                if((ps.p_Time==null) || (currentwp==null) || !ps.p_Time.equals(time)) {
     382                    // this node is newer than the previous, create a new waypoint.
     383                    ps.p_Time=time;
     384                    currentwp = new WayPoint(latLon);
     385                }
     386                // time: this sentence has complete time so always use it.
     387                String gpxdate = WayPoint.GPXTIMEFMT.format(d);
     388                currentwp.attr.put("time", gpxdate);
     389                // speed
     390                accu = e[GPRMC.SPEED.position];
     391                if(!accu.equals("") && !currentwp.attr.containsKey("speed")) {
     392                    double speed = Double.parseDouble(accu);
     393                    speed *= 0.514444444; // to m/s
     394                    currentwp.attr.put("speed", Double.toString(speed));
     395                }
     396                // course
     397                accu = e[GPRMC.COURSE.position];
     398                if(!accu.equals("") && !currentwp.attr.containsKey("course")) {
     399                    Double.parseDouble(accu);
     400                    currentwp.attr.put("course", accu);
     401                }
     402
     403                // TODO fix?
     404                // * Mode (A = autonom; D = differential; E = estimated; N = not valid; S
     405                // * = simulated)
     406                // *
     407                // * @since NMEA 2.3
     408                //
     409                //MODE(12);
     410            } else {
     411                ps.unknown++;
     412                return false;
     413            }
     414            ps.p_Date = currentDate;
     415            if(ps.p_Wp != currentwp) {
     416                if(ps.p_Wp!=null) {
     417                    ps.p_Wp.setTime();
     418                }
     419                ps.p_Wp = currentwp;
     420                ps.waypoints.add(currentwp);
     421                ps.success++;
     422                return true;
     423            }
     424            return true;
     425
     426        } catch(Exception x) {
     427            // out of bounds and such
     428            //System.out.println("Malformed line: "+s.toString().trim());
     429            ps.malformed++;
     430            ps.p_Wp=null;
     431            return false;
     432        }
     433    }
     434
     435    private LatLon parseLatLon(String ew, String ns, String dlat, String dlon)
     436        throws NumberFormatException {
     437        String widthNorth = dlat.trim();
     438        String lengthEast = dlon.trim();
     439
     440        // return a zero latlon instead of null so it is logged as zero coordinate
     441        // instead of malformed sentence
     442        if(widthNorth.equals("")&&lengthEast.equals("")) return new LatLon(0.0,0.0);
     443
     444        // The format is xxDDLL.LLLL
     445        // xx optional whitespace
     446        // DD (int) degres
     447        // LL.LLLL (double) latidude
     448        int latdegsep = widthNorth.indexOf('.') - 2;
     449        if (latdegsep < 0) return null;
     450
     451        int latdeg = Integer.parseInt(widthNorth.substring(0, latdegsep));
     452        double latmin = Double.parseDouble(widthNorth.substring(latdegsep));
     453        double lat = latdeg + latmin / 60;
     454        if ("S".equals(ns)) {
     455            if(!ew.equals("N")) return null;
     456            lat = -lat;
     457        }
     458
     459        int londegsep = lengthEast.indexOf('.') - 2;
     460        if (londegsep < 0) return null;
     461
     462        int londeg = Integer.parseInt(lengthEast.substring(0, londegsep));
     463        double lonmin = Double.parseDouble(lengthEast.substring(londegsep));
     464        double lon = londeg + lonmin / 60;
     465        if ("W".equals(ew)) {
     466            if(!ew.equals("E")) return null;
     467            lon = -lon;
     468        }
     469        return new LatLon(lat, lon);
     470    }
    471471}
  • trunk/src/org/openstreetmap/josm/io/OsmConnection.java

    r763 r1169  
    3434public class OsmConnection {
    3535
    36         public static class OsmParseException extends Exception {
    37                 public OsmParseException() {super();}
    38                 public OsmParseException(String message, Throwable cause) {super(message, cause);}
    39                 public OsmParseException(String message) {super(message);}
    40                 public OsmParseException(Throwable cause) {super(cause);}
    41         }
     36    public static class OsmParseException extends Exception {
     37        public OsmParseException() {super();}
     38        public OsmParseException(String message, Throwable cause) {super(message, cause);}
     39        public OsmParseException(String message) {super(message);}
     40        public OsmParseException(Throwable cause) {super(cause);}
     41    }
    4242
    43         protected boolean cancel = false;
    44         protected HttpURLConnection activeConnection;
     43    protected boolean cancel = false;
     44    protected HttpURLConnection activeConnection;
    4545
    46         private static OsmAuth authentication = new OsmAuth();
    47         /**
    48         * Initialize the http defaults and the authenticator.
    49         */
    50         static {
    51                 //TODO: refactor this crap (maybe just insert the damn auth http-header by yourself)
    52                 try {
    53                 HttpURLConnection.setFollowRedirects(true);
    54                 Authenticator.setDefault(authentication);
     46    private static OsmAuth authentication = new OsmAuth();
     47    /**
     48    * Initialize the http defaults and the authenticator.
     49    */
     50    static {
     51        //TODO: refactor this crap (maybe just insert the damn auth http-header by yourself)
     52        try {
     53            HttpURLConnection.setFollowRedirects(true);
     54            Authenticator.setDefault(authentication);
    5555        } catch (SecurityException e) {
    5656        }
    57         }
     57    }
    5858
    59         /**
    60         * The authentication class handling the login requests.
    61         */
    62         private static class OsmAuth extends Authenticator {
    63                 /**
    64                 * Set to true, when the autenticator tried the password once.
    65                 */
    66                 boolean passwordtried = false;
    67                 /**
    68                 * Whether the user cancelled the password dialog
    69                 */
    70                 boolean authCancelled = false;
     59    /**
     60    * The authentication class handling the login requests.
     61    */
     62    private static class OsmAuth extends Authenticator {
     63        /**
     64        * Set to true, when the autenticator tried the password once.
     65        */
     66        boolean passwordtried = false;
     67        /**
     68        * Whether the user cancelled the password dialog
     69        */
     70        boolean authCancelled = false;
    7171
    72                 @Override protected PasswordAuthentication getPasswordAuthentication() {
    73                         String username = Main.pref.get("osm-server.username");
    74                         String password = Main.pref.get("osm-server.password");
    75                         if (passwordtried || username.equals("") || password.equals("")) {
    76                                 JPanel p = new JPanel(new GridBagLayout());
    77                                 if (!username.equals("") && !password.equals(""))
    78                                         p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
    79                                 p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
    80                                 JTextField usernameField = new JTextField(username, 20);
    81                                 p.add(usernameField, GBC.eol());
    82                                 p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
    83                                 JPasswordField passwordField = new JPasswordField(password, 20);
    84                                 p.add(passwordField, GBC.eol());
    85                                 JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
    86                                 warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
    87                                 p.add(warning, GBC.eop());
     72        @Override protected PasswordAuthentication getPasswordAuthentication() {
     73            String username = Main.pref.get("osm-server.username");
     74            String password = Main.pref.get("osm-server.password");
     75            if (passwordtried || username.equals("") || password.equals("")) {
     76                JPanel p = new JPanel(new GridBagLayout());
     77                if (!username.equals("") && !password.equals(""))
     78                    p.add(new JLabel(tr("Incorrect password or username.")), GBC.eop());
     79                p.add(new JLabel(tr("Username")), GBC.std().insets(0,0,10,0));
     80                JTextField usernameField = new JTextField(username, 20);
     81                p.add(usernameField, GBC.eol());
     82                p.add(new JLabel(tr("Password")), GBC.std().insets(0,0,10,0));
     83                JPasswordField passwordField = new JPasswordField(password, 20);
     84                p.add(passwordField, GBC.eol());
     85                JLabel warning = new JLabel(tr("Warning: The password is transferred unencrypted."));
     86                warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
     87                p.add(warning, GBC.eop());
    8888
    89                                 JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
    90                                 p.add(savePassword, GBC.eop());
     89                JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), !username.equals("") && !password.equals(""));
     90                p.add(savePassword, GBC.eop());
    9191
    92                                 int choice = JOptionPane.showConfirmDialog(Main.parent, p, tr("Enter Password"), JOptionPane.OK_CANCEL_OPTION);
    93                                 if (choice == JOptionPane.CANCEL_OPTION) {
    94                                         authCancelled = true;
    95                                         return null;
    96                                 }
    97                                 username = usernameField.getText();
    98                                 password = String.valueOf(passwordField.getPassword());
    99                                 if (savePassword.isSelected()) {
    100                                         Main.pref.put("osm-server.username", username);
    101                                         Main.pref.put("osm-server.password", password);
    102                                 }
    103                                 if (username.equals(""))
    104                                         return null;
    105                         }
    106                         passwordtried = true;
    107                         return new PasswordAuthentication(username, password.toCharArray());
    108                 }
    109         }
     92                int choice = JOptionPane.showConfirmDialog(Main.parent, p, tr("Enter Password"), JOptionPane.OK_CANCEL_OPTION);
     93                if (choice == JOptionPane.CANCEL_OPTION) {
     94                    authCancelled = true;
     95                    return null;
     96                }
     97                username = usernameField.getText();
     98                password = String.valueOf(passwordField.getPassword());
     99                if (savePassword.isSelected()) {
     100                    Main.pref.put("osm-server.username", username);
     101                    Main.pref.put("osm-server.password", password);
     102                }
     103                if (username.equals(""))
     104                    return null;
     105            }
     106            passwordtried = true;
     107            return new PasswordAuthentication(username, password.toCharArray());
     108        }
     109    }
    110110
    111         /**
    112         * Must be called before each connection attemp to initialize the authentication.
    113         */
    114         protected final void initAuthentication() {
    115                 authentication.authCancelled = false;
    116                 authentication.passwordtried = false;
    117         }
     111    /**
     112    * Must be called before each connection attemp to initialize the authentication.
     113    */
     114    protected final void initAuthentication() {
     115        authentication.authCancelled = false;
     116        authentication.passwordtried = false;
     117    }
    118118
    119         /**
    120         * @return Whether the connection was cancelled.
    121         */
    122         protected final boolean isAuthCancelled() {
    123                 return authentication.authCancelled;
    124         }
     119    /**
     120    * @return Whether the connection was cancelled.
     121    */
     122    protected final boolean isAuthCancelled() {
     123        return authentication.authCancelled;
     124    }
    125125
    126         public void cancel() {
    127                 Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
    128                 cancel = true;
    129                 if (activeConnection != null) {
    130                         activeConnection.setConnectTimeout(100);
    131                         activeConnection.setReadTimeout(100);
    132                         try {
    133                                 Thread.sleep(100);
    134                         } catch (InterruptedException ex) {}
    135                         activeConnection.disconnect();
    136                 }
    137         }
     126    public void cancel() {
     127        Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
     128        cancel = true;
     129        if (activeConnection != null) {
     130            activeConnection.setConnectTimeout(100);
     131            activeConnection.setReadTimeout(100);
     132            try {
     133                Thread.sleep(100);
     134            } catch (InterruptedException ex) {}
     135            activeConnection.disconnect();
     136        }
     137    }
    138138
    139         protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
    140                 CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    141                 String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
    142                 ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
    143                 con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
    144         }
     139    protected void addAuth(HttpURLConnection con) throws CharacterCodingException {
     140        CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
     141        String auth = Main.pref.get("osm-server.username") + ":" + Main.pref.get("osm-server.password");
     142        ByteBuffer bytes = encoder.encode(CharBuffer.wrap(auth));
     143        con.addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));
     144    }
    145145}
  • trunk/src/org/openstreetmap/josm/io/OsmIdReader.java

    r627 r1169  
    2121/**
    2222 * Read only the ids and classes of an stream.
    23  * 
     23 *
    2424 * @author Imi
    2525 */
    2626public class OsmIdReader extends DefaultHandler {
    2727
    28         private boolean cancel;
    29         Map<Long, String> entries = new HashMap<Long, String>();
    30         private Reader in;
     28    private boolean cancel;
     29    Map<Long, String> entries = new HashMap<Long, String>();
     30    private Reader in;
    3131
    32         @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    33                 if (qName.equals("node") || qName.equals("way") || qName.equals("relation")) {
    34                         try {
    35                                 entries.put(Long.valueOf(atts.getValue("id")), qName);
    36                         } catch (Exception e) {
    37                                 e.printStackTrace();
    38                                 throw new SAXException(tr("Error during parse."));
    39                         }
    40                 }
     32    @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
     33        if (qName.equals("node") || qName.equals("way") || qName.equals("relation")) {
     34            try {
     35                entries.put(Long.valueOf(atts.getValue("id")), qName);
     36            } catch (Exception e) {
     37                e.printStackTrace();
     38                throw new SAXException(tr("Error during parse."));
     39            }
     40        }
    4141    }
    4242
    43         public Map<Long, String> parseIds(InputStream in) throws IOException, SAXException {
     43    public Map<Long, String> parseIds(InputStream in) throws IOException, SAXException {
    4444        this.in = new InputStreamReader(in, "UTF-8");
    45                 try {
    46                 SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(this.in), this);
     45        try {
     46            SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(this.in), this);
    4747        } catch (ParserConfigurationException e) {
    48                 if (!cancel) {
    49                         e.printStackTrace(); // broken SAXException chaining
    50                         throw new SAXException(e);
    51                 }
     48            if (!cancel) {
     49                e.printStackTrace(); // broken SAXException chaining
     50                throw new SAXException(e);
     51            }
    5252        } catch (SAXException e) {
    53                 if (!cancel)
    54                         throw e;
    55         }       
    56                 return entries;
    57         }
    58        
    59         public void cancel() {
    60                 cancel = true;
    61                 if (in != null)
     53            if (!cancel)
     54                throw e;
     55        }
     56        return entries;
     57    }
     58
     59    public void cancel() {
     60        cancel = true;
     61        if (in != null)
    6262            try {in.close();} catch (IOException e) {}
    63         }
     63    }
    6464}
  • trunk/src/org/openstreetmap/josm/io/OsmReader.java

    r1071 r1169  
    106106     private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>();
    107107
    108      /** 
     108     /**
    109109      * Data structure for relation objects
    110110      */
    111111     private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>();
    112112
    113      /** 
     113     /**
    114114      * List of protocol versions that will be accepted on reading
    115115      */
    … …  
    133133                         generator = atts.getValue("generator");
    134134
    135                          
     135
    136136                    } else if (qName.equals("bound")) {
    137137                         // old style bounds.
    138138                         // TODO: remove this around 1st October 2008.
    139                          // - this is a bit of a hack; since we still write out old style bound objects, 
     139                         // - this is a bit of a hack; since we still write out old style bound objects,
    140140                         // we don't want to load them both. so when writing, we add a "note" tag the our
    141141                         // old-style bound, and when reading, ignore those with a "note".
    … …  
    172172                              ds.dataSources.add(src);
    173173                         }
    174                          
     174
    175175                    // ---- PARSING NODES AND WAYS ----
    176                          
     176
    177177                    } else if (qName.equals("node")) {
    178178                         current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
    … …  
    192192                         list.add(id);
    193193
    194                     // ---- PARSING RELATIONS ----               
     194                    // ---- PARSING RELATIONS ----
    195195
    196196                    } else if (qName.equals("relation")) {
    … …  
    207207                         emd.type=atts.getValue("type");
    208208                         emd.relationMember.role = atts.getValue("role");
    209                          
     209
    210210                         if (emd.id == 0)
    211211                              throw new SAXException(tr("Incomplete <member> specification with ref=0"));
    212                          
     212
    213213                         list.add(emd);
    214                          
     214
    215215                    // ---- PARSING TAGS (applicable to all objects) ----
    216                          
     216
    217217                    } else if (qName.equals("tag")) {
    218218                         current.put(atts.getValue("k"), atts.getValue("v"));
    … …  
    231231          }
    232232     }
    233      
    234      /** 
     233
     234     /**
    235235      * Constructor initializes list of allowed protocol versions.
    236236      */
    … …  
    239239          allowedVersions.add(Main.pref.get("osm-server.version", "0.5"));
    240240          // now also add all compatible versions
    241           String[] additionalVersions = 
     241          String[] additionalVersions =
    242242               Main.pref.get("osm-server.additional-versions", "").split("/,/");
    243243          if (additionalVersions.length == 1 && additionalVersions[0].length() == 0)
    244244               additionalVersions = new String[] {};
    245           allowedVersions.addAll(Arrays.asList(additionalVersions));     
     245          allowedVersions.addAll(Arrays.asList(additionalVersions));
    246246     }
    247247
    … …  
    267267               current.timestamp = time;
    268268          }
    269          
     269
    270270          // user attribute added in 0.4 API
    271271          String user = atts.getValue("user");
    … …  
    274274               current.user = User.get(user);
    275275          }
    276          
     276
    277277          // visible attribute added in 0.4 API
    278278          String visible = atts.getValue("visible");
    … …  
    342342               adder.visit(w);
    343343          }
    344          
     344
    345345     }
    346346
    … …  
    348348      * Return the Way object with the given id, or null if it doesn't
    349349      * exist yet. This method only looks at ways stored in the data set.
    350       * 
     350      *
    351351      * @param id
    352352      * @return way object or null
    … …  
    365365      * Return the Relation object with the given id, or null if it doesn't
    366366      * exist yet. This method only looks at relations stored in the data set.
    367       * 
     367      *
    368368      * @param id
    369369      * @return relation object or null
    … …  
    380380
    381381     /**
    382       * Create relations. This is slightly different than n/s/w because 
     382      * Create relations. This is slightly different than n/s/w because
    383383      * unlike other objects, relations may reference other relations; it
    384384      * is not guaranteed that a referenced relation will have been created
    … …  
    387387      */
    388388     private void createRelations() {
    389          
     389
    390390          // pass 1 - create all relations
    391391          for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) {
    … …  
    399399               Relation en = findRelation(e.getKey().id);
    400400               if (en == null) throw new Error("Failed to create relation " + e.getKey().id);
    401                
     401
    402402               for (RelationMemberData emd : e.getValue()) {
    403403                    RelationMember em = emd.relationMember;
  • trunk/src/org/openstreetmap/josm/io/OsmServerLocationReader.java

    r1146 r1169  
    1212
    1313public class OsmServerLocationReader extends OsmServerReader {
    14  
     14
    1515    String url;
    16    
     16
    1717    public OsmServerLocationReader(String url) {
    1818        this.url = url;
    1919    }
    20    
     20
    2121    /**
    2222     * Method to download OSM files from somewhere
  • trunk/src/org/openstreetmap/josm/io/OsmServerObjectReader.java

    r1146 r1169  
    2020    String type;
    2121    boolean full;
    22    
     22
    2323    public OsmServerObjectReader(long id, String type, boolean full) {
    2424        this.id = id;
  • trunk/src/org/openstreetmap/josm/io/OsmServerReader.java

    r1146 r1169  
    1919/**
    2020 * This DataReader reads directly from the REST API of the osm server.
    21  * 
     21 *
    2222 * It supports plain text transfer as well as gzip or deflate encoded transfers;
    2323 * if compressed transfers are unwanted, set property osm-server.use-compression
    … …  
    2727 */
    2828public abstract class OsmServerReader extends OsmConnection {
    29         /**
    30         * Open a connection to the given url and return a reader on the input stream
    31         * from that connection. In case of user cancel, return <code>null</code>.
    32         * @param urlStr The exact url to connect to.
    33         * @param pleaseWaitDlg
    34         * @return An reader reading the input stream (servers answer) or <code>null</code>.
    35         */
    36         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;
     29    /**
     30    * Open a connection to the given url and return a reader on the input stream
     31    * from that connection. In case of user cancel, return <code>null</code>.
     32    * @param urlStr The exact url to connect to.
     33    * @param pleaseWaitDlg
     34    * @return An reader reading the input stream (servers answer) or <code>null</code>.
     35    */
     36    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;
    3939        return getInputStreamRaw(urlStr, pleaseWaitDlg);
    4040    }
    41    
     41
    4242    protected InputStream getInputStreamRaw(String urlStr, PleaseWaitDialog pleaseWaitDlg) throws IOException {
    43        
    44                 System.out.println("download: "+urlStr);
    45                 initAuthentication();
    46                 URL url = new URL(urlStr);
    47                 activeConnection = (HttpURLConnection)url.openConnection();
    48                 if (cancel) {
    49                         activeConnection.disconnect();
    50                         return null;
    51                 }
    52                
    53                 if (Boolean.parseBoolean(Main.pref.get("osm-server.use-compression", "true")))
    54                         activeConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
    5543
    56                 activeConnection.setConnectTimeout(15000);
    57                 if (isAuthCancelled() && activeConnection.getResponseCode() == 401)
    58                         return null;
    59                 if (activeConnection.getResponseCode() == 500)
    60                 {
    61                         throw new IOException(tr("Server returned internal error. Try a reduced area or retry after waiting some time."));
    62                 }
    63 //              System.out.println("got return: "+activeConnection.getResponseCode());
     44        System.out.println("download: "+urlStr);
     45        initAuthentication();
     46        URL url = new URL(urlStr);
     47        activeConnection = (HttpURLConnection)url.openConnection();
     48        if (cancel) {
     49            activeConnection.disconnect();
     50            return null;
     51        }
    6452
    65                 String encoding = activeConnection.getContentEncoding();
    66                 InputStream inputStream = new ProgressInputStream(activeConnection, pleaseWaitDlg);
    67                 if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
    68                         inputStream = new GZIPInputStream(inputStream);
    69                 }
    70                 else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
    71                         inputStream = new InflaterInputStream(inputStream, new Inflater(true));
    72                 }
    73                 return inputStream;
    74         }
    75    
     53        if (Boolean.parseBoolean(Main.pref.get("osm-server.use-compression", "true")))
     54            activeConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
     55
     56        activeConnection.setConnectTimeout(15000);
     57        if (isAuthCancelled() && activeConnection.getResponseCode() == 401)
     58            return null;
     59        if (activeConnection.getResponseCode() == 500)
     60        {
     61            throw new IOException(tr("Server returned internal error. Try a reduced area or retry after waiting some time."));
     62        }
     63//      System.out.println("got return: "+activeConnection.getResponseCode());
     64
     65        String encoding = activeConnection.getContentEncoding();
     66        InputStream inputStream = new ProgressInputStream(activeConnection, pleaseWaitDlg);
     67        if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
     68            inputStream = new GZIPInputStream(inputStream);
     69        }
     70        else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
     71            inputStream = new InflaterInputStream(inputStream, new Inflater(true));
     72        }
     73        return inputStream;
     74    }
     75
    7676    public abstract DataSet parseOsm() throws SAXException, IOException;
    77    
     77
    7878}
  • trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java

    r1137 r1169  
    7979
    8080    long uploadStartTime;
    81    
     81
    8282    public String timeLeft(int progress, int list_size) {
    8383        long now = System.currentTimeMillis();
    … …  
    9696        return time_left_str;
    9797    }
    98    
     98
    9999    public void uploadOsm(Collection<OsmPrimitive> list) throws SAXException {
    100100        processed = new LinkedList<OsmPrimitive>();
    … …  
    103103        Main.pleaseWaitDlg.progress.setMaximum(list.size());
    104104        Main.pleaseWaitDlg.progress.setValue(0);
    105        
     105
    106106        // controls whether or not we open and close a changeset. API 0.6 requires changesets.
    107107        boolean useChangesets = Main.pref.get("osm-server.version", "0.5").equals("0.6");
    108        
     108
    109109        // controls whether or not we try and uplaod the whole bunch in one go
    110         boolean useDiffUploads = Main.pref.getBoolean("osm-server.atomic-upload", 
     110        boolean useDiffUploads = Main.pref.getBoolean("osm-server.atomic-upload",
    111111            Main.pref.get("osm-server.version", "0.5").equals("0.6"));
    112        
     112
    113113        String comment = null;
    114114        while (useChangesets && comment == null) {
    115             comment = JOptionPane.showInputDialog(Main.parent, 
     115            comment = JOptionPane.showInputDialog(Main.parent,
    116116                 tr("Provide a brief comment as to the changes to you are uploading:"),
    117117                 tr("Commit comment"), JOptionPane.QUESTION_MESSAGE);
    … …  
    131131            return;
    132132        }
    133    
     133
    134134        try {
    135135            if (useDiffUploads) {
    … …  
    166166            }
    167167            catch (OsmTransferException ex) {
    168                 dealWithTransferException(ex);   
     168                dealWithTransferException(ex);
    169169            }
    170170            dealWithTransferException(e);
    171171        }
    172172    }
    173    
     173
    174174    /* FIXME: This code is terrible, please fix it!!!! */
    175175
    … …  
    183183     * can fix the issue where hitting cancel doesn't do anything while
    184184     * retrying. - Mv0 Apr 2008
    185      * 
     185     *
    186186     * Cancelling has an effect now, maybe it does not always catch on. Florian Heer, Aug 08
    187187     */
    … …  
    198198                    Main.pref.get("osm-server.url") +
    199199                    "/" + version +
    200                     "/" + "changeset" + 
     200                    "/" + "changeset" +
    201201                    "/" + "create");
    202202            System.out.print("upload to: "+url+ "..." );
    … …  
    205205            activeConnection.setRequestMethod("PUT");
    206206            addAuth(activeConnection);
    207            
     207
    208208            activeConnection.setDoOutput(true);
    209209            OutputStream out = activeConnection.getOutputStream();
    210210            OsmWriter.output(out, changeset);
    211211            out.close();
    212            
     212
    213213            activeConnection.connect();
    214214            System.out.println("connected");
    … …  
    224224            }
    225225            if (retCode != 200 && retCode != 412) {
    226                
     226
    227227                if (retries >= 0) {
    228228                    retries--;
    … …  
    232232                    return startChangeset(retries, comment);
    233233                }
    234                
     234
    235235                // Look for a detailed error message from the server
    236236                retMsg += "\n" + readString(activeConnection.getInputStream());
    … …  
    262262                throw new OsmTransferException (e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
    263263        }
    264        
     264
    265265        catch (Exception e) {
    266266            if (cancel)
    … …  
    274274        return true;
    275275    }
    276    
     276
    277277    private void uploadDiff(int retries, Collection<OsmPrimitive> list) throws OsmTransferException {
    278        
     278
    279279        CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset);
    280280
    … …  
    290290        String diff = duv.getDocument();
    291291        System.out.println(diff);
    292        
     292
    293293        Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
    294294        try {
    … …  
    299299                    Main.pref.get("osm-server.url") +
    300300                    "/" + version +
    301                     "/" + "changeset" + 
     301                    "/" + "changeset" +
    302302                    "/" + changeset.id +
    303303                    "/upload" );
    … …  
    307307            activeConnection.setRequestMethod("POST");
    308308            addAuth(activeConnection);
    309            
     309
    310310            activeConnection.setDoOutput(true);
    311311            PrintWriter out;
    … …  
    317317            out.print(diff);
    318318            out.close();
    319            
     319
    320320            activeConnection.connect();
    321321            System.out.println("connected");
    … …  
    323323            int retCode = activeConnection.getResponseCode();
    324324            String retMsg = "";
    325            
     325
    326326            if (retCode == 200) {
    327327                DiffResultReader.parseDiffResult(activeConnection.getInputStream(), list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
    … …  
    333333                    System.out.println("retrying ("+retries+" left)");
    334334                    stopChangeset(retries);
    335                 } else { 
     335                } else {
    336336                    // Look for a detailed error message from the server
    337337                    retMsg += "\n" + readString(activeConnection.getInputStream());
    … …  
    372372        }
    373373    }
    374    
    375    
     374
     375
    376376    private void stopChangeset(int retries) throws OsmTransferException {
    377377        Main.pleaseWaitDlg.currentAction.setText(tr("Closing changeset..."));
    … …  
    383383                    Main.pref.get("osm-server.url") +
    384384                    "/" + version +
    385                     "/" + "changeset" + 
     385                    "/" + "changeset" +
    386386                    "/" + changeset.id +
    387387                    "/close" );
    … …  
    391391            activeConnection.setRequestMethod("PUT");
    392392            addAuth(activeConnection);
    393            
     393
    394394            activeConnection.setDoOutput(true);
    395395            OutputStream out = activeConnection.getOutputStream();
    396396            OsmWriter.output(out, changeset);
    397397            out.close();
    398            
     398
    399399            activeConnection.connect();
    400400            System.out.println("connected");
    … …  
    415415                    System.out.println("retrying ("+retries+" left)");
    416416                    stopChangeset(retries);
    417                 } else { 
     417                } else {
    418418                    // Look for a detailed error message from the server
    419419                    retMsg += readString(activeConnection.getInputStream());
    420                    
     420
    421421                    // Report our error
    422422                    ByteArrayOutputStream o = new ByteArrayOutputStream();
    … …  
    490490        processed.add(e);
    491491    }
    492    
     492
    493493    /**
    494494     * Read a long from the input stream and return it.
    … …  
    540540                    new URL(Main.pref.get("osm-server.url") +
    541541                    "/" + version + "/"),
    542                     urlSuffix + 
     542                    urlSuffix +
    543543                    "/" + (osm.id==0 ? "create" : osm.id),
    544544                    new MyHttpHandler());
    … …  
    622622        }
    623623    }
    624    
     624
    625625    private void sendRequest(String requestMethod, String urlSuffix,
    626626            OsmPrimitive osm, boolean addBody)  {
    … …  
    636636        }
    637637    }
    638    
     638
    639639    private void dealWithTransferException (OsmTransferException e) {
    640640        Main.pleaseWaitDlg.currentAction.setText(tr("Transfer aborted due to error (will wait for 5 seconds):") + e.getMessage());
  • trunk/src/org/openstreetmap/josm/io/OsmTransferException.java

    r784 r1169  
    44public class OsmTransferException extends Exception {
    55
    6         public OsmTransferException() {
    7         }
     6    public OsmTransferException() {
     7    }
    88
    9         public OsmTransferException(String message) {
    10                 super(message);
    11         }
     9    public OsmTransferException(String message) {
     10        super(message);
     11    }
    1212
    13         public OsmTransferException(Throwable cause) {
    14                 super(cause);
    15         }
     13    public OsmTransferException(Throwable cause) {
     14        super(cause);
     15    }
    1616
    17         public OsmTransferException(String message, Throwable cause) {
    18                 super(message, cause);
    19         }
     17    public OsmTransferException(String message, Throwable cause) {
     18        super(message, cause);
     19    }
    2020
    2121}
  • trunk/src/org/openstreetmap/josm/io/OsmWriter.java

    r1071 r1169  
    2424public class OsmWriter extends XmlWriter implements Visitor {
    2525
    26         /**
    27         * The counter for new created objects. Starting at -1 and goes down.
    28         */
    29         private long newIdCounter = -1;
    30         /**
    31         * All newly created ids and their primitive that uses it. This is a back reference
    32         * map to allow references to use the correnct primitives.
    33         */
    34         public HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();
    35 
    36         private final boolean osmConform;
    37         private final Changeset changeset;
    38 
    39         public abstract static class Osm implements OsmWriterInterface {
    40                 public void header(PrintWriter out) {
    41                         out.print("<osm version='");
    42                         out.print(Main.pref.get("osm-server.version", "0.5"));
    43                         out.println("' generator='JOSM'>");
    44                 }
    45                 public void footer(PrintWriter out) {
    46                         out.println("</osm>");
    47                 }
    48         }
    49        
    50         // simple helper to write the object's class to the out stream
    51         private Visitor typeWriteVisitor = new Visitor() {
    52                 public void visit(Node n) { out.print("node"); }
    53                 public void visit(Way w) { out.print("way"); }
    54                 public void visit(Relation e) { out.print("relation"); }
    55         };
    56        
    57         /**
    58         * An output writer for function output that writes everything of the given dataset into
    59         * the xml
    60         */
    61         public static final class All extends Osm {
    62                 private final DataSet ds;
    63                 private final boolean osmConform;
    64 
    65                 /**
    66                 * Construct an writer function
    67                 * @param osmConform <code>true</code>, if the xml should be 100% osm conform. In this
    68                  *              case, not all information can be retrieved later (as example, modified state
    69                  *              is lost and id's remain 0 instead of decrementing from -1)
    70                 */
    71                 public All(DataSet ds, boolean osmConform) {
    72                         this.ds = ds;
    73                         this.osmConform = osmConform;
    74                 }
    75 
    76                 public void write(PrintWriter out) {
    77                         Visitor writer = new OsmWriter(out, osmConform, null);
    78                         for (Node n : ds.nodes)
    79                                 if (shouldWrite(n))
    80                                         writer.visit(n);
    81                         for (Way w : ds.ways)
    82                                 if (shouldWrite(w))
    83                                         writer.visit(w);
    84                         for (Relation e : ds.relations)
    85                                 if (shouldWrite(e))
    86                                         writer.visit(e);
    87         }
    88 
    89                 private boolean shouldWrite(OsmPrimitive osm) {
    90                 return osm.id != 0 || !osm.deleted;
    91         }
    92 
    93                 @Override public void header(PrintWriter out) {
    94                 super.header(out);
    95                         for (DataSource s : ds.dataSources) {
     26    /**
     27    * The counter for new created objects. Starting at -1 and goes down.
     28    */
     29    private long newIdCounter = -1;
     30    /**
     31    * All newly created ids and their primitive that uses it. This is a back reference
     32    * map to allow references to use the correnct primitives.
     33    */
     34    public HashMap<OsmPrimitive, Long> usedNewIds = new HashMap<OsmPrimitive, Long>();
     35
     36    private final boolean osmConform;
     37    private final Changeset changeset;
     38
     39    public abstract static class Osm implements OsmWriterInterface {
     40        public void header(PrintWriter out) {
     41            out.print("<osm version='");
     42            out.print(Main.pref.get("osm-server.version", "0.5"));
     43            out.println("' generator='JOSM'>");
     44        }
     45        public void footer(PrintWriter out) {
     46            out.println("</osm>");
     47        }
     48    }
     49
     50    // simple helper to write the object's class to the out stream
     51    private Visitor typeWriteVisitor = new Visitor() {
     52        public void visit(Node n) { out.print("node"); }
     53        public void visit(Way w) { out.print("way"); }
     54        public void visit(Relation e) { out.print("relation"); }
     55    };
     56
     57    /**
     58    * An output writer for function output that writes everything of the given dataset into
     59    * the xml
     60    */
     61    public static final class All extends Osm {
     62        private final DataSet ds;
     63        private final boolean osmConform;
     64
     65        /**
     66        * Construct an writer function
     67        * @param osmConform <code>true</code>, if the xml should be 100% osm conform. In this
     68         *      case, not all information can be retrieved later (as example, modified state
     69         *      is lost and id's remain 0 instead of decrementing from -1)
     70        */
     71        public All(DataSet ds, boolean osmConform) {
     72            this.ds = ds;
     73            this.osmConform = osmConform;
     74        }
     75
     76        public void write(PrintWriter out) {
     77            Visitor writer = new OsmWriter(out, osmConform, null);
     78            for (Node n : ds.nodes)
     79                if (shouldWrite(n))
     80                    writer.visit(n);
     81            for (Way w : ds.ways)
     82                if (shouldWrite(w))
     83                    writer.visit(w);
     84            for (Relation e : ds.relations)
     85                if (shouldWrite(e))
     86                    writer.visit(e);
     87        }
     88
     89        private boolean shouldWrite(OsmPrimitive osm) {
     90            return osm.id != 0 || !osm.deleted;
     91        }
     92
     93        @Override public void header(PrintWriter out) {
     94            super.header(out);
     95            for (DataSource s : ds.dataSources) {
    9696                // TODO: remove <bound> output after a grace period (1st October 08)
    97                                 out.print("  <bound note='this tag is deprecated and only provided for backward compatiblity' box='"+
    98                                                 s.bounds.min.lat()+","+
    99                                                 s.bounds.min.lon()+","+
    100                                                 s.bounds.max.lat()+","+
    101                                                 s.bounds.max.lon()+"' ");
    102                                 out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
    103                                 out.print("  <bounds minlat='" + 
    104                                                 s.bounds.min.lat()+"' minlon='"+
    105                                                 s.bounds.min.lon()+"' maxlat='"+
    106                                                 s.bounds.max.lat()+"' maxlon='"+
    107                                                 s.bounds.max.lon()+"' ");
    108                                 out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
    109                         }
    110         }
    111         }
    112 
    113         /**
    114         * An output writer for functino output that writes only one specific primitive into
    115         * the xml
    116         */
    117         public static final class Single extends Osm {
    118                 private final OsmPrimitive osm;
    119                 private final boolean osmConform;
    120                 private final Changeset changeset;
    121 
    122                 public Single(OsmPrimitive osm, boolean osmConform, Changeset changeset) {
    123                         this.osm = osm;
    124                         this.osmConform = osmConform;
    125                         this.changeset = changeset;
    126                 }
    127 
    128                 public void write(PrintWriter out) {
    129                         osm.visit(new OsmWriter(out, osmConform, changeset));
    130         }
    131         }
    132 
    133         public OsmWriter(PrintWriter out, boolean osmConform, Changeset changeset) {
    134                 super(out);
    135                 this.osmConform = osmConform;
    136                 this.changeset = changeset;
    137         }
    138 
    139         public void visit(Node n) {
    140                 if (n.incomplete) return;
    141                 addCommon(n, "node");
    142                 out.print(" lat='"+n.coor.lat()+"' lon='"+n.coor.lon()+"'");
    143                 addTags(n, "node", true);
    144         }
    145 
    146         public void visit(Way w) {
    147                 if (w.incomplete) return;
    148                 addCommon(w, "way");
    149                 out.println(">");
    150                 for (Node n : w.nodes)
    151                         out.println("    <nd ref='"+getUsedId(n)+"' />");
    152                 addTags(w, "way", false);
    153         }
    154 
    155         public void visit(Relation e) {
    156                 if (e.incomplete) return;
    157                 addCommon(e, "relation");
    158                 out.println(">");
    159                 for (RelationMember em : e.members) {
    160                         out.print("    <member type='");
    161                         em.member.visit(typeWriteVisitor);
    162                         out.println("' ref='"+getUsedId(em.member)+"' role='" + 
    163                                 XmlWriter.encode(em.role) + "' />");
    164                 }
    165                 addTags(e, "relation", false);
    166         }
    167        
    168 
    169         /**
    170         * Return the id for the given osm primitive (may access the usedId map)
    171         */
    172         private long getUsedId(OsmPrimitive osm) {
    173                 if (osm.id != 0)
    174                         return osm.id;
    175                 if (usedNewIds.containsKey(osm))
    176                         return usedNewIds.get(osm);
    177                 usedNewIds.put(osm, newIdCounter);
    178                 return osmConform ? 0 : newIdCounter--;
    179         }
    180 
    181         private void addTags(OsmPrimitive osm, String tagname, boolean tagOpen) {
    182                 if (osm.keys != null) {
    183                         if (tagOpen)
    184                                 out.println(">");
    185                         for (Entry<String, String> e : osm.keys.entrySet())
    186                                 out.println("    <tag k='"+ XmlWriter.encode(e.getKey()) +
    187                                                 "' v='"+XmlWriter.encode(e.getValue())+ "' />");
    188                         out.println("  </" + tagname + ">");
    189                 } else if (tagOpen)
    190                         out.println(" />");
    191                 else
    192                         out.println("  </" + tagname + ">");
    193         }
    194 
    195         /**
    196         * Add the common part as the form of the tag as well as the XML attributes
    197         * id, action, user, and visible.
    198         */
    199         private void addCommon(OsmPrimitive osm, String tagname) {
    200                 out.print("  <"+tagname+" id='"+getUsedId(osm)+"'");
    201                 if (!osmConform) {
    202                         String action = null;
    203                         if (osm.deleted)
    204                                 action = "delete";
    205                         else if (osm.modified)
    206                                 action = "modify";
    207                         if (action != null)
    208                                 out.print(" action='"+action+"'");
    209                 }
    210                 if (osm.timestamp != null) {
    211                         out.print(" timestamp='"+osm.timestamp+"'");
    212                 }
    213                 // user and visible added with 0.4 API
    214                 if (osm.user != null) {
    215                         out.print(" user='"+XmlWriter.encode(osm.user.name)+"'");
    216                 }
    217                 out.print(" visible='"+osm.visible+"'");
    218                 if (osm.version != -1)
    219                         out.print(" version='"+osm.version+"'");
    220                 if (this.changeset != null && this.changeset.id != 0)
    221                         out.print(" changeset='"+this.changeset.id+"'" );
    222         }
     97                out.print("  <bound note='this tag is deprecated and only provided for backward compatiblity' box='"+
     98                        s.bounds.min.lat()+","+
     99                        s.bounds.min.lon()+","+
     100                        s.bounds.max.lat()+","+
     101                        s.bounds.max.lon()+"' ");
     102                out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
     103                out.print("  <bounds minlat='" +
     104                        s.bounds.min.lat()+"' minlon='"+
     105                        s.bounds.min.lon()+"' maxlat='"+
     106                        s.bounds.max.lat()+"' maxlon='"+
     107                        s.bounds.max.lon()+"' ");
     108                out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
     109            }
     110        }
     111    }
     112
     113    /**
     114    * An output writer for functino output that writes only one specific primitive into
     115    * the xml
     116    */
     117    public static final class Single extends Osm {
     118        private final OsmPrimitive osm;
     119        private final boolean osmConform;
     120        private final Changeset changeset;
     121
     122        public Single(OsmPrimitive osm, boolean osmConform, Changeset changeset) {
     123            this.osm = osm;
     124            this.osmConform = osmConform;
     125            this.changeset = changeset;
     126        }
     127
     128        public void write(PrintWriter out) {
     129            osm.visit(new OsmWriter(out, osmConform, changeset));
     130        }
     131    }
     132
     133    public OsmWriter(PrintWriter out, boolean osmConform, Changeset changeset) {
     134        super(out);
     135        this.osmConform = osmConform;
     136        this.changeset = changeset;
     137    }
     138
     139    public void visit(Node n) {
     140        if (n.incomplete) return;
     141        addCommon(n, "node");
     142        out.print(" lat='"+n.coor.lat()+"' lon='"+n.coor.lon()+"'");
     143        addTags(n, "node", true);
     144    }
     145
     146    public void visit(Way w) {
     147        if (w.incomplete) return;
     148        addCommon(w, "way");
     149        out.println(">");
     150        for (Node n : w.nodes)
     151            out.println("    <nd ref='"+getUsedId(n)+"' />");
     152        addTags(w, "way", false);
     153    }
     154
     155    public void visit(Relation e) {
     156        if (e.incomplete) return;
     157        addCommon(e, "relation");
     158        out.println(">");
     159        for (RelationMember em : e.members) {
     160            out.print("    <member type='");
     161            em.member.visit(typeWriteVisitor);
     162            out.println("' ref='"+getUsedId(em.member)+"' role='" +
     163                XmlWriter.encode(em.role) + "' />");
     164        }
     165        addTags(e, "relation", false);
     166    }
     167
     168
     169    /**
     170    * Return the id for the given osm primitive (may access the usedId map)
     171    */
     172    private long getUsedId(OsmPrimitive osm) {
     173        if (osm.id != 0)
     174            return osm.id;
     175        if (usedNewIds.containsKey(osm))
     176            return usedNewIds.get(osm);
     177        usedNewIds.put(osm, newIdCounter);
     178        return osmConform ? 0 : newIdCounter--;
     179    }
     180
     181    private void addTags(OsmPrimitive osm, String tagname, boolean tagOpen) {
     182        if (osm.keys != null) {
     183            if (tagOpen)
     184                out.println(">");
     185            for (Entry<String, String> e : osm.keys.entrySet())
     186                out.println("    <tag k='"+ XmlWriter.encode(e.getKey()) +
     187                        "' v='"+XmlWriter.encode(e.getValue())+ "' />");
     188            out.println("  </" + tagname + ">");
     189        } else if (tagOpen)
     190            out.println(" />");
     191        else
     192            out.println("  </" + tagname + ">");
     193    }
     194
     195    /**
     196    * Add the common part as the form of the tag as well as the XML attributes
     197    * id, action, user, and visible.
     198    */
     199    private void addCommon(OsmPrimitive osm, String tagname) {
     200        out.print("  <"+tagname+" id='"+getUsedId(osm)+"'");
     201        if (!osmConform) {
     202            String action = null;
     203            if (osm.deleted)
     204                action = "delete";
     205            else if (osm.modified)
     206                action = "modify";
     207            if (action != null)
     208                out.print(" action='"+action+"'");
     209        }
     210        if (osm.timestamp != null) {
     211            out.print(" timestamp='"+osm.timestamp+"'");
     212        }
     213        // user and visible added with 0.4 API
     214        if (osm.user != null) {
     215            out.print(" user='"+XmlWriter.encode(osm.user.name)+"'");
     216        }
     217        out.print(" visible='"+osm.visible+"'");
     218        if (osm.version != -1)
     219            out.print(" version='"+osm.version+"'");
     220        if (this.changeset != null && this.changeset.id != 0)
     221            out.print(" changeset='"+this.changeset.id+"'" );
     222    }
    223223}
  • trunk/src/org/openstreetmap/josm/io/ProgressInputStream.java

    r782 r1169  
    1616public class ProgressInputStream extends InputStream {
    1717
    18         private final InputStream in;
    19         private int readSoFar = 0;
    20         private int lastDialogUpdate = 0;
    21         private final URLConnection connection;
    22         private PleaseWaitDialog pleaseWaitDlg;
     18    private final InputStream in;
     19    private int readSoFar = 0;
     20    private int lastDialogUpdate = 0;
     21    private final URLConnection connection;
     22    private PleaseWaitDialog pleaseWaitDlg;
    2323
    24         public class OsmServerException extends IOException {
    25                 private OsmServerException(String e) {
    26                         super(e);
    27                 }
    28         }
     24    public class OsmServerException extends IOException {
     25        private OsmServerException(String e) {
     26            super(e);
     27        }
     28    }
    2929
    30         public ProgressInputStream(URLConnection con, PleaseWaitDialog pleaseWaitDlg) throws IOException, OsmServerException {
    31                 this.connection = con;
     30    public ProgressInputStream(URLConnection con, PleaseWaitDialog pleaseWaitDlg) throws IOException, OsmServerException {
     31        this.connection = con;
    3232
    33                 try {
    34                         this.in = con.getInputStream();
    35                 } catch (IOException e) {
    36                         if (con.getHeaderField("Error") != null)
    37                                 throw new OsmServerException(tr(con.getHeaderField("Error")));
    38                         throw e;
    39                 }
     33        try {
     34            this.in = con.getInputStream();
     35        } catch (IOException e) {
     36            if (con.getHeaderField("Error") != null)
     37                throw new OsmServerException(tr(con.getHeaderField("Error")));
     38            throw e;
     39        }
    4040
    41                 int contentLength = con.getContentLength();
    42                 this.pleaseWaitDlg = pleaseWaitDlg;
    43                 if (pleaseWaitDlg == null)
    44                         return;
    45                 if (contentLength > 0)
    46                         pleaseWaitDlg.progress.setMaximum(contentLength);
    47                 else
    48                         pleaseWaitDlg.progress.setMaximum(0);
    49                 pleaseWaitDlg.progress.setValue(0);
    50         }
     41        int contentLength = con.getContentLength();
     42        this.pleaseWaitDlg = pleaseWaitDlg;
     43        if (pleaseWaitDlg == null)
     44            return;
     45        if (contentLength > 0)
     46            pleaseWaitDlg.progress.setMaximum(contentLength);
     47        else
     48            pleaseWaitDlg.progress.setMaximum(0);
     49        pleaseWaitDlg.progress.setValue(0);
     50    }
    5151
    52         @Override public void close() throws IOException {
    53                 in.close();
    54         }
     52    @Override public void close() throws IOException {
     53        in.close();
     54    }
    5555
    56         @Override public int read(byte[] b, int off, int len) throws IOException {
    57                 int read = in.read(b, off, len);
    58                 if (read != -1)
    59                         advanceTicker(read);
    60                 return read;
    61         }
     56    @Override public int read(byte[] b, int off, int len) throws IOException {
     57        int read = in.read(b, off, len);
     58        if (read != -1)
     59            advanceTicker(read);
     60        return read;
     61    }
    6262
    63         @Override public int read() throws IOException {
    64                 int read = in.read();
    65                 if (read != -1)
    66                         advanceTicker(1);
    67                 return read;
    68         }
     63    @Override public int read() throws IOException {
     64        int read = in.read();
     65        if (read != -1)
     66            advanceTicker(1);
     67        return read;
     68    }
    6969
    70         /**
    71         * Increase ticker (progress counter and displayed text) by the given amount.
    72         * @param amount
    73         */
    74         private void advanceTicker(int amount) {
    75                 if (pleaseWaitDlg == null)
    76                         return;
     70    /**
     71    * Increase ticker (progress counter and displayed text) by the given amount.
     72    * @param amount
     73    */
     74    private void advanceTicker(int amount) {
     75        if (pleaseWaitDlg == null)
     76            return;
    7777
    78                 if (pleaseWaitDlg.progress.getMaximum() == 0 && connection.getContentLength() != -1)
    79                         pleaseWaitDlg.progress.setMaximum(connection.getContentLength());
     78        if (pleaseWaitDlg.progress.getMaximum() == 0 && connection.getContentLength() != -1)
     79            pleaseWaitDlg.progress.setMaximum(connection.getContentLength());
    8080
    81                 readSoFar += amount;
     81        readSoFar += amount;
    8282
    83                 if (readSoFar / 1024 != lastDialogUpdate) {
    84                         lastDialogUpdate++;
    85                         String progStr = " "+readSoFar/1024+"/";
    86                         progStr += (pleaseWaitDlg.progress.getMaximum()==0) ? "??? KB" : (pleaseWaitDlg.progress.getMaximum()/1024)+" KB";
    87                         pleaseWaitDlg.progress.setValue(readSoFar);
     83        if (readSoFar / 1024 != lastDialogUpdate) {
     84            lastDialogUpdate++;
     85            String progStr = " "+readSoFar/1024+"/";
     86            progStr += (pleaseWaitDlg.progress.getMaximum()==0) ? "??? KB" : (pleaseWaitDlg.progress.getMaximum()/1024)+" KB";
     87            pleaseWaitDlg.progress.setValue(readSoFar);
    8888
    89                         String cur = pleaseWaitDlg.currentAction.getText();
    90                         int i = cur.indexOf(' ');
    91                         if (i != -1)
    92                                 cur = cur.substring(0, i) + progStr;
    93                         else
    94                                 cur += progStr;
    95                         pleaseWaitDlg.currentAction.setText(cur);
    96                 }
    97         }
     89            String cur = pleaseWaitDlg.currentAction.getText();
     90            int i = cur.indexOf(' ');
     91            if (i != -1)
     92                cur = cur.substring(0, i) + progStr;
     93            else
     94                cur += progStr;
     95            pleaseWaitDlg.currentAction.setText(cur);
     96        }
     97    }
    9898}
  • trunk/src/org/openstreetmap/josm/io/XmlWriter.java

    r627 r1169  
    1010/**
    1111 * Helper class to use for xml outputting classes.
    12  * 
     12 *
    1313 * @author imi
    1414 */
    1515public class XmlWriter {
    1616
    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         }
     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    }
    2626
    2727
    28         protected XmlWriter(PrintWriter out) {
    29                 this.out = out;
    30         }
     28    protected XmlWriter(PrintWriter out) {
     29        this.out = out;
     30    }
    3131
    32         /**
    33         * Encode the given string in XML1.0 format.
    34         * Optimized to fast pass strings that don't need encoding (normal case).
    35         */
    36         public static String encode(String unencoded) {
    37                 StringBuilder buffer = null;
    38                 for (int i = 0; i < unencoded.length(); ++i) {
    39                         String encS = XmlWriter.encoding.get(unencoded.charAt(i));
    40                         if (encS != null) {
    41                                 if (buffer == null)
    42                                         buffer = new StringBuilder(unencoded.substring(0,i));
    43                                 buffer.append(encS);
    44                         } else if (buffer != null)
    45                                 buffer.append(unencoded.charAt(i));
    46                 }
    47                 return (buffer == null) ? unencoded : buffer.toString();
    48         }
     32    /**
     33    * Encode the given string in XML1.0 format.
     34    * Optimized to fast pass strings that don't need encoding (normal case).
     35    */
     36    public static String encode(String unencoded) {
     37        StringBuilder buffer = null;
     38        for (int i = 0; i < unencoded.length(); ++i) {
     39            String encS = XmlWriter.encoding.get(unencoded.charAt(i));
     40            if (encS != null) {
     41                if (buffer == null)
     42                    buffer = new StringBuilder(unencoded.substring(0,i));
     43                buffer.append(encS);
     44            } else if (buffer != null)
     45                buffer.append(unencoded.charAt(i));
     46        }
     47        return (buffer == null) ? unencoded : buffer.toString();
     48    }
    4949
    50         /**
    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         }
     50    /**
     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    }
    6868
    69         /**
    70         * The output writer to save the values to.
    71         */
    72         protected final PrintWriter out;
    73         final private static HashMap<Character, String> encoding = new HashMap<Character, String>();
    74         static {
    75                 encoding.put('<', "&lt;");
    76                 encoding.put('>', "&gt;");
    77                 encoding.put('"', "&quot;");
    78                 encoding.put('\'', "&apos;");
    79                 encoding.put('&', "&amp;");
    80                 encoding.put('\n', "&#xA;");
    81                 encoding.put('\r', "&#xD;");
    82                 encoding.put('\t', "&#x9;");
    83         }
     69    /**
     70    * The output writer to save the values to.
     71    */
     72    protected final PrintWriter out;
     73    final private static HashMap<Character, String> encoding = new HashMap<Character, String>();
     74    static {
     75        encoding.put('<', "&lt;");
     76        encoding.put('>', "&gt;");
     77        encoding.put('"', "&quot;");
     78        encoding.put('\'', "&apos;");
     79        encoding.put('&', "&amp;");
     80        encoding.put('\n', "&#xA;");
     81        encoding.put('\r', "&#xD;");
     82        encoding.put('\t', "&#x9;");
     83    }
    8484}
Note: See TracChangeset for help on using the changeset viewer.