001 // License: GPL. Copyright 2007 by Immanuel Scholz and others
002 package org.openstreetmap.josm.data;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.io.BufferedReader;
007 import java.io.IOException;
008 import java.io.InputStreamReader;
009 import java.io.OutputStreamWriter;
010 import java.io.PrintWriter;
011 import java.io.Reader;
012 import java.io.StringReader;
013 import java.net.HttpURLConnection;
014 import java.net.MalformedURLException;
015 import java.net.URL;
016 import java.net.URLConnection;
017
018 import javax.swing.JOptionPane;
019 import javax.xml.stream.XMLStreamException;
020
021 import org.openstreetmap.josm.Main;
022 import org.openstreetmap.josm.io.OsmConnection;
023 import org.openstreetmap.josm.tools.Base64;
024
025 /**
026 * This class tweak the Preferences class to provide server side preference settings, as example
027 * used in the applet version.
028 *
029 * @author Imi
030 */
031 public class ServerSidePreferences extends Preferences {
032 public static class MissingPassword extends Exception{
033 public String realm;
034 public MissingPassword(String r) {
035 realm = r;
036 }
037 }
038
039 private final Connection connection;
040
041 private class Connection extends OsmConnection {
042 URL serverUrl;
043 public Connection(URL serverUrl) {
044 this.serverUrl = serverUrl;
045 }
046 public String download() throws MissingPassword {
047 try {
048 System.out.println("reading preferences from "+serverUrl);
049 URLConnection con = serverUrl.openConnection();
050 String username = get("applet.username");
051 String password = get("applet.password");
052 if(password.isEmpty() && username.isEmpty()) {
053 con.addRequestProperty("Authorization", "Basic "+Base64.encode(username+":"+password));
054 }
055 con.connect();
056 if(username.isEmpty() && con instanceof HttpURLConnection
057 && ((HttpURLConnection) con).getResponseCode()
058 == HttpURLConnection.HTTP_UNAUTHORIZED) {
059 String t = ((HttpURLConnection) con).getHeaderField("WWW-Authenticate");
060 t = t.replace("Basic realm=\"","").replace("\"","");
061 throw new MissingPassword(t);
062 }
063 BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
064 StringBuilder b = new StringBuilder();
065 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
066 b.append(line);
067 b.append("\n");
068 }
069 if (con instanceof HttpURLConnection) {
070 ((HttpURLConnection) con).disconnect();
071 }
072 return b.toString();
073 } catch (IOException e) {
074 e.printStackTrace();
075 }
076 return null;
077 }
078 public void upload(String s) {
079 try {
080 URL u = new URL(getPreferencesDir());
081 System.out.println("uploading preferences to "+u);
082 HttpURLConnection con = (HttpURLConnection)u.openConnection();
083 String username = get("applet.username");
084 String password = get("applet.password");
085 if(password.isEmpty() && username.isEmpty()) {
086 con.addRequestProperty("Authorization", "Basic "+Base64.encode(username+":"+password));
087 }
088 con.setRequestMethod("POST");
089 con.setDoOutput(true);
090 con.connect();
091 PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream()));
092 out.println(s);
093 out.close();
094 con.getInputStream().close();
095 con.disconnect();
096 JOptionPane.showMessageDialog(
097 Main.parent,
098 tr("Preferences stored on {0}", u.getHost()),
099 tr("Information"),
100 JOptionPane.INFORMATION_MESSAGE
101 );
102 } catch (Exception e) {
103 e.printStackTrace();
104 JOptionPane.showMessageDialog(
105 Main.parent,
106 tr("Could not upload preferences. Reason: {0}", e.getMessage()),
107 tr("Error"),
108 JOptionPane.ERROR_MESSAGE
109 );
110 }
111 }
112 }
113
114 public ServerSidePreferences(URL serverUrl) {
115 Connection connection = null;
116 try {
117 connection = new Connection(new URL(serverUrl+"user/preferences"));
118 } catch (MalformedURLException e) {
119 e.printStackTrace();
120 JOptionPane.showMessageDialog(
121 Main.parent,
122 tr("Could not load preferences from server."),
123 tr("Error"),
124 JOptionPane.ERROR_MESSAGE
125 );
126 }
127 this.connection = connection;
128 }
129
130 @Override public String getPreferencesDir() {
131 return connection.serverUrl.toString();
132 }
133
134 /**
135 * Do nothing on load. Preferences are loaded with download().
136 */
137 @Override public void load() {
138 }
139
140 /**
141 * Do nothing on save. Preferences are uploaded using upload().
142 */
143 @Override public void save() {
144 }
145
146 public void download(String userName, String password) {
147 if (!properties.containsKey("applet.username") && userName != null) {
148 properties.put("applet.username", userName);
149 }
150 if (!properties.containsKey("applet.password") && password != null) {
151 properties.put("applet.password", password);
152 }
153 try {
154 download();
155 } catch (MissingPassword e) {
156 }
157 }
158
159 public boolean download() throws MissingPassword {
160 resetToDefault();
161 String cont = connection.download();
162 if (cont == null) return false;
163 Reader in = new StringReader(cont);
164 boolean res = false;
165 try {
166 fromXML(in);
167 } catch (RuntimeException e) {
168 e.printStackTrace();
169 } catch (XMLStreamException e) {
170 e.printStackTrace();
171 }
172 return res;
173 }
174
175 /**
176 * Use this instead of save() for the ServerSidePreferences, since uploads
177 * are costly while save is called often.
178 *
179 * This is triggered by an explicit menu option.
180 */
181 public void upload() {
182 connection.upload(toXML(true));
183 }
184 }