// License: GPL. Copyright 2007 by Immanuel Scholz and others
package org.openstreetmap.josm.data;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.io.OsmConnection;
import org.openstreetmap.josm.io.OsmTransferException;
import org.openstreetmap.josm.io.XmlWriter;
import org.openstreetmap.josm.tools.Base64;
import org.openstreetmap.josm.tools.XmlObjectParser;
/**
* This class tweak the Preferences class to provide server side preference settings, as example
* used in the applet version.
*
* @author Imi
*/
public class ServerSidePreferences extends Preferences {
static private final Logger logger = Logger.getLogger(ServerSidePreferences.class.getName());
private final Connection connection;
private class Connection extends OsmConnection {
URL serverUrl;
public Connection(URL serverUrl) {
this.serverUrl = serverUrl;
}
public String download() {
try {
System.out.println("reading preferences from "+serverUrl);
URLConnection con = serverUrl.openConnection();
if (con instanceof HttpURLConnection) {
addAuth((HttpURLConnection) con);
}
con.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder b = new StringBuilder();
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
b.append(line);
b.append("\n");
}
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).disconnect();
}
return b.toString();
} catch (IOException e) {
e.printStackTrace();
} catch(OsmTransferException e) {
e.printStackTrace();
}
return null;
}
public void upload(String s) {
try {
URL u = new URL(getPreferencesDir());
System.out.println("uploading preferences to "+u);
HttpURLConnection con = (HttpURLConnection)u.openConnection();
// FIXME:
// - doesn't work if CredentialManager isn't JosmPreferencesCredentialManager
// - doesn't work for OAuth
con.addRequestProperty("Authorization", "Basic "+Base64.encode(get("osm-server.username")+":"+get("osm-server.password")));
con.setRequestMethod("POST");
con.setDoOutput(true);
con.connect();
PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream()));
out.println(s);
out.close();
con.getInputStream().close();
con.disconnect();
JOptionPane.showMessageDialog(
Main.parent,
tr("Preferences stored on {0}", u.getHost()),
tr("Information"),
JOptionPane.INFORMATION_MESSAGE
);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
Main.parent,
tr("Could not upload preferences. Reason: {0}", e.getMessage()),
tr("Error"),
JOptionPane.ERROR_MESSAGE
);
}
}
}
public ServerSidePreferences(URL serverUrl) {
Connection connection = null;
try {
connection = new Connection(new URL(serverUrl+"user/preferences"));
} catch (MalformedURLException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
Main.parent,
tr("Could not load preferences from server."),
tr("Error"),
JOptionPane.ERROR_MESSAGE
);
}
this.connection = connection;
}
@Override public String getPreferencesDir() {
return connection.serverUrl.toString();
}
/**
* Do nothing on load. Preferences are loaded with download().
*/
@Override public void load() {
}
/**
* Do nothing on save. Preferences are uploaded using upload().
*/
@Override public void save() {
}
public static class Prop {
public String key;
public String value;
}
public void download(String userName, String password) {
resetToDefault();
if (!properties.containsKey("osm-server.username") && userName != null) {
properties.put("osm-server.username", userName);
}
if (!properties.containsKey("osm-server.password") && password != null) {
properties.put("osm-server.password", password);
}
String cont = connection.download();
if (cont == null) return;
Reader in = new StringReader(cont);
try {
XmlObjectParser.Uniform<Prop> parser = new XmlObjectParser.Uniform<Prop>(in, "tag", Prop.class);
for (Prop p : parser) {
properties.put(p.key, p.value);
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
/**
* Use this instead of save() for the ServerSidePreferences, since uploads
* are costly while save is called often.
*
* This is triggered by an explicit menu option.
*/
public void upload() {
StringBuilder b = new StringBuilder("<preferences>\n");
for (Entry<String, String> p : properties.entrySet()) {
if (p.getKey().equals("osm-server.password")) {
continue; // do not upload password. It would get stored in plain!
}
b.append("<tag key='");
b.append(XmlWriter.encode(p.getKey()));
b.append("' value='");
b.append(XmlWriter.encode(p.getValue()));
b.append("' />\n");
}
b.append("</preferences>");
connection.upload(b.toString());
}
@Override public Collection<Bookmark> loadBookmarks() {
URL url = null;
try {
Collection<Bookmark> bookmarks;
bookmarks = new LinkedList<Bookmark>();
url = new URL("http://"+connection.serverUrl.getHost()+"/josm/bookmarks");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
for (String line = in.readLine(); line != null; line = in.readLine()) {
StringTokenizer st = new StringTokenizer(line, ",");
if (st.countTokens() != 5) {
System.err.println(tr("Error: Unexpected line ''{0}'' in bookmark list from server",line));
continue;
}
Bookmark b = new Bookmark();
b.setName(st.nextToken());
double[] values= new double[4];
for (int i = 0; i < 4; ++i) {
String token = st.nextToken();
try {
values[i] = Double.parseDouble(token);
} catch(NumberFormatException e) {
System.err.println(tr("Error: Illegal double value ''{0}'' on line ''{1}'' in bookmark list from server",token,line));
continue;
}
}
b.setArea(new Bounds(values));
bookmarks.add(b);
}
in.close();
return bookmarks;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(SecurityException e) {
e.printStackTrace();
logger.warning(tr("Failed to load bookmarks from ''{0}'' for security reasons. Exception was: {1}", url == null ? "null" : url.toExternalForm(), e.toString()));
}
return Collections.emptyList();
}
@Override public void saveBookmarks(Collection<Bookmark> bookmarks) {
}
}