Commit 170b20cc authored by Christian Schudt's avatar Christian Schudt

Language info should be in the Session, not in the Connection

I feel the language (the stream's "xml:lang" attribute) should be in the Session interface rather than the Connection (similar as the stream id), because it's unrelated to the session's transport.

The HttpSession already did that.

Otherwise the used language is not easy to retrieve, e.g. when using SessionManager to get the session and OF-208 is hard to solve.

Alternatively we can expose the Connection in the Session interface, but this approach feels wrong to me.

Also use `java.util.Locale` rather than String, because it better reflects what can be in `xml:lang` (it can also have country codes, e.g. "de-CH")
parent 21f57aa5
......@@ -268,21 +268,6 @@ public interface Connection extends Closeable {
*/
public void setXMPPVersion(int majorVersion, int minorVersion);
/**
* Returns the language code that should be used for this connection
* (e.g. "en").
*
* @return the language code for the connection.
*/
public String getLanguage();
/**
* Sets the language code that should be used for this connection (e.g. "en").
*
* @param language the language code.
*/
public void setLanaguage(String language);
/**
* Returns true if the connection is using compression.
*
......
......@@ -30,6 +30,7 @@ import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
......@@ -331,10 +332,11 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
* stream ID.
*
* @param conn the connection to create the session from.
* @param language The language to use for the new session.
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn) {
return createClientSession(conn, nextStreamID());
public LocalClientSession createClientSession(Connection conn, Locale language) {
return createClientSession(conn, nextStreamID(), language);
}
/**
......@@ -345,10 +347,22 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn, StreamID id) {
return createClientSession( conn, id, null);
}
/**
* Creates a new <tt>ClientSession</tt> with the specified streamID.
*
* @param conn the connection to create the session from.
* @param id the streamID to use for the new session.
* @param language The language to use for the new session.
* @return a newly created session.
*/
public LocalClientSession createClientSession(Connection conn, StreamID id, Locale language) {
if (serverName == null) {
throw new IllegalStateException("Server not initialized");
}
LocalClientSession session = new LocalClientSession(serverName, conn, id);
LocalClientSession session = new LocalClientSession(serverName, conn, id, language);
conn.init(session);
// Register to receive close notification on this session so we can
// remove and also send an unavailable presence if it wasn't
......@@ -362,13 +376,20 @@ public class SessionManager extends BasicModule implements ClusterEventListener/
return session;
}
public HttpSession createClientHttpSession(long rid, InetAddress address, StreamID id, HttpConnection connection)
/**
* Creates a new <tt>ClientSession</tt> with the specified streamID.
*
* @param conn the connection to create the session from.
* @param id the streamID to use for the new session.
* @return a newly created session.
*/
public HttpSession createClientHttpSession(long rid, InetAddress address, StreamID id, HttpConnection connection, Locale language)
throws UnauthorizedException {
if (serverName == null) {
throw new UnauthorizedException("Server not initialized");
}
PacketDeliverer backupDeliverer = server.getPacketDeliverer();
HttpSession session = new HttpSession(backupDeliverer, serverName, address, id, rid, connection);
HttpSession session = new HttpSession(backupDeliverer, serverName, address, id, rid, connection, language);
Connection conn = session.getConnection();
conn.init(session);
conn.registerCloseListener(clientSessionListener, session);
......
......@@ -32,6 +32,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
......@@ -131,8 +132,8 @@ public class HttpSession extends LocalClientSession {
};
public HttpSession(PacketDeliverer backupDeliverer, String serverName, InetAddress address,
StreamID streamID, long rid, HttpConnection connection) {
super(serverName, new HttpVirtualConnection(address), streamID);
StreamID streamID, long rid, HttpConnection connection, Locale language) {
super(serverName, new HttpVirtualConnection(address), streamID, language);
this.isClosed = false;
this.lastActivity = System.currentTimeMillis();
this.lastRequestID = rid;
......@@ -249,24 +250,6 @@ public class HttpSession extends LocalClientSession {
return hold;
}
/**
* Sets the language this session is using.
*
* @param language the language this session is using.
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* Returns the language this session is using.
*
* @return the language this session is using.
*/
public String getLanguage() {
return language;
}
/**
* Sets the max interval within which a client can send polling requests. If more than one
* request occurs in the interval the session will be terminated.
......
......@@ -21,6 +21,7 @@ package org.jivesoftware.openfire.http;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Locale;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
......@@ -181,7 +182,7 @@ public class HttpSessionManager {
version = "1.5";
}
HttpSession session = createSession(connection.getRequestId(), address, connection);
HttpSession session = createSession(connection.getRequestId(), address, connection, Locale.forLanguageTag(language));
session.setWait(Math.min(wait, getMaxWait()));
session.setHold(hold);
session.setSecure(connection.isSecure());
......@@ -197,9 +198,6 @@ public class HttpSessionManager {
}
session.resetInactivityTimeout();
// Store language and version information in the connection.
session.setLanguage(language);
String [] versionString = version.split("\\.");
session.setMajorVersion(Integer.parseInt(versionString[0]));
session.setMinorVersion(Integer.parseInt(versionString[1]));
......@@ -296,11 +294,11 @@ public class HttpSessionManager {
return JiveGlobals.getIntProperty("xmpp.httpbind.client.idle.polling", 60);
}
private HttpSession createSession(long rid, InetAddress address, HttpConnection connection) throws UnauthorizedException {
private HttpSession createSession(long rid, InetAddress address, HttpConnection connection, Locale language) throws UnauthorizedException {
// Create a ClientSession for this user.
StreamID streamID = SessionManager.getInstance().nextStreamID();
// Send to the server that a new client session has been created
HttpSession session = sessionManager.createClientHttpSession(rid, address, streamID, connection);
HttpSession session = sessionManager.createClientHttpSession(rid, address, streamID, connection, language);
// Register that the new session is associated with the specified stream ID
sessionMap.put(streamID.getID(), session);
session.addSessionCloseListener(sessionListener);
......
......@@ -396,21 +396,6 @@ public class SocketConnection implements Connection {
this.minorVersion = minorVersion;
}
@Override
public String getLanguage() {
return language;
}
/**
* Sets the language code that should be used for this connection (e.g. "en").
*
* @param language the language code.
*/
@Override
public void setLanaguage(String language) {
this.language = language;
}
@Override
public boolean isFlashClient() {
return flashClient;
......
......@@ -269,7 +269,7 @@ abstract class SocketReadingMode {
sb.append("\" id=\"");
sb.append(socketReader.session.getStreamID().toString());
sb.append("\" xml:lang=\"");
sb.append(socketReader.connection.getLanguage());
sb.append(socketReader.session.getLanguage());
sb.append("\" version=\"");
sb.append(Session.MAJOR_VERSION).append('.').append(Session.MINOR_VERSION);
sb.append("\">");
......
......@@ -580,7 +580,7 @@ public abstract class StanzaHandler {
sb.append("\" id=\"");
sb.append(session.getStreamID());
sb.append("\" xml:lang=\"");
sb.append(connection.getLanguage());
sb.append(session.getLanguage());
sb.append("\" version=\"");
sb.append(Session.MAJOR_VERSION).append('.').append(Session.MINOR_VERSION);
sb.append("\">");
......
......@@ -55,12 +55,6 @@ public abstract class VirtualConnection implements Connection {
private AtomicReference<State> state = new AtomicReference<State>(State.OPEN);
@Override
public String getLanguage() {
// Information not available. Return any value. This is not actually used.
return null;
}
@Override
public int getMajorXMPPVersion() {
// Information not available. Return any value. This is not actually used.
......@@ -133,11 +127,6 @@ public abstract class VirtualConnection implements Connection {
//Ignore
}
@Override
public void setLanaguage(String language) {
//Ignore
}
@Override
public void setCompressionPolicy(CompressionPolicy compressionPolicy) {
//Ignore
......
......@@ -477,16 +477,6 @@ public class NIOConnection implements Connection {
this.minorVersion = minorVersion;
}
@Override
public String getLanguage() {
return language;
}
@Override
public void setLanaguage(String language) {
this.language = language;
}
@Override
public boolean isCompressed() {
return ioSession.getFilterChain().contains(COMPRESSION_FILTER_NAME);
......
......@@ -24,6 +24,7 @@ import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
......@@ -211,7 +212,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
// Default language is English ("en").
String language = "en";
Locale language = Locale.forLanguageTag("en");
// Default to a version of "0.0". Clients written before the XMPP 1.0 spec may
// not report a version in which case "0.0" should be assumed (per rfc3920
// section 4.4.1).
......@@ -219,7 +220,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
int minorVersion = 0;
for (int i = 0; i < xpp.getAttributeCount(); i++) {
if ("lang".equals(xpp.getAttributeName(i))) {
language = xpp.getAttributeValue(i);
language = Locale.forLanguageTag(xpp.getAttributeValue(i));
}
if ("version".equals(xpp.getAttributeName(i))) {
try {
......@@ -248,8 +249,6 @@ public class LocalClientSession extends LocalSession implements ClientSession {
}
}
// Store language and version information in the connection.
connection.setLanaguage(language);
connection.setXMPPVersion(majorVersion, minorVersion);
// Indicate the TLS policy to use for this connection
......@@ -278,7 +277,7 @@ public class LocalClientSession extends LocalSession implements ClientSession {
connection.setCompressionPolicy(getCompressionPolicy());
// Create a ClientSession for this user.
LocalClientSession session = SessionManager.getInstance().createClientSession(connection);
LocalClientSession session = SessionManager.getInstance().createClientSession(connection, language);
// Build the start packet response
StringBuilder sb = new StringBuilder(200);
......@@ -555,8 +554,8 @@ public class LocalClientSession extends LocalSession implements ClientSession {
* @param connection The connection we are proxying.
* @param streamID unique identifier of this session.
*/
public LocalClientSession(String serverName, Connection connection, StreamID streamID) {
super(serverName, connection, streamID);
public LocalClientSession(String serverName, Connection connection, StreamID streamID, Locale language) {
super(serverName, connection, streamID, language);
// Set an unavailable initial presence
presence = new Presence();
presence.setType(Presence.Type.unavailable);
......
......@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.jivesoftware.openfire.Connection;
......@@ -187,7 +188,7 @@ public class LocalComponentSession extends LocalSession implements ComponentSess
}
public LocalComponentSession(String serverName, Connection conn, StreamID id) {
super(serverName, conn, id);
super(serverName, conn, id, Locale.getDefault());
}
@Override
......
......@@ -17,6 +17,7 @@
package org.jivesoftware.openfire.session;
import java.util.Collection;
import java.util.Locale;
import org.dom4j.Element;
import org.jivesoftware.openfire.Connection;
......@@ -197,7 +198,7 @@ public class LocalConnectionMultiplexerSession extends LocalSession implements C
}
public LocalConnectionMultiplexerSession(String serverName, Connection connection, StreamID streamID) {
super(serverName, connection, streamID);
super(serverName, connection, streamID, Locale.getDefault());
}
@Override
......
......@@ -8,6 +8,8 @@ import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.xmpp.packet.Packet;
import java.util.Locale;
/**
* @author dwd
*
......@@ -19,7 +21,7 @@ public class LocalServerSession extends LocalSession implements ServerSession {
public LocalServerSession(String serverName, Connection connection,
StreamID streamID) {
super(serverName, connection, streamID);
super(serverName, connection, streamID, Locale.getDefault());
}
/* (non-Javadoc)
......
......@@ -20,6 +20,7 @@ import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.net.ssl.SSLSession;
......@@ -100,14 +101,17 @@ public abstract class LocalSession implements Session {
*/
protected final StreamManager streamManager;
private final Locale language;
/**
* Creates a session with an underlying connection and permission protection.
*
* @param serverName domain of the XMPP server where the new session belongs.
* @param connection The connection we are proxying.
* @param streamID unique identifier for this session.
* @param language The language to use for this session.
*/
public LocalSession(String serverName, Connection connection, StreamID streamID) {
public LocalSession(String serverName, Connection connection, StreamID streamID, Locale language) {
if (connection == null) {
throw new IllegalArgumentException("connection must not be null");
}
......@@ -118,6 +122,7 @@ public abstract class LocalSession implements Session {
this.address = new JID(null, serverName, id, true);
this.sessionManager = SessionManager.getInstance();
this.streamManager = new StreamManager(conn);
this.language = language;
}
/**
......@@ -470,4 +475,8 @@ public abstract class LocalSession implements Session {
streamManager.setEnabled(true);
}
@Override
public final Locale getLanguage() {
return language;
}
}
......@@ -28,6 +28,7 @@ import org.xmpp.packet.Packet;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Locale;
/**
* The session represents a connection between the server and a client (c2s) or
......@@ -212,4 +213,12 @@ public interface Session extends RoutableChannelHandler {
* @return cipher suite name.
*/
public String getCipherSuiteName();
/**
* Returns the language code that should be used for this connection
* (e.g. "en").
*
* @return the language code for the connection.
*/
Locale getLanguage();
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ package org.jivesoftware.openfire.plugin.session;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.util.Date;
import java.util.Locale;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.StreamID;
......@@ -211,6 +212,11 @@ public abstract class RemoteSession implements Session {
}
}
@Override
public final Locale getLanguage() {
return Locale.getDefault();
}
/**
* Simple implementation of the StreamID interface to hold the stream ID of
* the surrogated session.
......
......@@ -17,6 +17,7 @@ package org.jivesoftware.openfire.websocket;
import java.io.IOException;
import java.io.StringReader;
import java.util.Locale;
import java.util.TimerTask;
import org.apache.commons.pool2.impl.GenericObjectPool;
......@@ -244,7 +245,7 @@ public class XmppWebSocket {
String host = stanza.attributeValue("to");
StreamError streamError = null;
Locale language = Locale.forLanguageTag(stanza.attributeValue("lang", "en"));
if (STREAM_FOOTER.equals(stanza.getName())) {
// an error occurred while setting up the session
closeStream(null);
......@@ -261,12 +262,12 @@ public class XmppWebSocket {
streamError = new StreamError(StreamError.Condition.host_unknown);
Log.warn("Closing session due to incorrect hostname in stream header. Host: " + host);
} else {
xmppSession = SessionManager.getInstance().createClientSession(wsConnection);
xmppSession = SessionManager.getInstance().createClientSession(wsConnection, language);
xmppSession.setSessionData("ws", Boolean.TRUE);
}
if (streamError == null) {
openStream(stanza.attributeValue("lang", "en"), stanza.attributeValue("from"));
openStream(language.toLanguageTag(), stanza.attributeValue("from"));
configureStream();
} else {
closeStream(streamError);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment