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 }