source: josm/src/org/openstreetmap/josm/io/OsmServerWriter.java@ 298

Last change on this file since 298 was 298, checked in by imi, 17 years ago
  • added license description to head of each source file
File size: 6.6 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedReader;
7import java.io.ByteArrayOutputStream;
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.InputStreamReader;
11import java.io.OutputStream;
12import java.net.HttpURLConnection;
13import java.net.URL;
14import java.net.UnknownHostException;
15import java.util.Collection;
16import java.util.LinkedList;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.Segment;
22import org.openstreetmap.josm.data.osm.Way;
23import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
24import org.openstreetmap.josm.data.osm.visitor.Visitor;
25import org.xml.sax.SAXException;
26
27/**
28 * Class that uploades all changes to the osm server.
29 *
30 * This is done like this: - All objects with id = 0 are uploaded as new, except
31 * those in deleted, which are ignored - All objects in deleted list are
32 * deleted. - All remaining objects with modified flag set are updated.
33 *
34 * This class implements visitor and will perform the correct upload action on
35 * the visited element.
36 *
37 * @author imi
38 */
39public class OsmServerWriter extends OsmConnection implements Visitor {
40
41 /**
42 * This list contain all sucessfull processed objects. The caller of
43 * upload* has to check this after the call and update its dataset.
44 *
45 * If a server connection error occours, this may contain fewer entries
46 * than where passed in the list to upload*.
47 */
48 public Collection<OsmPrimitive> processed;
49
50 /**
51 * Whether the operation should be aborted as soon as possible.
52 */
53 private boolean cancel = false;
54
55 /**
56 * Send the dataset to the server. Ask the user first and does nothing if he
57 * does not want to send the data.
58 */
59 public void uploadOsm(Collection<OsmPrimitive> list) throws SAXException {
60 processed = new LinkedList<OsmPrimitive>();
61 initAuthentication();
62
63 Main.pleaseWaitDlg.progress.setMaximum(list.size());
64 Main.pleaseWaitDlg.progress.setValue(0);
65
66 NameVisitor v = new NameVisitor();
67 try {
68 for (OsmPrimitive osm : list) {
69 if (cancel)
70 return;
71 osm.visit(v);
72 Main.pleaseWaitDlg.currentAction.setText(tr("Upload {0} {1} ({2})...", tr(v.className), v.name, osm.id));
73 osm.visit(this);
74 Main.pleaseWaitDlg.progress.setValue(Main.pleaseWaitDlg.progress.getValue()+1);
75 }
76 } catch (RuntimeException e) {
77 e.printStackTrace();
78 throw new SAXException("An error occoured: "+e.getMessage());
79 }
80 }
81
82 /**
83 * Upload a single node.
84 */
85 public void visit(Node n) {
86 if (n.id == 0 && !n.deleted && n.get("created_by") == null) {
87 n.put("created_by", "JOSM");
88 sendRequest("PUT", "node", n, true);
89 } else if (n.deleted) {
90 sendRequest("DELETE", "node", n, false);
91 } else {
92 sendRequest("PUT", "node", n, true);
93 }
94 processed.add(n);
95 }
96
97 /**
98 * Upload a segment (without the nodes).
99 */
100 public void visit(Segment ls) {
101 if (ls.id == 0 && !ls.deleted && ls.get("created_by") == null) {
102 ls.put("created_by", "JOSM");
103 sendRequest("PUT", "segment", ls, true);
104 } else if (ls.deleted) {
105 sendRequest("DELETE", "segment", ls, false);
106 } else {
107 sendRequest("PUT", "segment", ls, true);
108 }
109 processed.add(ls);
110 }
111
112 /**
113 * Upload a whole way with the complete segment id list.
114 */
115 public void visit(Way w) {
116 if (w.id == 0 && !w.deleted && w.get("created_by") == null) {
117 w.put("created_by", "JOSM");
118 sendRequest("PUT", "way", w, true);
119 } else if (w.deleted) {
120 sendRequest("DELETE", "way", w, false);
121 } else {
122 sendRequest("PUT", "way", w, true);
123 }
124 processed.add(w);
125 }
126
127 /**
128 * Read a long from the input stream and return it.
129 */
130 private long readId(InputStream inputStream) throws IOException {
131 BufferedReader in = new BufferedReader(new InputStreamReader(
132 inputStream));
133 String s = in.readLine();
134 if (s == null)
135 return 0;
136 try {
137 return Long.parseLong(s);
138 } catch (NumberFormatException e) {
139 return 0;
140 }
141 }
142
143 /**
144 * Send the request. The objects id will be replaced if it was 0 before
145 * (on add requests).
146 *
147 * @param requestMethod The http method used when talking with the server.
148 * @param urlSuffix The suffix to add at the server url.
149 * @param osm The primitive to encode to the server.
150 * @param addBody <code>true</code>, if the whole primitive body should be added.
151 * <code>false</code>, if only the id is encoded.
152 */
153 private void sendRequest(String requestMethod, String urlSuffix,
154 OsmPrimitive osm, boolean addBody) {
155 try {
156 String version = Main.pref.get("osm-server.version", "0.4");
157 URL url = new URL(
158 Main.pref.get("osm-server.url") +
159 "/" + version +
160 "/" + urlSuffix +
161 "/" + ((version.equals("0.4") && osm.id==0) ? "create":osm.id));
162 System.out.println("upload to: "+url);
163 activeConnection = (HttpURLConnection)url.openConnection();
164 activeConnection.setConnectTimeout(15000);
165 activeConnection.setRequestMethod(requestMethod);
166 if (addBody)
167 activeConnection.setDoOutput(true);
168 activeConnection.connect();
169
170 if (addBody) {
171 OutputStream out = activeConnection.getOutputStream();
172 OsmWriter.output(out, new OsmWriter.Single(osm, true));
173 out.close();
174 }
175
176 int retCode = activeConnection.getResponseCode();
177 if (retCode == 200 && osm.id == 0)
178 osm.id = readId(activeConnection.getInputStream());
179 System.out.println("got return: "+retCode+" with id "+osm.id);
180 String retMsg = activeConnection.getResponseMessage();
181 activeConnection.disconnect();
182 if (retCode == 410 && requestMethod.equals("DELETE"))
183 return; // everything fine.. was already deleted.
184 if (retCode != 200) {
185 // Look for a detailed error message from the server
186 if (activeConnection.getHeaderField("Error") != null)
187 retMsg += "\n" + activeConnection.getHeaderField("Error");
188
189 // Report our error
190 ByteArrayOutputStream o = new ByteArrayOutputStream();
191 OsmWriter.output(o, new OsmWriter.Single(osm, true));
192 System.out.println(new String(o.toByteArray(), "UTF-8").toString());
193 throw new RuntimeException(retCode+" "+retMsg);
194 }
195 } catch (UnknownHostException e) {
196 throw new RuntimeException(tr("Unknown host")+": "+e.getMessage(), e);
197 } catch (Exception e) {
198 if (cancel)
199 return; // assume cancel
200 if (e instanceof RuntimeException)
201 throw (RuntimeException)e;
202 throw new RuntimeException(e.getMessage(), e);
203 }
204 }
205}
Note: See TracBrowser for help on using the repository browser.